- Choose the correct attributes for deploying Optimizely Web Experimentation as a non-blocking resource
- Avoid page flickering when deploying Optimizely Web Experimentation as a non-blocking resource
If you are looking for better page-load performance, you might consider deploying Optimizely Web Experimentation as a non-blocking resource using either defer
or async
. However, this sometimes causes page flickering, which in turn can generate sub-optimal user experiences.
This article will outline the various considerations around loading Optimizely Web Experimentation as a non-blocking resource.
We strongly recommend that you do not deploy your Optimizely Web Experimentation snippet as non-blocking. These instructions are intended as a last resort, and should not be followed unless you have no other option.
Choose the right attribute for the snippet’s script tag
Loading the Optimizely Web Experimentation snippet as a non-blocking resource (or “less-blocking,” in the case of async
) requires using either the defer
or async
attribute on the script
tag. Each attribute induces different loading behavior from the snippet, so be sure you choose the one that’s most appropriate.
The defer
attribute:
-
Will load the script over the network in parallel to DOM parsing
-
Once the snippet is fetched, script execution will wait until after the browser parses the DOM (immediately after
PerformanceNavigationTiming.domInteractive
and prior toDOMContentLoaded
) -
Guarantees the script will be executed in the order in which it appears in the document, relative to other defer scripts
-
Does not guarantee the script will be executed in the document order relative to synchronous scripts
-
Does not guarantee to be non-render-blocking
Example:
<script src="https://cdn.optimizely.com/js/12345678.js" defer></script>
The async
attribute:
-
Will load the script over the network in parallel to DOM parsing
-
Will execute the script immediately after the snippet is fetched, blocking DOM parsing during execution
-
Does not guarantee the script will be executed in the order in which it appears in the HTML, relative to all scripts
-
Does not guarantee to be non-render-blocking
Example:
<script src="https://cdn.optimizely.com/js/12345678.js" async></script>
Load the snippet programmatically via JavaScript
If you want to ensure the snippet is entirely non-render-blocking, you could load it programmatically via JavaScript, via the window.onload
handler. Window.onload
waits until after the entire page has been fully loaded before firing. This includes all external resources, like images, CSS, scripts, etc.
However, loading Optimizely Web Experimentation this late in the page-rendering process will have other negative impacts, especially relating to pageview and bounce/exit metrics tracking, and the ability to employ a flicker-management solution.
Example:
window.addEventListener("load", function() { var loadScript = document.createElement('script'); loadScript.src = 'https://cdn.optimizely.com/js/PROJECT_ID.js'; document.head.appendChild(loadScript); });
Prevent page flickering
To prevent page-flicker, you will have to mask either the entire page or the portions of the page that your experiment will affect.
To do this, apply visibility: hidden
to certain elements in the DOM, and then remove that rule once after the Optimizely Web Experimentation client has been initialized and has applied synchronous variation changes.
Here is a technical guide that outlines how to employ a masking solution.
Page flickering is only an issue with above-the-fold visual experiments—those that are visible as soon as the page loads. Some examples where page flickering may not be a concern include:
-
Experiments that take place below-the-fold
-
Experiments that take place after some visitor action, like triggering a popup modal
-
Experiments where the snippet is deployed down-funnel, for tracking purposes only
Impact on metrics and integrations
Since async
and defer
affect the predictability of the snippet’s execution timing, it is critical to understand how adding these attributes to your snippet tag might affect your experiment.
Both implementations can potentially lead to broken analytics or audience integrations due to timing issues. Be sure to audit your integrations before deploying the Optimizely Web Experimentation snippet to production using async
/ defer
:
-
When deploying Optimizely Web Experimentation using defer, the snippet generally executes later in the page-load, which means that it is likely to affect your ability to accurately measure pageview and bounce/exit metrics. The benefit of using
defer
is that order of execution will be enforced whenever there are other dependency scripts being loaded withdefer
. -
When deploying Optimizely Web Experimentation using
async
, it is difficult to manage the order of execution against other dependencies.
You may have to refactor any integration code relying on Optimizely Web Experimentation’s getter methods (e.g., get-visitor) to ensure that those API methods are available when they are called. This is best handled with the lifecycle event listener activated.