Try our conversational search powered by Generative AI!

Sanjay Kumar
Mar 30, 2020
  2646
(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

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 http://nuget.episerver.com/feed/packages.svc/ 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.

Note:

  • 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

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.

CODE

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
};

visitorGroupList.Add(viewModel);
}
}
}

return visitorGroupList;
}
}
Controller

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.

  [RoutePrefix("v1/google/analytics")]
  public class AnalyticsController : Controller
  {
        private readonly AnalyticsViewModelFactory _analyticsViewModelFactory;
        public AnalyticsController(AnalyticsViewModelFactory analyticsViewModelFactory)
        {
            _analyticsViewModelFactory = analyticsViewModelFactory ?? throw new ArgumentNullException(nameof(analyticsViewModelFactory));
        }

        [HttpGet]
        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

Comments

Please login to comment.
Latest blogs
Optimizely and the never-ending story of the missing globe!

I've worked with Optimizely CMS for 14 years, and there are two things I'm obsessed with: Link validation and the globe that keeps disappearing on...

Tomas Hensrud Gulla | Apr 18, 2024 | Syndicated blog

Visitor Groups Usage Report For Optimizely CMS 12

This add-on offers detailed information on how visitor groups are used and how effective they are within Optimizely CMS. Editors can monitor and...

Adnan Zameer | Apr 18, 2024 | Syndicated blog

Azure AI Language – Abstractive Summarisation in Optimizely CMS

In this article, I show how the abstraction summarisation feature provided by the Azure AI Language platform, can be used within Optimizely CMS to...

Anil Patel | Apr 18, 2024 | Syndicated blog

Fix your Search & Navigation (Find) indexing job, please

Once upon a time, a colleague asked me to look into a customer database with weird spikes in database log usage. (You might start to wonder why I a...

Quan Mai | Apr 17, 2024 | Syndicated blog

The A/A Test: What You Need to Know

Sure, we all know what an A/B test can do. But what is an A/A test? How is it different? With an A/B test, we know that we can take a webpage (our...

Lindsey Rogers | Apr 15, 2024

.Net Core Timezone ID's Windows vs Linux

Hey all, First post here and I would like to talk about Timezone ID's and How Windows and Linux systems use different IDs. We currently run a .NET...

sheider | Apr 15, 2024