Split Testing
The Split Testing integration enables the A/B Promo module, which allows users to publish different variants of content and track the performance of the original promo vs. its variants. The Split Testing integration must be enabled for a site for the A/B Promo module to be available for use. Currently, no themes have been styled to include the A/B Promo, so custom Javascript must be added to the site.
To enable the Split Testing integration:
- Click > Admin > Sites & Settings.
- In the Sites widget, click Global. The Edit Global widget appears. (To enable Split Testing for a specific site only, select that site.)
- Click , located to the left of , and type Advanced.
- Under Custom Scripts and Styles, click .
- Enter a name for Internal Name for the custom element.
- Click Add under Elements and select Script Element.
- Enter a name for Internal Name for the script element.
- Enter the Javascript required by the front end to support the A/B Promo module. See the reference code below.
- Click Save.
Reference implementation code for front-end developers:
window.addEventListener('load', event => {
let nodes = []
let iterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_ALL,
() => NodeFilter.FILTER_ACCEPT,
false
)
let current
while ((current = iterator.nextNode())) {
if (current.nodeType == Node.COMMENT_NODE) {
let comment = current.nodeValue
if (comment.startsWith('SplitStart')) {
let [_, id, numOfVariants, testAudiencePercentage] = comment.split(' ')
// This assumes that there will only be one node between the opening and closing comments
let openingCommentNode = current
let contentNode = openingCommentNode.nextSibling
let closingCommentNode = contentNode.nextSibling
// Clean-up
openingCommentNode.remove()
closingCommentNode.remove()
nodes.push([contentNode, id, numOfVariants, testAudiencePercentage])
}
}
}
nodes.forEach(element => {
let [content, id, numOfVariants, testAudiencePercentage] = element
// Select the variants randomly but remain consistent across page loads
let selection = localStorage.getItem('variant.' + id)
if (selection == null) {
// Determine if user is to be part of the test audience
if (Math.floor(Math.random() * 100) < testAudiencePercentage) {
// Generate random integer between 1 and the number of variants, inclusive of 1
selection = Math.floor(Math.random() * (numOfVariants - 1)) + 1
} else {
// Select Original
selection = 0
}
localStorage.setItem('variant.' + id, selection)
}
fetch('?renderedSplitId=' + id + '&variantSelection=' + selection)
.then(response => response.json())
// Converts string from json into html fragrment
.then(json =>
document.createRange().createContextualFragment(json.fragment)
)
// Grabs the node from Fragment
.then(fragment => fragment.firstChild)
// Adds node to DOM
.then(node => {
content.replaceWith(node)
return node
// Adds listener to track clicks
})
.then(node => {
node.querySelectorAll('a').forEach(a => {
a.addEventListener('click', () => {
fetch('/_split', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body:
'trackMode=click&splitId=' + id + '&splitVariant=' + selection
})
})
})
// Reports impression
})
.then(() =>
fetch('/_split', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body:
'trackMode=impression&splitId=' + id + '&splitVariant=' + selection
})
)
})
})
Previous Topic
Deprecating and deleting production guides
Next Topic
Sitemaps