Setting up A/B testing
Estimated duration: 15-30 minutes
This guide demonstrates how to set up A/B testing and the related metrics in your web application using the Prepr GraphQL API.
Introduction
Let's look at an everyday use case. The marketing team wants to increase the clickthrough rate of the landing page header and have prepared two potentially successful headers but are unsure which one will appeal to customers the most. In this case, they run an A/B test.
A/B testing is a simple and efficient way to compare two versions of something to figure out which performs better. In Prepr, marketers can create A and B variants of a section header, then you can render them in your website to show them to visitors randomly. Check out a demo A/B test in action (opens in a new tab).
The image below is an A/B test in a car leasing website. It shows the A and B variants of the section header on the Electric Lease landing page.
Once implemented, Prepr starts measuring the conversion rate for each variant and determines which is more effective.
Prerequisites
To set up your front end for A/B testing according to the guide below, you need to have the following set up in Prepr:
We will make use of the Landing page Electric Lease content item from the Acme Lease demo data. Take note that the A/B test is defined in a Stack field. Check out the marketers docs for more details on how to add an A/B test to a content item.
Set up your front end for A/B testing
Before setting up your front end for A/B testing, make sure to add the Prepr Tracking Code to track visitors when they view pages.
Now you're ready to do the A/B test setup with the below steps.
- Step 1: Create a customer ID to track and link each visitor to a variant.
- Step 2: Retrieve the variants using the API
- Step 3: Add HTML attributes to track impressions and conversion events
Create a customer ID
To make sure each web app visitor consistently sees the correct A/B test variant when they view a page, Prepr CMS identifies each visitor by a Prepr Customer ID. This value is set to the query header in the next step.
The Prepr tracking pixel you added, assigns each visitor a unique ID with a
cookie called __prepr_uid
.
You can use this __prepr_uid
value to set the Prepr Customer ID.
But, if a visitor is new, this cookie doesn't exist on the first page visit.
Follow the steps below to generate and store a Prepr Customer ID for each visitor including their first page visit:
- Check if the
__prepr_uid
cookie is set. - If the cookie isn't set yet, meaning the first time this visitor views a page, generate a random ID.
- Set the
__prepr_uid
cookie value to the generated ID. - Make this ID available to the web app as a global variable. This variable will be used for the Prepr Customer ID instead of the cookie.
This solution can best be implemented in the middleware of your web app where you have access to reading and setting cookies and can store a global variable. See the following example on how to set this up in the Next.js middleware.
import type {NextRequest} from 'next/server'
import {NextResponse} from 'next/server'
import {headers} from 'next/headers'
export function middleware(request: NextRequest) {
//Get the cookie to check if it exists
let prepr_uid = request.cookies.get('__prepr_uid')?.value
let newResponse = NextResponse.next()
// If the cookie doesn't exist yet, generate a random ID
if (!prepr_uid) {
prepr_uid = crypto.randomUUID()
newResponse.cookies.set('__prepr_uid', prepr_uid, {
maxAge: 1 * 365 * 24 * 60, // Set for one year
})
}
// Create a global variable to make it available to the
// rest of the web app for the Prepr Customer Id
newResponse.headers.set('Prepr-Customer-Id', prepr_uid)
return newResponse
}
Now that the global variable is set, we can later retrieve the Prepr Customer ID with this helper function:
import {headers} from 'next/headers'
export function getPreprUUID() {
return headers().get('Prepr-Customer-Id')
}
For other frameworks, you could use the Session ID instead of the __prepr_uid
cookie in your front end and use
this value as the Prepr Customer ID to be sent to Prepr.
See the example Laravel code snippet below.
$prepr_customer_id = Session::getId();
Make the session persistent by setting the cookie's lifetime
parameter to something like 90 days.
This means that you get the same session ID even when a customer visits the site multiple times.
Now that the Prepr Customer Id is available you can continue the next step to retrieve the variants.
Retrieve variants using the API
Now it's time to retrieve the Landing page Electric Lease content including the section header variants.
Copy the sample query below into your front-end application.
{
Page(slug: "electric-lease") {
_id
title
_slug
stack {
__typename
... on SectionHeader {
_id
title
}
}
}
}
To retrieve the page content and determine the visitor's variant, set the Prepr Customer Id header to the variable from the previous step when you make the query request to the API.
--header 'Prepr-Customer-ID: <YOUR-CUSTOMER-ID-VARIABLE>'
Follow the Connecting front-end apps guide to learn more about retrieving content items for a specific framework.
See an example of a response below for the A variant:
{
"data": {
"Page": {
"_id": "8da86294-c15d-415a-9fa3-6ea289c9403c",
"title": "Landing page Electric Lease",
"_slug": "electric-lease",
"stack": [
{
"_context": {
"kind": "AB_TEST",
"variant_key": "eyJpIjoiYmU3OTkxMWEtNjE3My00YmYzLWE5ZGUtZTg2YzYzNWMyYjhiIiwiZSI6IjVmMWFhM2I4LTQyZjktNGY2OS04MzYzLTkxMDFhZmFlNDQ2ZiIsInYiOiJBIn0=",
"variant_id": "A"
},
"title": "Short. Affordable. Electric.",
"cta_button": {
"text": "Find your car"
}
}
]
}
}
}
Take note of the following important context fields:
kind
- This returns a value ofAB_TEST
when an A/B test is enabled for this element in the Stack.variant_id
- This returns a valueA
orB
to indicate the returned variant of the A/B test.variant_key
= A unique ID for the variant. You will use this field value in the next step to indicate which components need to be tracked for impressions.
The algorithm remembers which visitor gets which variant so that the same visitor always gets the same section header variant when interacting with your web app.
You can do a test run of the A/B test in Prepr before launching it on your live website:
- Open the embedded API Explorer as described here.
- Copy and paste your Graphql query into the Operations pane.
- Under the Header section, enter Prepr-Customer-ID with any customer ID value. Go to the Segments tab in the Prepr application to find the ID when you click a specific customer. Customers are added automatically when you set up the Prepr tracking pixel.
- Run the query to get the variant for that customer ID.
- Re-run the query for a different Customer ID.
The algorithm should match a Customer ID and a section header variant. For example, Customer 1 always gets Variant A, Customer 2 - Variant B.
Add HTML attributes to track impressions and conversion events
To track visitor impressions and conversions for an A/B test and get accurate metrics, you need to add HTML attributes to elements in your A/B test. When you add these attributes, the tracking pixel automatically tracks impressions and your chosen conversion events.
Usually, you'd collaborate with the marketing team to choose the element and the corresponding event that indicates a conversion in the A/B test.
In our example, we have a section header with some specific text and a call-to-action button for each variant, so we want to report on the following types of visitor interactions:
- Impressions: How many visitors looked at the section header for each variant.
- Clicks: How many visitors clicked the CTA button for each variant.
Prepr will determine the conversion rate and other related metrics based on these events and will show you which variant performed best.
To start collecting impressions, add the HTML attribute data-prepr-variant-key
to the Section header.
The impression is then recorded when the Section header element scrolls into view.
Set the data-prepr-variant-key
value to the Prepr variant key value returned in the query response.
To start collecting clicks, add the HTML attribute data-prepr-variant-event
to the CTA button.
The click is recorded when the CTA button element is clicked.
If you want to track a conversion other than a click event, e.g. a quote request, then set your data-prepr-variant-event
to the custom event.
For example: data-prepr-variant-event="QuoteRequest"
.
See an example code snippet to include the HTML attributes below:
...
<!-- section header -->
<div class="..." data-prepr-variant-key="{{ variant_key }}">
<!-- section header image -->
<img src="..." class="...">
<div class="...">
<div class="...">
<!-- section header text -->
<h1 class="...">Short. Affordable. Electric.</h1>
<span>
<!-- Call-to-action button -->
<a href="/catalog?category=electric" data-prepr-variant-event>
<button class="...">Request a quote</button></a>
</span>
</div>
</div>
...
That’s it. You've set up A/B testing in your front end. A correct section header variant will be displayed every time a customer visits your website and Prepr will calculate metrics for the A/B test.
As visitors interact with your web app, data will be collected and metrics will be visible in the A/B test. Go to the Landing page Electric Lease content item to see the metrics.
Congratulations, you have successfully set up A/B testing in your front end. Check out the next section if you are implementing a static website.
Implementing A/B testing for static (SSG) websites
Unlike dynamic sites, static sites serve pre-built content to a web browser without calls to a database. To perform A/B testing for static site rendering, you need to set up variants ahead of time (particularly before you build the web app) and then split traffic between different routes using the edge middleware (see an example tool (opens in a new tab)). Let’s see it in detail.
The A/B testing for static site rendering looks like this:
- On pages where an A/B test needs to be triggered, you call the API to pre-fetch variants. Your request must include the following fields:
- _context - system field that contains additional details about variants such as the following fields:
- kind – returns a value of PERSONALIZATION or AB_TEST.
- variant - returns a value of A or B if kind has a value of AB_TEST
Here’s an example code snippet. Update the id string of the query with your Content item ID (find the ID in the right-hand column on the Page content item in Prepr).
query{
Page(id: "8da86294-c15d-415a-9fa3-6ea289c9403c") {
_id
title
_slug
stack (personalize: false) {
__typename
... on SectionHeader {
_id
heading
text
cta_label
_context {
kind
variant_id
}
}
}
}
}
- When a user visits your web app, you make a one-time request to know if this user is assigned to Bucket A or Bucket B. Your request must include the following headers:
- Prepr-Customer-ID with a session ID of a visitor
- Prepr-Bucket-Customer = true
The bucketing runs at the edge location of the CDN and takes no longer than 7 ms. A response to your API request contains a header – either X-Prepr-Customer-Bucket A or X-Prepr-Customer-Bucket B.
See an example request below:
curl --location --globoff 'https://graphql.prepr.io/<YOUR-ACCESS-TOKEN>' \
--header 'Prepr-Customer-ID: 409ad1af-d644-4d3f-8cb9-691c0318a980' \
--header 'Prepr-Bucket-Customer: true'
- With this information, the front-end middleware can redirect a visitor to a respective variant of your A/B test. For all the requests from the same visitor, the same variant will be shown.
Want to learn more?
Check out the following guides:
Schedule a free consultation
Do you want to get started with A/B testing but still have questions or want a demo?
Schedule a free call (opens in a new tab) with a Prepr solution engineer.
Was this article helpful?
We’d love to learn from your feedback