Try our conversational search powered by Generative AI!

Sanjay Kumar
Mar 30, 2020
(3 votes)

Episerver A/B testing and visitor group (personalization) metadata into an analytics payload for consumption with the Google Analytics

The purpose of this blog post is to retrieve the real-time A/B testing and visitor group (personalization) details and feed into the Google Analytics for tracking real-time content item progress on your website.


A/B Testing is the variations of content items and that compares which variation performs best. When A/B testing running then majors number the conversions for the A and B version, one the gets the best result then wins.

Episerver CMS and Episerver Commerce each have own three conversion goals and developer can define custom conversion goals using KPI interface. A/B testing is distributed as free AddOn which you can download from NuGet but you need to add in Nuget package manager before download. The name of NuGet package that installs under the ~/module folder is EPiServer.Marketing.Testing after installation you need to update Episerver database schema.

Episerver CMS Conversions Goals:

  1. Landing page: The goal for the visitor to navigate the specify page and only click is counted as a conversion.
  2. Site Stickiness: The A/B test counts a conversion if a visitor goes from the target page to any other page on the site during the set time period (1-60 minutes).
  3. Time on Page: Visitors spend some time on the page for specifying numbers second.

Episerver Commerce Conversions Goals:

  1. Add to cart: Create a visitor group for the specific product and then the visitor adds that product to a cart, it is counted as a conversion.
  2. Purchase product: If a site visitor buys the added products on the cart, then it is counted as a conversion.
  3. Average order: The conversion goal to track completed orders on each of the test pages. The conversion goal totals up the values of all Episerver Commerce carts created by visitors included in the A/B test. The test determines which page variant creates the highest average value for all those carts when picking a winner. If a visitor creates multiple carts, all the (purchased) carts are included in the total, which means that the visitor can “convert” many times in the test duration. On Episerver Commerce websites using different currencies, the test converts all carts to the same currency.


  • Developers can create own custom conversions which known as KPI (Key performance indicator)
  • For the Commerce-related conversion goals, you required Episerver Commerce and then you can create commerce-related visitor groups criteria for personalization


Personalization in Episerver target the website content to selected visitor groups. The personalization feature is based on customized visitor groups that you create based on a set of personalization criteria. Episerver provides two types of criteria one for CMS and another for commerce.

List of CMS and Commerce visitor group criteria, you can see the difference in both.

Let's create visitor groups (personalization) for the CMS and Commerce following the below steps.

Episerver CMS visitor group

  • Go to visitor group area and click to create button
  • Tap on Time and Place criteria options and drag `Time on Site` from the right section in `Drop new creation here` in the left section.
  • Enter specific time in seconds e.g. 10
  • Enter the visitor group name e.g. Time On-Site Visitor Group
  • Click to Save.

Episerver Commerce visitor group

  • Go to visitor group area and click to create button
  • Tap on Commerce criteria options and `Product in Cart or Wish List` from the right section in `Drop new creation here` in the left section.
  • Enter the specific product codes. e.g. 123456
  • Enter visitor group name e.g. Add to cart visitor group
  • Click to Save.

The below screenshot is an example of the cart page AB testing where you can see CMS and Commerce related conversion goals with personalization.


Using the below code you can retrieve the real-time A/B testing and visitor group (personalization) details. I have divided the code into four main part. 

  • View Model
  • Factory or Service
  • Controller
  • Assign the payload result into Google Analytics
View Model

Create two view models with the name AnalyticsViewModel and VisitorGroupViewModel.

The AnalyticsViewModel view model is the payload response view model that returns the real-time A/B testing and personalization details into the response of payload.

public class AnalyticsViewModel 

     public bool AbTestRunning { get; set; }

     public string AbTestId { get; set; }

     public string AbTestVariant { get; set; }

     public bool PersonalizationRunning { get; set; }

     public string PersonalizationId { get; set; }

     public string PersonalizationType { get; set; }


The VisitorGroupViewModel view model that helps to get the visitor group details into the created factory class.

public class VisitorGroupViewModel
public string Id { get; set; }

public string Name { get; set; }
Factory or Service

Create a factory class with name AnalyticsViewModelFactory within this factory you need to inject the following dependency that I listed below which helps to get visitor group (personalization) and A/B testing variation details for the current session and feed into the payload response.

  • IVisitorGroupRepository
  • IVisitorGroupRoleRepository
  • ITestManager
public class AnalyticsViewModelFactory
private readonly IVisitorGroupRepository _visitorGroupRepository;
private readonly IVisitorGroupRoleRepository _visitorGroupRoleRepository;
private readonly ITestManager _testManager;

public AnalyticsViewModelFactory(
IVisitorGroupRepository visitorGroupRepository,
IVisitorGroupRoleRepository visitorGroupRoleRepository,
ITestManager testManager)
_visitorGroupRepository = visitorGroupRepository ?? throw new ArgumentNullException(nameof(visitorGroupRepository));
_visitorGroupRoleRepository = visitorGroupRoleRepository ?? throw new ArgumentNullException(nameof(visitorGroupRoleRepository));
_testManager = testManager ?? throw new ArgumentNullException(nameof(testManager));

public AnalyticsViewModel Create(HttpContextBase httpContext)
var visitorGroups = this.GetVisitorGroupsByCurrentUser(httpContext);
var visitorIds = visitorGroups?.Select(x => x.Id).ToList();
var visitorNames = visitorGroups?.Select(x => x.Name).ToList();

var activeTests = _testManager?.GetActiveTests();
var variantNames = activeTests?.Select(x => x.Title).ToList();
var testIds = activeTests?.Select(x => x?.Id.ToString()).ToList();

return new AnalyticsViewModel
AbTestRunning = activeTests?.Count > decimal.Zero,
AbTestId = string.Join(",", testIds ?? new List<string>()),
AbTestVariant = string.Join(",", variantNames ?? new List<string>()),
PersonalizationRunning = visitorIds?.Count > decimal.Zero,
PersonalizationId = string.Join(",", visitorIds ?? new List<string>()),
PersonalizationType = string.Join(",", visitorNames ?? new List<string>())

private List<VisitorGroupViewModel> GetVisitorGroupsByCurrentUser(HttpContextBase httpContext)
var visitorGroupList = new List<VisitorGroupViewModel>();
var user = httpContext.User;
var visitorGroups = _visitorGroupRepository.List();

foreach (var visitorGroup in visitorGroups)
if (_visitorGroupRoleRepository.TryGetRole(visitorGroup.Name, out var virtualRoleObject))
if (virtualRoleObject.IsMatch(user, httpContext))
var viewModel = new VisitorGroupViewModel
Id = visitorGroup.Id.ToString(),
Name = visitorGroup.Name


return visitorGroupList;

Create an endpoint v1/google/analytics using a controller with the name of AnalyticsController where you will inject the factory/service to load the data into the payload.

  public class AnalyticsController : Controller
        private readonly AnalyticsViewModelFactory _analyticsViewModelFactory;
        public AnalyticsController(AnalyticsViewModelFactory analyticsViewModelFactory)
            _analyticsViewModelFactory = analyticsViewModelFactory ?? throw new ArgumentNullException(nameof(analyticsViewModelFactory));

        public JsonResult GetAnalytics()
            return this.JsonNet(_analyticsViewModelFactory.Create(this.HttpContext));
Assign the payload result into Google Analytics

When you will hit the v1/google/analytics endpoint then you get a result similar like below and then pass into the Google Analytics script datalayer properties.

"abTestRunning": true,
"abTestId": "a0a77ae9-31ec-4d74-8952-32a082535bb1,29de7423-f6ba-4212-a913-34e0517ffda3",
"abTestVariant": "Cart A/B Test, AboutUs A/B Test",
"personalizationRunning": true,
"personalizationId": "adb342d2-8ebb-4430-a305-e403c549452a",
"personalizationType": "Time On Site Visitor Group"

Thanks for visiting my blog!

Mar 30, 2020


Please login to comment.
Latest blogs
Join the Content Recommendations Work Smarter webinar May 8th 16.00-16.45 CET with expert Aidan Swain

Learn more about Content Recommendations, with Optimizely’s very own Senior Solutions consultant, Aidan Swain . He will discuss best practices and...

Karen McDougall | Apr 12, 2024

Plugin for Identifying and Bulk Deleting Orphaned Missing Properties in Optimizely

I am aware that the Optimizely World community has extensively discussed this topic, with numerous solutions and code snippets available to help...

Adnan Zameer | Apr 11, 2024 | Syndicated blog

Enhancing the Authoring Experience: Extending the LinkItem

The LinkItem field is one of the most demanded properties by the community, allowing editors to effortlessly create and manage links across pages a...

Santiago Morla | Apr 10, 2024 | Syndicated blog

The distinctions between Optimizely Web Experimentation and Optimizely Feature Experimentation

This blog is part of the series - Unlocking the Power of Experimentation: A Marketer's Insight. Let’s dive into Optimizely's powerful experimentati...

Holly Quilter | Apr 9, 2024