Customer experience

Een A/B-test opzetten met JavaScript [stappenplan]

0

Wil je een eigen A/B-test bouwen in JavaScript (JS)? Doorloop dan dit stappenplan.

A/B-testen is een ideaal middel om meer rendement te halen uit je website. En om meer te leren over de bezoekers van je website.

Stap 1. Voorbereiding

Voordat je een A/B-test opzet, is het belangrijk dat je goed uitdenkt hoe de test eruit gaat zien en wat je precies wil meten.

Zo is het handig om eerst een design te maken, zodat in het designproces al mogelijke problemen naar voren komen. Daarnaast is het goed om te bepalen wat er gemeten moet worden tijdens de test. Wordt bijvoorbeeld een call-to-action aangepast in de test? Dan is het handig om hier een Analytics-event aan toe te voegen, zodat deze gemakkelijk te meten is.

Stap 2. Opbouw van een A/B-test

De meeste A/B-testtools adviseren gebruikers om hun tool-snippet zo hoog mogelijk in de head van de website te plaatsen. Hierdoor gebeurt het soms dat bepaalde objecten nog niet aanwezig zijn wanneer het script van je test wordt uitgevoerd.

Om die reden is het belangrijk dat het script van de test zo is opgebouwd dat de veranderingen pas worden uitgevoerd nadat deze elementen aanwezig zijn. In onderstaand voorbeeld heb ik twee objecten gebruikt, het jQuery-object en het Google Analytics-object. Bekijk hieronder de functies die ik gebruik om ze aan te roepen.

jQuery

Als je jQuery gebruikt, dan begin je met dit object. Zo weet je zeker dat de jQuery-code die je gebruikt in de test ook daadwerkelijk werkt. Hiervoor gebruik ik een ‘IIFE’ (Immediately Invoked Function Expression) die zichzelf blijft oproepen (tot 50 keer) als het jQuery-object nog niet gevonden is.

Als het jQuery-object gevonden is, dan wordt het toegewezen aan variable ‘$’, zoals gebruikelijk is voor jQuery, en wordt de startfunctie uitgevoerd waar de wijzigingen van de test in staan.

var $, JQIndex = 0;

(function getJQ() {
if (window.jQuery) {
//* Als jQuery object aanwezig is, wijs het dan toe aan $ en voer de start functie uit.
$ = window.jQuery;
start();
} else if (JQindex < 50) {
//* Als het jQuery object niet aanwezig is, probeer het dan tot 50 keer met een interval van 50 ms.
//* Als jQuery niet nodig is voor de test, dan hoeft deze functie niet gebruikt worden.
JQindex++; //* +1 bij JQIndex
setTimeout(() => {
getJQ();
}, 50);

Voorbeeld van een startfunctie met jQuery:

function start(){
$(‘.cta’).css(‘background’, ‘red’);console.log(‘start’);
}

Het is handig om in het begin een console.log in het script te hebben om te controleren of de test werkt.

Google Analytics-object

Het Google Analytics-object is wat complexer. Hier heb je namelijk niet alleen het object nodig, maar moet ook de correcte tracker opgezocht worden en maak je gebruik van het GA ID.

Omdat dit een complexer object is, regel ik dit in een eigen functie die ik aanroep voor de startfunctie (zodat we in de startfunctie GA kunnen gebruiken):

(function getJQ() {
if (window.jQuery) {
$ = window.jQuery;
getTracker(); //* Here
start();
}

Bovenstaand is een snippet van de jQuery-code.

Voor de getTracker-functie is een GA ID nodig. Wat ik over het algemeen doe, is een object maken met het GA ID en andere data. Denk aan: op welke pagina de test draait, voor welke devices, wat de ID en naam van de test is en wat de variant is. Dit plaats ik bovenaan de test, in de global scope van het testscript (buiten functies zoals de startfunctie).

Dit object noem ik vaak ‘data’ en kan er zo uitzien:

var data = {
gaid: ‘UA-XXXXX-XX’, //* Vul hier het GA ID in van de website
category: ‘AB-test’, //* GA event categorie, bij AB-testen over het algemeen “AB-testen”
testId: ‘A01’, //* test ID
devices: ‘DTM’, //* devices: Desktop, Tablet, Mobiel
page: ‘Home’, //* pagina waar test wordt uitgevoerd (Home, PLP, PDP)
name: ‘Kleur CTA aanpassen’, //* naam test
variant: ‘B: Variant’, //* A: Control – B: Variant
};

De getTracker-functie is als volgt opgedeeld:

  • Controleren of het GA-object aanwezig is en zo ja, controleren of het object het ‘create’-attribuut bezit (dit om zeker te weten dat het GA-object volledig is geladen).
  • Het ophalen van alle trackers.
  • De correcte tracker opslaan door het GA ID (UA-XXXX-XX) in het data-object.

Voorbeeld van de getTracker-functie:

//* Variabelen
var tracker, trackerIndex = 0, GAindex = 0;function getTracker() {
if (window[window[‘GoogleAnalyticsObject’]] && window[window[‘GoogleAnalyticsObject’]].create) {
//* Als het GA object aanwezig is en het “create” attribuut bezit, haal dan alle trackers op en plaats deze in “allTrackers”
var allTrackers = window[window[‘GoogleAnalyticsObject’]].getAll();//* Deze “for loop” gaat alle trackers af en vergelijkt het tracking ID van de verschillende trackers met het GA ID van het data object.
for (var i = 0; i < allTrackers.length; i++) {
if (allTrackers[i].get(‘trackingId’) === data.gaid) {
//* Als het tracker ID overeenkomt met het GA ID, dan wordt deze tracker toegewezen aan het variabel “tracker” en wordt de functie trackerSend aangeroepen (deze wordt besproken in het volgende hoofdstuk)
tracker = allTrackers[i];
trackerSend(”, ‘true’); //* Wordt besproken in het volgende hoofdstuk
return; //* Stop loop als de tracker gevonden is.
} else if (i === allTrackers.length – 1 && !tracker) {
//* Als de tracker niet aanwezig is, probeer het dan tot 50 keer met een interval van 50 ms,
if (trackerIndex !== 50) {
console.warn(‘Tracker not found, Trying again’);
setTimeout(function () {
return getTracker();
}, 50);
trackerIndex++;
} else {
//* Als de tracker na 50 nog niet is gevonden, stuur een error naar de console.
console.error(“TRACKER: \””.concat(toolConfig.gaid, “\” NOT FOUND”));
}
}
}
} else if (GAindex < 50) {
//* Als het GA object niet aanwezig is, probeer het dan tot 50 keer met een interval van 50 ms.
JQindex++;
setTimeout(function () {
return getTracker();
}, 50);
GAindex++;
} else {
//* Als het GA object na 50 nog niet is gevonden, stuur een error naar de console.
console.error(‘Google Analytics not found!’);
}
};

Stap 3. Custom events

Als het bovenstaande goed is gegaan, dan heb je nu de GA-tracker beschikbaar in je test (in het tracker-variabel) en kun je beginnen met het versturen van custom events vanuit de test.

Zelf gebruik ik een functie die de info van het data-object meestuurt met alle events.

Deze staat al in het voorbeeld van de getTracker-code: de functie ‘trackerSend’, die aangeroepen wordt wanneer de GA-tracker gevonden is.

De functie moet je in de global scope van het testscript plaatsen en ziet er als volgt uit.

function trackerSend() {
var extra = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ”;
var nonInteract = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
extra ? extra = ‘ : ‘ + extra : extra;
tracker.send(‘event’, data.category, data.testId + ‘ – ‘ + data.devices + ‘ – ‘ + data.page + ‘ – ‘ + data.name + ‘ – ‘ + data.variant + extra, {
nonInteraction: nonInteract
});
};

Deze functie kan parameters ontvangen. De eerste is informatie om mee te sturen met het event en de tweede is een boolean (true – false) om aan te gegeven of het een nonInteract-event is of niet. NonInteract is de vraag of het event wordt afgevuurd door de interactie van de gebruiker of niet?

Denk bijvoorbeeld aan:

  • Event versturen bij pagina laden: nonInteract = True, aangezien bij het laden van de pagina er geen gebruikersinteractie is.
  • Event versturen na het klikken op CTA: nonInteract = False, aangezien er interactie is van de gebruiker, namelijk de klik op de CTA.

In de getTracker-functie staat de trackerSend-functie al en ziet er als volgt uit:

trackerSend(“”, true);

Dit is het algemene ‘test is geladen’-event. Dit heeft geen extra info en het nonInteract attribute staat op true.

Het event naar GA ziet er als volgt uit:

test in code javascript

Als je custom events wil toevoegen aan bijvoorbeeld klik- of scroll-events, dan kun je dit doen in de startfunctie:

function start(){
var $cta = $(‘.cta’);$cta.css(‘background’, ‘red’);
$cta.on(‘click’, function() {
trackerSend(‘CTA klikt!’);
});
};

In dit geval hoef je de boolean van nonInteract niet door te geven, omdat de trackerSend-functie deze standaard op false zet. De tweede parameter van deze functie hoef je dus niet in te vullen als het een interactief event is.

Het event naar GA ziet er als volgt uit:

test in code javascript

Stap 4. Afronden code

Als je mee hebt gedaan, dan zal je test er nu ongeveer zo uitzien.

var data = {
gaid: ‘UA-XXXXX-XX’,
category: ‘AB-test’,
testId: ‘A01’,
devices: ‘DTM’,
page: ‘Home’,
name: ‘Kleur CTA aanpassen’,
variant: ‘B: Variant’,
};var $, tracker, trackerIndex = 0, GAindex = 0;function getTracker() {
if (window[window[‘GoogleAnalyticsObject’]] && window[window[‘GoogleAnalyticsObject’]].create) {
var allTrackers = window[window[‘GoogleAnalyticsObject’]].getAll();for (var i = 0; i < allTrackers.length; i++) {
if (allTrackers[i].get(‘trackingId’) === data.gaid) {
tracker = allTrackers[i];
trackerSend(”, true);
return;
} else if (i === allTrackers.length – 1 && !tracker) {
if (trackerIndex !== 50) {
console.warn(‘Tracker not found, Trying again’);
setTimeout(function () {
return getTracker();
}, 50);
trackerIndex++;
} else {
console.error(“TRACKER: \””.concat(data.gaid, “\” NOT FOUND”));
}
}
}
} else if (GAindex < 50) {
GAindex++;
setTimeout(function () {
return getTracker();
}, 50);
} else {
console.error(‘Google Analytics not found!’);
}
};
function trackerSend() {
var extra = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ”;
var nonInteract = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
extra ? extra = ‘ : ‘ + extra : extra;
tracker.send(‘event’, data.category, data.testId + ‘ – ‘ + data.devices + ‘ – ‘ + data.page + ‘ – ‘ + data.name + ‘ – ‘ + data.variant + extra, {
nonInteraction: nonInteract
});
};

function start(){
var $cta = $(‘.cta’);

$cta.css(‘background’, ‘red’);
$cta.on(‘click’, function() {
trackerSend(‘CTA klikt!’);
});
}

(function getJQ() {
if (window.jQuery) {
$ = window.jQuery;
getTracker();
start();
} else if (JQindex < 50) {
setTimeout(() => {
getJQ();
}, 50);
}
})();

Wat we bij Online Dialogue nu vaak nog doen is deze code dupliceren en daarin de wijzigingen van de test verwijderen, maar de custom GA-events laten staan en de variant in het data object veranderen naar ‘A: Control’.

Stap 5. Testen

Heb je dit allemaal gedaan en heb je beide varianten 50-50 verdeeld in de testtool? Dan kun je de custom events van de twee versies vergelijken, om zo je A/B-test te analyseren en tot nieuwe inzichten te komen. Maar eerst beide versies nog even testen…

Gebruik de previewfunctie van je testtool en controleer of in versie B de veranderingen goed worden uitgevoerd (voor zowel desktop, tablet, mobiel). En check ook of bij variant A en B de events juist worden afgevuurd. Als dit het geval is, dan kun je de test live zetten!