Assign variants to user

Assuming you have already filtered out any irrelevant A/B tests for a given page, it's now time to assign variants of the relevant A/B tests for the page to the user at hand.

Assume you have the following running A/B tests (the filters object has been omitted for brevity, and ids are shown as human readable):

[
    {
      "id": "ab-test-1",
      "variations":[
         {
            "id": "variant-a",
            "weight":50
         },
         {
            "id": "variant-b",
            "weight":50
         },
      ]
    },
    {
      "id": "ab-test-2",
      "variations":[
         {
            "id": "variant-a",
            "weight":20
         },
         {
            "id": "variant-b",
            "weight":30
         },
         {
            "id": "variant-c",
            "weight":50
         }
      ]
    },
]

For the above example, the following things need to be considered:

  • Every user should have a variant assigned for each of the two A/B tests. This means there's a total of six combinations which can occur. Adding more tests exponentially increases the number of combinations available, thus the filtering we did in the previous step is extremely important.

  • The user should be assigned a variant from ab-test-1 with an equal chance of getting variant-a or variant-b as their weight distribution is the same.

  • The user should be assigned a variant from ab-test-2 with a higher chance of getting variant-c as it has the biggest weight.

  • If the total among the weights does not equal 100, there's a chance equal to the difference between 100 and total that no variant will be applied, and the user will be shown the default or standard version of the page. In this case they are equal to 100.

  • The same user should always be assigned the same variants in order to ensure consistency.

Given the above considerations we need to ensure that the variant selection is fair and adheres to the weights provided, and that the same user always gets the same variant. To do this, we can use hashing. By hashing the session id of the user which should be stored and thus always the same, and the id of the A/B test we're picking variants for, we will always get the same value. This ensures consistency for the user. Since both ids are completely randomized, the hash value will also be random, thus by taking the remainder when dividing with 100, we get a percentile value which we can then use to pick the variant based on their weights. With a large number of users, and the randomization mentioned, the test will achieve the appropriate traffic split configured through the A/B test variant weights. Consider the following Java snippet below:

import com.google.common.hash.Hashing; // The hashing library in question

List<String> getAbTestsAndVariantsForSessionId(List<RunningAbTest> runningABTests, String sessionId) {
    ArrayList<String> selections = new ArrayList<>();
    for (RunningAbTest abTest : runningABTests) { // for every running AB test
        long percentile = Hashing.murmur3_32().hashUnencodedChars(sessionId + "#" + abTest.getId()).padToLong() % 100; //this is a JAVA implementation of the hashing algorithm to calculate the percentile. The session id and AB test id should be joined by "#"
        List<RunningAbTestVariant> variations = abTest.getVariations(); // the list of available variations for the given AB test
        int acc = 0; // start by setting the limit to 0
        for (RunningAbTestVariant variant : variations) {
            acc += variant.getWeight(); // add the weight of the current variation to the limit and check whether the percentile is below that target number. If yes, select the variant and stop. If not, repeat until it's carried out.
            if (acc > percentile) {
                selections.add(abTest.getId() + ":" + variant.getId()); // join the test id with the variant id to conform to the format defined in the "Calling FAS with A/B variant information" section i.e. "id-of-test:id-of-variant-in-test"
                break;
            }
        }
    return selections; // return a list of all variants selected for the given user
}

Hint: If you need more information about the session id, check out the identities section here.

As you can see from the code the important things to note are:

  • the selection for a given test needs to follow the ab-test-id:variant-id format, or for example: ab-test-1:variant-b .

  • The string to be hashed should be equal to {session-id}#{ab-test-id} or a # joined string of both ids.

  • The hashing algorithm used should be MurmurHash3 . You should be able to find as suitable implementation in any language.

Everything mentioned in this section is also covered via the SDK.

Once you have all of the necessary selections for the user in the format ab-test-id:variant-id you can join them together in a single string with the semicolon ; symbol, in the format selection-1;selection-2 or for a complete example using the running A/B tests in our example response: ab-test-1:variant-b;ab-test-2:variantc. This value can then be used in the fh_abtests parameter to request the exact version of the page we want. More on that below.

pageRequest variant for page

Last updated