Randomly assign a new user to a group for A/B testing using Edge Workers
This example will randomly assign a new user to a group for A/B testing. The assignment will be stored in a cookie and will be passed to the origin in a query parameter. To allow easy testing, the A/B group can be forced via a query string parameter. The group names, percentage split, cookie name, and query parameter name are configured through constants in the EdgeWorker JavaScript module
Outcome : Randomly assign a new user to a group for A/B testing
Below is the code snippet in main.js
/*
(c) Copyright 2020 Akamai Technologies, Inc. Licensed under Apache 2 license.
Version: 0.1
Purpose:
Enable A/B testing.
Randomly assign new users to an A/B testing group.
Include the A/B group in a query parameter sent to the origin.
Include the A/B group in a cookie to the browser.
Allow overriding the group with a query string parameter for easy testing.
Repo: https://github.com/akamai/edgeworkers-examples/tree/master/a-b-test
*/
import { Cookies, SetCookie } from 'cookies';
import URLSearchParams from 'url-search-params';
// ====== Begin Configuration ====== //
// Update constants below to configure A/B logic
/** Probability that a user is added to the "A" group. 0.5 = 50% */
const probabilityOfA = 0.5;
/** Name of cookie that stores A/B group assignment. */
const cookieName = 'testGroup';
/**
* Name of query parameter that contains A/B group assignment
* This query parameter will be added to the outgoing onClientRequest.
* The query parameter can be added to the incoming request to force A/B group assignment.
*/
const queryParamName = 'testGroup';
/** Cookie and query string value to use for users in the "A" group. */
const groupAValue = 'A';
/** Cookie and query string value to use for users in the "B" group. */
const groupBValue = 'B';
// ====== End Configuration ====== //
export function onClientRequest (request) {
const cookies = new Cookies(request.getHeader('Cookie'));
const params = new URLSearchParams(request.query);
// Initialize existing and reult group value from the request cookie
const existingGroupValue = cookies.get(cookieName);
let resultGroupValue = existingGroupValue;
// override result group value if forced by query parameter
const paramValue = params.get(queryParamName);
if (paramValue) {
resultGroupValue = paramValue;
}
// If no group value has been assigned,
// then randomly choose one based on configured percentage
if (!resultGroupValue) {
if (Math.random() <= probabilityOfA) {
resultGroupValue = groupAValue;
} else {
resultGroupValue = groupBValue;
}
}
// If group value if different than the existing cookie,
// then replace the incoming cookie with the new value.
if (resultGroupValue != existingGroupValue) {
cookies.delete(cookieName);
cookies.add(cookieName, resultGroupValue);
request.setHeader('Cookie', cookies.toHeader());
}
// If the group was not already included in the incoming query parameter,
// then add the query parameter to the query string.
// The query parameter allows the origin to respond with appropriate logic
// and ensures the A/B group is included in the cache key.
if (!paramValue) {
params.append(queryParamName, resultGroupValue);
request.route({ query: params.toString() });
}
}
export function onClientResponse (request, response) {
// Set a response cookie with the A/B group based on
// the request cookie set in the onClientRequest handler.
const cookies = new Cookies(request.getHeader('Cookie'));
const cookieValue = cookies.get(cookieName);
const setCookie = new SetCookie({ name: cookieName, value: cookieValue });
response.setHeader('Set-Cookie', setCookie.toHeader());
}