> For the complete documentation index, see [llms.txt](https://fredhopper.gitbook.io/product-discovery/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://fredhopper.gitbook.io/product-discovery/a-b-testing-for-fhr/integration-steps-for-a-caching-solution/manual-a-b-tests-integration/assign-variants-to-user.md).

# 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**):

```javascript
[
    {
      "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:

{% tabs %}
{% tab title="Java" %}

```java
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
}
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const MurmurHash3 = require('imurmurhash'); // The hashing library in question

const getAbTestsAndVariantsForSessionId = (runningAbTests, sessionId) => {
    const selections = [];
    runningAbTests.forEach(abTest => { // for every running AB test
        const percentile = MurmurHash3(sessionId + "#" + abTest.id).result() % 100; //this is the hashing algorithm to calculate the percentile. The session id and AB test id should be joined by "#"
        const variations = abTest.variations; // the list of available variations for the given AB test
        let acc = 0; // start by setting the limit to 0
        for(let variation of variations) {
            acc += variation.weight; // 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.push(abTest.id + ":" + variation.id); // 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
}
```

{% endtab %}

{% tab title="PHP" %}

```php
// you will need php 8.1

function getAbTestsAndVariantsForSessionId($runningAbTests, $sessionId) {
    $selections = [];
    foreach($runningAbTests as $abTest) { // for every running AB test
        $percentile = hash('murmur3a', $sessionId . "#" . $abTest['id']) % 100; //this is the hashing algorithm to calculate the percentile. The session id and AB test id should be joined by "#"
        $variations = $abTest['variations']; // the list of available variations for the given AB test
        $acc = 0; // start by setting the limit to 0
        foreach($variations as $variation) {
            $acc += $variation['weight']; // 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) {
                array_push($selections,$abTest['id'] . ":" . $variation['id']); // 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
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Hint:** If you need more information about the **session** **id**, check out the identities section [here](https://github.com/Attraqt/cadp-doc/tree/5a05211e39bae3b80322f49dbecbab178663140c/setting-up/managing-identities/README.md).
{% endhint %}

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.

{% hint style="info" %}
Everything mentioned in this section is also covered via the **SDK.**
{% endhint %}

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.

{% content-ref url="/pages/Zauokrw3FoqiuVzcxEgj" %}
[Request variant for page](/product-discovery/a-b-testing-for-fhr/integration-steps-for-a-caching-solution/manual-a-b-tests-integration/request-variant-for-page.md)
{% endcontent-ref %}
