Content Split

Note: This feature is currently released under our Controlled Availability program. To request access to this feature, please log in to My Oracle Support and create a service request. Availability for this feature is specific to product trim. Contact your account representative for more information.

While we’re not supporting A/B Testing, the custom solution below is what we can do.

Randomized audience split is done with JavaScript that selects one of the coupled content nodes and renders it persistently.

This component depends on the Cookie Component, so please implement it prior to the Content Split.

Establish the Content Split component

This step is performed once for the whole account.

Create a single Web personalization for all your shared scripts. It should go first in alphabetical order. This makes its Content nodes run first on the web page. All the Content nodes in it also run from left to right, as the arrows on the Canvas show.

Copy and paste the following JavaScript code into a Content and set its Location to the whole site.

let callbacks = {};

function getWeights(name) {
  let weights = callbacks[name].weights;

  let totalWeight = weights.reduce((sum, val) => {
    return sum + (val ? val : 0);
  },0);

  let undefinedWeights = weights.filter(function(val) {
    return typeof val === 'undefined';
  });

  if (totalWeight > 100 || totalWeight !== 100 && undefinedWeights.length === 0) {
    throw new Error('Audience split is not configured properly for the ' + name + ' content group. Sum of content weights is not equal to 100.');
  }

  let equalSplitWeight = (100 - totalWeight) / undefinedWeights.length;
  return weights.map((val) => val === undefined ? equalSplitWeight : val);
}

function inRange(val, min, max) {
  return (val - min) * (val - max) <= 0;
}

function runOne(name) {
  let variantIndex = data.global.cookie(name);

  if (typeof variantIndex === 'undefined') {
    let weights = getWeights(name);
    let weightRange = [];
    let randomUnder100 = parseInt(+new Date() / 100, 10) % 100;

    weights.forEach(function(val, index) {
      let prev = weightRange[index - 1] ? weightRange[index - 1][1] : 0;
      weightRange.push([prev, prev + val]);
      if (inRange(randomUnder100, prev, prev + val)) {
        variantIndex = index;
      };
    });
  }

  data.global.cookie(name, variantIndex, 365);

  callbacks[name].handlers[variantIndex]();
  delete callbacks[name];
}

data.global.split = function(config, callback) {
  if (typeof config === 'string') {
    config = {
      name: config
    }
  }

  if (!callbacks[config.name]) {
    setTimeout(function() {
      runOne(config.name);
    }, 0);
    callbacks[config.name] = {
      handlers: [callback],
      weights: [config.weight]
    };
  } else {
    callbacks[config.name].handlers.push(callback);
    callbacks[config.name].weights.push(config.weight);
  }
}

Perform traffic split under a Web personalization

This is done for each Content you want to be part of an A/B test.

As soon as the Content Split component is set up, you can call it from any Content. Use the following syntax:

data.global.split(settings, variantCodeWrapper);

Where settings is either a string, accepting the test name, or an object comprised of the test name and variant weight. Here’s a detailed description of the arguments.

Argument Name

Description Type

settings

You could either pass a name of the group the variants belong to, or an object containing both the group name and the variant weight in percentage from the available traffic.

You could use Web personalization’s name as the group name, i.e. info.campaign.name

Here's the string notation:

info.campaign.name

and the object notation:

{
  name: info.campaign.name,
  weight: 50
}

String or Object

variantCodeWrapper

A function that holds all the variant JavaScript code. It can also use the data.html and data.css values to incorporate the corresponding code of that content.

Function

Example 1

data.global.split(info.campaign.name, function() {
  document.querySelector('.btn-confirm').innerText = 'Purchase now';
});

Example 2

data.global.split({
  name: info.campaign.name,
  weight: 20
}, function() {
  document.querySelector('.btn-confirm').innerText = 'Purchase now';
});

Learn more

Web Personalization Canvas - Learn more on setting up a web personalization

Web Personalization Content Editing - Understand content editing capabilities