Head to Head Guide

A guide to implement a Head to Head test with Criteo.

Overview

For setting up head-to-head tests, Criteo has created an easy to implement, transparent and free of charge cookie split tool. The tool is a piece of JavaScript code that must be executed on your website. It can be hard-coded or integrated within a Tag Management Solution. The code needs to be implemented on all pages of your website. The code may be reviewed and tested by both you and the other parties involved in the head-to-head for full transparency.

How the code works:

  1. For each user, the code creates a cookie called cto_h2h under your domain.

  2. The value of this cookie can be either "A" or "B".

  3. The first time a user arrives to your website after the code is in place, the user is assigned randomly to a population and its value gets stored on the previously mentioned cookie.

  4. Every time that user loads any page on your website, the code reads the content of the cookie, assigns the value to a JavaScript variable and updates the cookie expiration date.

  5. The code will then setup the split rate, with a variable called splitRate_cto_h2h. Default is 50%

The code has to be executed at the beginning of each page in order to have the user assigned to a population before the 2 competitors tags are called. As the call to the loader needs to be done conditionally inside a a Javascript code, the way of doing the call to the loader will be different. You can see in the code below.

[[disclaimer-developer]]

Steps

1) Implement the following code on all pages of your site:

<script>
var cookiename_cto_h2h = "cto_h2h"; // Name of the cookie
var splitRate_cto_h2h = 50; // Split rate between the 2 parties
function getCookie_cto_h2h(cname) { // It returns the content of the cookie received as parameter
    var name = cname + "=";
    var ca = document.cookie.split(";");
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == " ") c = c.substring(1);
        if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
    }
    return "";
}

function assignPopulationRandomly(percentage) { // Returns A or B under the specified percentage.
    return (((Math.random() * 100 | 0) + 1) <= percentage) ? "A" : "B";
}

function updateCookie_cto_h2h(name, value) {
    var date = new Date();
    date.setTime(date.getTime() + (365 * 24 * 60 * 60 * 1000)); // The cookie will expire after 365 days
    var expires = "; expires=" + date.toGMTString();
    document.cookie = name + "=" + value + expires + "; path=/";
}
var population_cto_h2h = getCookie_cto_h2h(cookiename_cto_h2h); // Pull the actual group from the cookie
if (population_cto_h2h == "") population_cto_h2h = assignPopulationRandomly(splitRate_cto_h2h); // If no group, assign one randomly based on the Split rate
updateCookie_cto_h2h(cookiename_cto_h2h, population_cto_h2h); // Update the cookie

</script>

<script>
if (population_cto_h2h == "A") { // START CRITEO
    // Call to Criteo loader
    var cto_loader = document.createElement("script");
    cto_loader.type = "text/javascript";
    cto_loader.async = true;
    cto_loader.src = ("https:" == document.location.protocol ? "https:" : "http:") + "//static.criteo.net/js/ld/ld.js";
    document.getElementsByTagName("head")[0].appendChild(cto_loader);
    //TAG

}
// END CRITEO
else { // START COMPETITOR
}
// END COMPETITOR
</script>

2) This is an example of the code implemented on the Homepage of your site:

<script>
var cookiename_cto_h2h = "cto_h2h"; // Name of the cookie
var splitRate_cto_h2h = 50; // Split rate between the 2 parties
function getCookie_cto_h2h(cname) { // It returns the content of the cookie received as parameter
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1);
        if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
    }
    return "";
}

function assignPopulationRandomly(percentage) { // Returns A or B under the specified percentage.
    return (((Math.random() * 100 | 0) + 1) <= percentage) ? "A" : "B";
}

function updateCookie_cto_h2h(name, value) {
    var date = new Date();
    date.setTime(date.getTime() + (365 * 24 * 60 * 60 * 1000)); // The cookie will expire after 365 days
    var expires = "; expires=" + date.toGMTString();
    document.cookie = name + "=" + value + expires + "; path=/";
}
var population_cto_h2h = getCookie_cto_h2h(cookiename_cto_h2h); // Pull the actual group from the cookie
if (population_cto_h2h == "") population_cto_h2h = assignPopulationRandomly(splitRate_cto_h2h); // If no group, assign one randomly based on the Split rate
updateCookie_cto_h2h(cookiename_cto_h2h, population_cto_h2h); // Update the cookie

</script>

<script type="text/javascript">
if (population_cto_h2h == "A") { // START CRITEO
    // Call to Criteo loader
    var cto_loader = document.createElement("script");
    cto_loader.type = "text/javascript"; cto_loader.async = true;
    cto_loader.src = ("https:" == document.location.protocol ? "https:" : "http:") +"//static.criteo.net/js/ld/ld.js";
    document.getElementsByTagName("head")[0].appendChild(cto_loader);
    var site_type = /iPad/.test(navigator.userAgent) ? "t" : /Mobile|iP(hone|od)|Android|BlackBerry|IEMobile|Silk/.test(navigator.userAgent) ? "m" : "d";
    window.criteo_q = window.criteo_q || [];
    window.criteo_q.push(
        { event: "setAccount", account: {{accountid}} },
        { event: "setEmail", email: "criteotest@test.com" },
        { event: "setSiteType", type: site_type },
        { event: "viewHome" }
    );
}
// END CRITEO
else {  // START COMPETITOR
}
// END COMPETITOR
</script>

3) Once it is implemented, you can test that the random rate is OK. Click button below to see the function for using in the console of your browser:

(function() {
    var times_A = 0;
    var times_B = 0;
    var iterations = 1000000;
    for (var n = 0; n < iterations; n++) {
        test = assignPopulationRandomly(splitRate_cto_h2h);
        if (test == 'A') times_A++;
        else times_B++;
    }
    console.log("Random function TEST Results - Iterations : " + iterations + " \n Population A:" + times_A + " times" + " \n Population B:" + times_B + " times");
})();

4) If you are using GTM, add the following code as a variable within the GTM set-up. The function will give you back either "A" or "B". This variable you can use then in a trigger on the tag.

function() {
    // Settings
    var cookiename_cto_h2h = "cto_h2h"; //Name of the cookie
    var splitRate_cto_h2h = 50; //Split rate between the 2 parties

    // Check if cookie already exits
    var population_cto_h2h = '';
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == " ") c = c.substring(1);
        if (c.indexOf(cookiename_cto_h2h + "=") == 0) {
            population_cto_h2h = c.substring(cookiename_cto_h2h.length, c.length);
            population_cto_h2h = population_cto_h2h.split("=")[1]; // Returns A or B
        }
    }

    // Populate the cookie, as there is no pool present in the cookie
    if (population_cto_h2h == "" || population_cto_h2h == undefined) {
        console.log("we generated again a h2h value");
        population_cto_h2h = (((Math.random() * 100 | 0) + 1) <= splitRate_cto_h2h) ? "A" : "B";
    }

    var date = new Date();
    date.setTime(date.getTime() + (365 * 24 * 60 * 60 * 1000));
    var expires = "; expires=" + date.toGMTString();
    var default_path = "; path=/"; // really important so the var will be reachable from any page of the website
    document.cookie = cookiename_cto_h2h + "=" + population_cto_h2h + expires + default_path;
    return population_cto_h2h; // Returns A or B
}

5) Create a GTM Trigger for each competitor: 1

Verification

[[accurate]]