We have updated our Data Processing Addendum, for more information – Click here.

A/B Testing on the Front-End

A/B testing is a fantastic capability to have; it’s the most basic experimentation method and is core to the practice. It answers the simple question: “Which increases my success metrics more, A or B?” A/B testing on the web is enormously popular with good reason. It’s fundamental to growing business and delighting users. 

When doing A/B testing you need to have two experiences, an ‘A’ and a ‘B’ for customers to experience. And then you have to determine which experience a user will see. Split’s SDK can be used to bucket users both on the application’s front-end and back-end. 

On the back-end, you can use the Split SDK to change the page served to a user to determine the variation they see. However, sometimes you need to implement the SDK on the front-end. There could be many reasons for that, such as a lack of back-end implementation or compute resources.

In order to make a front-end SDK work for A/B testing on a webpage, you have a couple of options

  1. Ship down both experiences to the client and let Split show the correct experience for the user.
  2. Use a loading page and redirect to the A or B version of the page.

For option one, you can ship down the code to the browser to display the different treatments. However, one thing you will want to do is avoid the page flickering while the Split SDK loads to determine which experience, A or B, is shown to the incoming user. If your experiment is on a part of the page below the fold, the flicker typically won’t be seen by users navigating the page. 

If you want to avoid flickering on an experiment above the fold, then one option is to use a brief loading page until the SDK is ready to show the result of the Split Treatment. Here is a code example of what that might look like:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>HTML CSS Test</title>
    <style media="all">
        .spinner {
            width: 64px;
            height: 64px;
            border: 8px solid;
            border-color: #3d5af1 transparent #3d5af1 transparent;
            border-radius: 50%;
            animation: spin-anim 1.2s linear infinite;
        }
        @keyframes spin-anim {
            0% {
                transform: rotate(0deg);
            }
            100% {
                transform: rotate(360deg);
            }
        }
        body {
            background-color: pink;
        }
        h1 {
            color: blue;
            margin-left: 30px;
        }
        .button {
            border: none;
            border-radius: 10px;
            padding: 15px;
            min-height: 30px;
            min-width: 120px;
        }
        .a {
            background-color: #0a0a23;
            color: #fff;
        }
        .b {
            background-color: #ffffff;
            color: rgb(0, 0, 0);
        }
        .hide {
            display: none
        }
    </style>
    <script src="https://cdn.split.io/sdk/split-10.22.1.min.js"></script>
    <script>
        var factory = splitio({
            core: {
                authorizationKey: "SDK_KEY",
                key: "KEY" // unique identifier for your user
            }});
        var client = factory.client();
        client.on(client.Event.SDK_READY, function () {
            // once the SDK is ready, clear out the loader
            const loaderContainer = document.querySelector('.loader-container');
            loaderContainer.classList.add('hide');

            const body = document.getElementById('body');
            body.classList.remove('hide');
            // get treatment
            var treatment = client.getTreatment('css_demo');
            // get features to flip based upon CSS classes
            const featureA = document.querySelectorAll('.a');
            const featureB = document.querySelectorAll('.b');
            if (treatment === 'on') {
                featureB.forEach(element => {
                    element.classList.add('hide')
                })
            } else if (treatment === 'off') {
                featureA.forEach(element => {
                    element.classList.add('hide')
                })
            } else {
                console.error('Error connecting to Split')
                // default rule here
                featureA.forEach(element => {
                    element.classList.add('hide')
                })
            }
        });  </script>
</head>
<body>
    <div class="loader-container">
        <div class="spinner"></div>
    </div>
    <div id="body" class="hide">
        <h2>Welcome To This Demo</h2>
        <button type="button" class="button a">This is FEATURE A</button>
        <button type="button" class="button b">This is FEATURE B</button>
    </div>
</body>
</html>

This will create a spinner like that below, which will spin until the SDK has loaded and will make the decision for which treatment to show. 

When the SDK is finished loading, you’ll see the revealed treatment:

In this way, your customers will see a short loading page before the feature is loaded, eliminating the flicker. The different features are both shipped down and in the page. The features are shown and hidden using CSS using display: none.  

For the second option, you can use a landing page that does the redirect. In this way, you can perform A/B testing on whole pages, such as complete redesigns. 

Doing a redirect like this, however, may impact SEO results. Ultimately it is preferable to do full-page A/B testing using a backend SDK. But when that is not possible, Split can make it happen. 

See below for a code example. Replace pageA with the experimental page, and pageB with the control page. 

There will be a loading page and then the browser will be redirected to the proper page. One thing that may color the results is if only one of the pages is a redirect. In general, you want to make the experiences outside of the page itself as equivalent as possible in order to not compromise the experiment. As such, Split doesn’t recommend only redirecting on only one of the experiences.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <script src="https://cdn.split.io/sdk/split-10.22.1.min.js"></script>
    <script type="text/javascript">
      const pageA = "https://www.example.com/pageA"
      const pageB = "https://www.example.com/pageB"
      const factory = splitio({
        core: {
          authorizationKey: 'SDK_KEY',
          key: USER_KEY // unique identifier for your user
        }
      });
      let client = factory.client();
      client.on(client.Event.SDK_READY, function() {
            // get treatment
            let treatment = client.getTreatment('split_name');
            // get features to flip based upon CSS classes
            if (treatment === 'on') {
              window.location.href = pageA;
            } else if (treatment === 'off') {
              window.location.href = pageB;
            } else {
              console.error('Error connecting to Split')
              // default rule here
              window.location.href = pageB;

            }
            }
          );
    </script>
    <title>Redirecting...</title>
    <style>
      body {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        font-family: Arial, sans-serif;
      }
      .spinner {
        display: inline-block;
        width: 40px;
        height: 40px;
        border: 4px solid #f3f3f3;
        border-top: 4px solid #3498db;
        border-radius: 50%;
        animation: spin 2s linear infinite;
      }
      @keyframes spin {
        0% {
          transform: rotate(0deg);
        }
        100% {
          transform: rotate(360deg);
        }
      }
    </style>
  </head>
  <body>
    <div class="spinner"></div>
    <p>Loading...</p>
  </body>
</html>

You’ve seen ways to change the experience based upon the treatment received from the Split SDK. And you’ve seen it done in two different ways, either by changing the CSS to show or hide elements, or by redirecting to an entirely different page. This allows for A/B testing using the JavaScript Split SDK and without using any backend resources on one of your own servers. This is a rapid implementation approach that you can get up and running extremely quickly—gaining all of that A/B testing goodness without undesirable flicker on the front-end. 

Unlock meaningful, valuable insights and drive growth with Split and A/B testing.

Switch It On With Split

The Split Feature Data Platform™ gives you the confidence to move fast without breaking things. Set up feature flags and safely deploy to production, controlling who sees which features and when. Connect every flag to contextual data, so you can know if your features are making things better or worse and act without hesitation. Effortlessly conduct feature experiments like A/B tests without slowing down. Whether you’re looking to increase your releases, to decrease your MTTR, or to ignite your dev team without burning them out–Split is both a feature management platform and partnership to revolutionize the way the work gets done. Schedule a demo to learn more.

Get Split Certified

Split Arcade includes product explainer videos, clickable product tutorials, manipulatable code examples, and interactive challenges.

Want to Dive Deeper?

We have a lot to explore that can help you understand feature flags. Learn more about benefits, use cases, and real world applications that you can try.

Create Impact With Everything You Build

We’re excited to accompany you on your journey as you build faster, release safer, and launch impactful products.