Skip to main content
menu_icon.png

Everything you need to switch from Optimizely Classic to X in one place: See the Optimizely X Web Transition Guide.

x
Optimizely Knowledge Base

Fix a timing issue

relevant products:
  • Optimizely X Web Experimentation
  • Optimizely X Web Personalization
  • Optimizely Classic

THIS ARTICLE WILL HELP YOU:
  • Fix issues with timing that causes variation content not to appear on your live site
  • Adjust the timing of variation code for elements that don't exist on the page when it first loads

Not all web pages load all content on a page at the same time. Sometimes, some of the content on a page may depend on an AJAXrequestor may be automatically loaded after some delay following the initial page load. If an element doesn't exist on a page when Optimizely's variation code tries to change it, the change may not occur. This is a timing issue.

If you're seeing a timing issue, you'll see variation code load as expected in the Editor, but not on your live site

To fix timing issues, you’ll essentially tell Optimizely to both wait until the element is loaded on the page before changing it, as well as hide the element until Optimizely is able to make the change. This article walks you through a couple of approaches.

Optimizely X

Optimizely X provides a few utilities to help you control the timing of your variation code:

utils.waitForElement(selector);

Use the waitForElement function above to wait for an element before executing a change. This runs just once, when the element is found.

utils.observeSelector(selector, callback, options);

The observeSelector function uses DOM mutation observers to constantly check if an element has changed and run the variation code when a change is detected. This is useful for dynamic content and SPAs, but it's not compatible with all browsers.

Here's where to use them:

  1. Navigate to the Editor. Click the Variation Code Editor icon ().

  2. Select JavaScript to add custom code. Use the utilities above to adjust the timing of your variation code, or find more utilities in our developer docs.

To see an example using an Optimizely utility, click the Help icon () below the Variation Code Editor window.

Optimizely Classic

In Optimizely Classic, use define functions to hide the delayed element and wait to apply variation code when the content loads. There are two ways to set this up: either through Project JavaScript or Experiment JavaScript, depending on your account type.

The code below only applies to experiments set to immediate activation mode, not to experiments set to Manual Activation Mode or Conditional Activation Mode.

Do you have an Optimizely Enterprise Plan? You can load AJAX-based content with conditional activation mode, which lets you specify a code condition that Optimizely will poll every 50ms to check if it's true. Check out this article instead.

If you're a customer with an Enterprise account, use the following global approach with Project JavaScript.

  1. Navigate to Settings JavaScript. 

  2. Then, copy and paste the function into the Project JavaScript code box. You shouldn't need to change or edit the code.

    /* pollForDelayedContent function v1.1.0 */
    window.pollForDelayedContent=function(a,b,c){var d=+new Date,e=50;c=c||{};var f=c.selectorToHide||a,g=c.unhideDelayInMilliseconds||0,h=1e3*c.timeoutInSeconds||null,i=c.intervalInMilliseconds||e,j=function(a){var b="optlyHide_"+ +new Date;return $("head").prepend("<style id='"+b+"' type='text/css'>"+a+" {visibility:hidden !important;}</style>"),function(){$("#"+b).remove()}},k=j(f),l=function(){b(),setTimeout(k,g)},m=function(){var b=+new Date;$(a).length>=a.split(",").length?l():h&&b-d>h?k():setTimeout(m,i)};m()};
    
  3. Then, call the pollForDelayedContent() function as many times as you need to in your variation code.

If you don't have an Enterprise account, use the following approach with Experiment Javascript. You'll do this for every experiment you run.

  1. Navigate to your experiment, then Options > Experiment JavaScript.

  2. Then, copy and paste the following code. You shouldn't need to change or edit the code. The extra comment lines force Optimizely to execute the code within it immediately when Optimizely loads. (In Project JavaScript, this immediate execution happens automatically).

    /* pollForDelayedContent function v1.1.0 */
    /* _optimizely_evaluate=force */
    window.pollForDelayedContent=function(a,b,c){var d=+new Date,e=50;c=c||{};var f=c.selectorToHide||a,g=c.unhideDelayInMilliseconds||0,h=1e3*c.timeoutInSeconds||null,i=c.intervalInMilliseconds||e,j=function(a){var b="optlyHide_"+ +new Date;return $("head").prepend("<style id='"+b+"' type='text/css'>"+a+" {visibility:hidden !important;}</style>"),function(){$("#"+b).remove()}},k=j(f),l=function(){b(),setTimeout(k,g)},m=function(){var b=+new Date;$(a).length>=a.split(",").length?l():h&&b-d>h?k():setTimeout(m,i)};m()};
    /* _optimizely_evaluate=safe */Click Save.
  3. Then, call the pollForDelayedContent() function as many times as you need to in your variation code.

Examples

The pollForDelayedContent() function doesn't necessarily require deep knowledge of jQuery and JavaScript, but it's a technical workaround that may become more complex for certain web pages or Optimizely experiments.

Use the simple example below if you’re less confident about your technical knowledge. The advanced example is handy if you’re more technical and your experiment needs the advanced functionality (most experiments don't).

Here are some extra resources in case you’re not confident about what jQuery is and how Optimizely uses it, and how to manually find selectors on your page.

Simple example (does not use the optional options):

/* pollForDelayedContent function variation code simple v1  */
/* _optimizely_evaluate=force */
window.pollForDelayedContent("selectorToChange", function() {
  // variationCode
});
/* _optimizely_evaluate=safe */

Paste the above code in your variation code, then update each of the following function parameters:

  • selectorToChange: replace this with the selector(s) of the element(s) flashing or appearing dynamically after the initial page load, failing to be changed by your Optimizely changes or loading with a delay on your page. If you use multiple CSS selectors (e.g. 'body, nav.main'), the next argument, “variationCode” won't run unless each comma separated CSS selector is present on the page at least once. 

  • variationCode: replace with your variation code (the code in the < Edit Code > section of your experiment variation).

Advanced example (this does use the optional options):

/* pollForDelayedContent function variation code advanced v1  */
/* _optimizely_evaluate=force */
window.pollForDelayedContent("#selectorToChange", function() {
  // variationCode
}, {
 selectorToHide : 'img',
 unhideDelayInMilliseconds: 500,
 timeoutInSeconds : 5,
 intervalInMilliseconds : 100
});
/* _optimizely_evaluate=safe */

Paste the above code in your variation code. Then, update any needed function parameters and remove any optional, unneeded parameters. 

  • selectorToChange: replace this with the selector(s) of the element(s) flashing or appearing dynamically after the initial page load, failing to be changed by your Optimizely changes or loading with a delay on your page. If you use multiple CSS selectors (e.g. 'body, nav.main'), the next argument, “variationCode” won't run unless each comma separated CSS selector is present on the page at least once. 

  • variationCode: replace with your variation code (the code in the < Edit Code > section of your experiment variation).

  • selectorToHide: (optional) change value from img to the selector of the element that’s flashing or not appearing on your page. Replaces selectorToChange as the element to hide until variationCode has been executed.

  • unhideDelayInMilliseconds: (optional) Replace 500 in above example to set the time in milliseconds before selectorToChange (or selectorToHide if provided) is unhidden after variationCode runs. If this argument is not specified, there is no timeout.

  • timeoutInSeconds: (optional) Replace 5 in example above to set the time in seconds the pollForDelayedContent() function will take to "timeout" or stop trying. If this argument is not specified, the pollForDelayedContent() function will never timeout.

  • intervalInMilliseconds: (optional) Replace 100 to set the time in milliseconds the pollForDelayedContent() function will wait between checking for the selectorToChange (or selectorToHide if provided). If this argument is not specified, the pollForDelayedContent() function will be set up to poll every 50 milliseconds.

Avoid copying and pasting all of your variation code (the code in the < Edit code > section of your variation) into the variationCode placeholder. Just add the lines of code that apply to the selectorToChange element. Pasting all variation code changes could cause your other pages changes to be delayed until the selectorToChange element is found.

The pollForDelayedContent() function uses a recursive JavaScript timeout instead of a JavaScript Interval. This is more performant than a JavaScript Interval, but still can affect page performance. If you're concerned, work with your web development team to decide if this approach is right for you.