How We Overcame the Speed Impact of Anti-flicker Snippet (A Case Study)
Dec 7, 2020
How We Overcame the Speed Impact of Anti-flicker Snippet (A Case Study)
Dec 7, 2020
Introduction
The marketing team at one of our clients wanted to undertake A/B tests for their landing pages without needing any intervention from the tech team. As they started the A/B tests, we observed that the landing pages under experiment experienced a speed degradation. We then set on course to achieve a setup where:
This post details our experience & findings to achieve such a setup.
About Our Site & Setup
To set the context, below are the details of the site setup:
Example Landing Page
For the purpose of this blog post, we have created a demo landing page (to avoid disclosing client specific information). We have also set up Google Optimize A/B test experiments for this page. You can see the demo landing page here (without any A/B tests configured for it). Below snapshot shows how this page loads without any A/B tests configured for it:
Why was an Anti-flicker Snippet Required?
When the A/B tests were originally configured, no anti-flicker snippet was added. Google Optimize's JavaScript (that controlled rendering of A/B test variants) was added to the site via Google Tag Manager. However, this resulted in a "flicker effect". The loading snapshot below shows this via our demo landing page:
This flicker effect raised two issues:
To overcome these two issues, an anti-flicker snippet provided by Google Optimize (here) was added directly to the landing page code.
How the Anti-flicker Snippet Changed Page Loading Behavior
The anti-flicker snippet resulted in the page content remaining invisible untill the Optimize JavaScript came into action. The loading snapshot below shows this change of behavior via our demo landing page:
As seen above, the anti-flicker snippet addressed the two issues highlighted earlier. The undesirable flicker during loading was avoided and the page content was only displayed as controlled by the A/B test tool. This maintained the sanctity of the A/B test experiment.
Speed Impact of Anti-flicker Snippet
A side-effect of adding the anti-flicker snippet was that the page content started to render a lot later. This translated into PageSpeed score degradation of ~16 points for our landing page:
A similar speed degradation can be seen via our demo landing page. As seen in the loading snapshots above, the start render happens at ~3 seconds with the anti-flicker snippet as compared to ~1.5 seconds without it. The below table captures these numbers:
Landing Page Type | Start Render | Speed Index |
Landing page without any A/B test setup | 1.5 sec | 2.0 sec |
Landing Page with A/B test setup | 1.5 sec | 3.0 sec |
Landing Page with A/B test and anti-flicker setup | 3.0 sec | 3.0 sec |
How We Addressed the Speed Impact of the Anti-flicker Snippet
Anti-flicker snippet hides the entire page content till the A/B test tool's JavaScript kicks into action. An alternative to this could be to selectively hide only those parts of the page that are controlled by the A/B test. With this in mind, we created a modified version of the anti-flicker snippet. This resulted in a page-loading sequence as following:
As seen in the loading snapshots above, with the modified anti-flicker snippet:
With the modified anti-flicker snippet, the start render time got back to 1.5 seconds from the earlier observed 3.0 seconds:
Landing Page Type | Start Render | Speed Index |
Landing page without any A/B test setup | 1.5 sec | 2.0 sec |
Landing Page with A/B test setup | 1.5 sec | 3.0 sec |
Landing Page with A/B test and anti-flicker setup | 3.0 sec | 3.0 sec |
Landing Page with A/B test and optimized anti-flicker setup | 1.5 sec | 3.0 sec |
Our Modified Anti-flicker Snippet
Below is the modified anti-flicker snippet we added to our landing pages code directly:
<script>
function hideOptimizeElements()
{
for (e in googleOptimizeEleList)
document.querySelector(googleOptimizeEleList[e]).style.opacity=0;
}
function showOptimizeElements()
{
for (e in googleOptimizeEleList)
document.querySelector(googleOptimizeEleList[e]).style.opacity=1;
}
hideOptimizeElements();
setTimeout(showOptimizeElements, 4000);
</script>
We requested the marketing team to modify the the code snippet to load Google Optimize as following (notice the onload
attribute):
<script async src="https://www.googleoptimize.com/optimize.js?id=<GTM-XYZXYZ>"
onload="showOptimizeElements();"></script>
As can be seen above, rather than controlling the opacity of the entire document, the above snippet controls opacity of elements within a list googleOptimizeEleList
. googleOptimizeEleList
is expected to be a list of query selectors for container-element that is part of the A/B test experiment. We leveraged our CMS to populate the value for googleOptimizeEleList
.
How We Incorporated Modified Anti-flicker in our Workflow
In order to incorporate the modified anti-flicker snippet, we required a way by which the marketing team could provide the query selector for in-experiment element(s). To achieve this, we requested the marketing team to:
Our front-end code was setup to fetch the selector from the CMS and add it to the googleOptimizeEleList
list. In this way, whenever the marketing configured an A/B test, they performed an additional step of letting the site know the elements to hide via the CMS. The site page concealed only part of the page instead of the complete page.
Limitations of Our Approach
While the solution suggested above is the best-fit for our setup, following are it's limitations:
Conclusion
A/B testing tools need to evolve to facilitate server-side handling of A/B tests. Untill that happens, an early start render can be achieved via our modified anti-flicker snippet (albiet some restrictions as listed above).
Also Read