ab-tests
Configuration

Configuration

To start A/B testing, you need to create middleware by calling the createMiddleware function.

The function needs to be passed a list of tests (tests) and the life time of the results cookie (cookieLifeTime, in seconds):

middleware.ts
import { type Test } from '@nimpl/ab-tests/dist/lib/types/tests';
import { createMiddleware } from '@nimpl/ab-tests';
 
const tests: Test[] = [
  {
    id: 'some-id',
    source: '/',
    variants: [
      {
        weight: 0.5,
        destination: '/'
      },
      {
        weight: 0.5,
        destination: '/page-2'
      }
    ],
  }
]
 
export const middleware = createMiddleware({ tests, cookieLifeTime: 72400 });

How does this work

  1. The middleware will find a suitable test for which the request will match the given instructions.

  2. If the test is found, a nimpl_ab cookie will be added with a session lifetime (if cookieLifeTime is set - with a lifetime specified in this option).

  3. Upon repeated requests, it will be checked whether the user still matches the test that was previously passed (considering the ignoreOnNextRequests option). If yes - the user will see the previously dropped version, otherwise - will try to participate in other tests.

Important

If cookieLifeTime is not set - the user may not stop being a participant in the A/B test after closing the tab or browser.

A session may not end even after closing the browser and rebooting the system, depending on the browser and its settings.

Test description

Each test is described by the following keys:

id - identifier of the current test, can be set to anything;

source - the path the test will follow;

has - array of rules that should be fulfilled for the user’s request (more about rule description);

missing - array of rules that should not be fulfilled for the user’s request (more about rule description);

variants - array of possible variants of the current test (more about variants).

Rule description

The user’s request data are checked in accordance with the rules. The principles of the rules are similar to the rules of next.js.

Each rule may contain the following keys:

type - the type of rule. Options: header, cookie, host, query;

key - the key from the selected type to match against;

value - the value that will be checked for the given key. If not specified - any value will be correct;

ignoreOnNextRequests - ignore the rule when the test participant repeats the visit to the test page.

Variant

The test can have as many options as you like. The main condition is that the total probability of the options falling out should not exceed 1.

Each option is an object with keys:

destination - the path where the option is located;

weight - probability of the option being given (from 0 to 1);

type - variant type - rewrite or redirect. Accordingly, when the option is triggered, either a rewrite will be performed or a redirect to the specified page will occur;

status - response status when variant drops out.

Dynamic Data

Rules, just like in next.js, support dynamic data.

But, unlike next.js, this only works through regular expression variables (f.e. (?<param>.*)).

Dynamic data can be obtained from source or from value of the rules. Then they can be embedded in destination tests:

{
  id: 'some-id',
  source: '/en-(?<country>de|fr|it)',
  has: [
    {
      type: 'query',
      key: 'ref',
      value: 'utm_(?<ref>moogle|daybook)',
    }
  ],
  variants: [
    {
      weight: 0.5,
      destination: '/en-:country/:ref'
    },
    {
      weight: 0.5,
      destination: '/en-:country/:ref/new'
    }
  ],
}