The availability of features may depend on your plan type. Contact your Customer Success Manager if you have any questions.
Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Page activation

Describes how to use polling and callback to activate a page.

Conditional activation mode is a flexible and powerful way to activate a page and its associated experiments. There are two ways to use it

  • Polling – You enter a condition and Optimizely Web Experimentation activates the page once that condition is true.
  • Callback – You enter a function and trigger a callback once your code is ready for the page to activate.

Based on the code you enter, Optimizely automatically determines if it should be polled for or executed as a function. See the examples for detailed usage definitions.

Polling

If the code entered does not evaluate to a function type, it is checked every 50 milliseconds, and the page is activated when it evaluates to true. Optimizely checks this code in a try/catch block, so a condition that results in an error is assumed to be false and polling continues.

/*
 * Usage Option #1 - Polling
 *   Optimizely polls for the code condition to be true if the JavaScript
 *   entered does not evaluate to a function type.
 *
 *  Note: Optimizely evaluates this code in a try/catch block, meaning
 *  if your expression errors, it evaluates as false. Timeout is two seconds.
 */

 // check if butter bar is in the DOM
 document.getElementById("butter-bar-flash-sale") !== null;

/*
 * Usage Option #2 - Callback Function
 *   Optimizely calls the function entered immediately if the JavaScript entered
 *   does evaluate to a function type.
 *
 * @param {Function} activate - Activate this Page
 * @param {Object=}  options {
 *                     isActive : {Boolean} - Indicates if this page is active
 *                     pageId : {String} - ID of the activated Page
 *                   }
 *
 *  Note: Optimizely calls this function immediately when the snippet loads, so make
 *  sure any functions referenced are defined at that time.
 */

 function(activate, options) {
   // Do logic and call `activate()` when appropriate
 }

Polling – Meta tag data

To activate an experiment based on the value of a meta tag, select the contents of the meta tag with jQuery and check them for your value.

<meta name="keywords" content="movies,games,videos,photos"/>
/*
 * Condition: Activate when the description meta tag contains 'sports', 'games', or 'puzzles'
 * Type: Polling
 */

 (/sports|games|puzzles/).test($('meta[name=keywords]').attr('content'))

Polling – JavaScript variable

To activate an experiment based on the value of a JavaScript variable, enter the condition to check.

/*
 * Condition: Activate when the Omniture eVar 33 contains 'product'
 * Type: Polling
 */

 window.s.eVar33.indexOf('product') != -1

Polling – DOM element

To activate an experiment based on the existence of a DOM element, select that element and check the length of the result.

/*
 * Condition: Activate when the green button DOM element appears
 * Type: Polling
 */

 function pollingFn() {
   return document.querySelectorAll("button.green").length > 0;
 }

Callback function

If the code entered is a function, Optimizely assumes it is of the form shown here and calls it immediately, passing an activate function and an options object. Rather than returning a value, your code should call activate() when it's ready, using options.isActive and options.pageId if needed. Because this function is called immediately when the Optimizely snippet loads, any functions or variables referenced here should be available/defined at the time they're used.

📘

Note

No matter which method is used, remember that this is only an activation condition. Visitors must still meet URL and audience targeting to actually be bucketed into any experiments.

Callback function – Button click

To activate an experiment when a button is clicked, bind a click or mousedown event to that element using jQuery and activate the experiment when that event fires.

/*
 * Condition: Activate when a button is clicked
 * Type: Callback function
 */

 function(activate, options) {
   // following line assumes you are including jQuery in your Optimizely snippet
   var $ = window.optimizely.get('jquery');

   $('html').on('mousedown', '#btn', function() {
     activate();
   });
 }

Callback function – AJAX response

To activate an experiment after an AJAX call returns, use jQuery's ajaxComplete function to listen to completed AJAX requests. If the response contains or corresponds to the element that should be changed, activate the experiment.

📘

Note

Optimizely's default (trimmed) version of jQuery doesn't contain the ajaxComplete function. To use this function, you can include the full version of jQuery in your Optimizely snippet (Project Settings -> Project Code Settings) or reference your own version of jQuery that loads above the Optimizely snippet via window.$.

You can disable $.ajaxComplete on your site if the AJAX setup is called with global option set to false, preventing this event from firing. See jQuery's documentation for more information.

/*
 * Condition: Activate when an AJAX call contains the element that should be changed
 * Type: Callback function
 */

 function(activate, options) {
   // following line assumes you are including (full version of) jQuery in your Optimizely snippet
   var $ = window.optimizely.get('jquery');

   $(document).ajaxComplete(function(event, xhr, settings) {
     if (xhr.responseText.indexOf('rightRailModule') != -1) {
       activate();
     }
   });
 }

Callback function – DOM mutation activation

To activate an experiment based on a DOM element either changing or appearing on the page, make the following call in your experiment's conditional activation code box:

function(activate, options) {
  window.activateOnDOMMutation('#element:not(.changed)', activate, true);
}

The first part of the call, #element:not(.changed), is a DOM element selector you would like to monitor. Any time this element displays on the page or is changed, the experiment is activated once or multiple times depending on the last parameter. You can use any DOM selector that can be used with jQuery. If you change the selected element or its children in the variation code, you create an infinite loop. You can prevent this by excluding selectors with an added class, as shown in the code example. You would add the ".changed" class in the experiment code.

The second part of the call, activate, activates the experiment with the given ID.

The last parameter, true, tells the DOM mutation call that you want to reactivate the experiment every time the selector changes or is added to the page. Adding false here activates the experiment once. This is useful when you are appending content to the page and you do not want to append every time the DOM selector changes.

/*
 * Condition: Activate when the dom selector changes on the page
 * Type: Callback Function
 *
 * Place the following code in your Project Javascript and call the function below in your experiment's
 * conditional activation code box:
 *
 * window.activateOnDOMMutation('#element', window['optimizely'].push(["activate", EXPERIMENT_ID]), true);
 * @param '#element': DOM Selector of element you'd like to watch
 * @param 'window['optimizely'].push(["activate", EXPERIMENT_ID])': Replace EXPERIMENT_ID with the current
 * experiment's ID
 * @param 'true': True re-activates the experiment on the DOM selector changing or being added to the DOM.
 * False activates the experiment only the first time the selector is added or updated.
 */

(function(win) {
    'use strict';

    var listeners = [],
        doc = win.document,
        MutationObserver = win.MutationObserver || win.WebKitMutationObserver,
        observer;

    function waitForElement(selector, repeat, fn) {

        // Store the selector and callback to be monitored
        listeners.push({
            selector: selector,
            fn: fn,
            repeat: repeat,
        });
        if (!observer) {
            // Watch for changes in the document
            observer = new MutationObserver(check);
            observer.observe($(document), {
                childList: true,
                subtree: true
            });
        }
        // Check if the element is currently in the DOM
        check();
    }

    function check() {
        // Check the DOM for elements matching a stored selector
        for (var i = 0, len = listeners.length, listener, elements; i < len; i++) {
            listener = listeners[i];
              // Query for elements matching the specified selector
              elements = $(listener.selector);
              for (var j = 0, jLen = elements.length, element; j < jLen; j++) {
                 element = elements[j];
                if (!element.ready || listener.repeat) {
                     // Invoke the callback with the element
                      listener.fn.call(element, element);
                  }
             }
        }
    }

    function activateOnDOMMutation(selector, activate, repeat) {
      repeat = repeat === undefined ? false : repeat;
      if (window.MutationObserver || window.WebKitMutationObserver) {
        waitForElement(selector, repeat, function(element) {
           activate();
        });
      } else {
        // this solution does not handle older browsers
      }
    }

    // Expose functions
    win.waitForElement = waitForElement;
    win.activateOnDOMMutation = activateOnDOMMutation;

})(this);

Callback activation – Conditionally activated pages

Use jQuery and the native utility functions of Optimizely to activate a page conditionally after a DOM element is found on the page. This method is advantageous to the polling activation type because it's not limited by the two-second timeout after DOM ready.

function callbackFn(activate, options) {
  var utils = window.optimizely.get('utils');
  var $ = window.optimizely.get('jquery');

  utils.waitForElement('button').then(function(buttonElement) {
    if ($('button').length > 0) {
      activate();
    }
  });
}

Callback activation – Custom activation

There might be instances where you want to activate a page following the execution of an asynchronous function. You can use conditional activation to call the external function and pass activate as a callback.

function callbackFn(activate, options) {
    if (window.location.href.indexOf(/* Some URL */) !== -1) {
        options.isActive && activate({isActive: false});
        window.customProcessFunction.init(activate);
    }
}

Use utility functions on dynamic pages

On single-page applications and dynamic websites, content can render or re-render after the initial page load. The utils object from window.optimizely.get('utils') lets your variation code wait for the right DOM state before it runs.

These patterns apply in the following cases:

  • An experiment must reapply variation code each time the application re-renders.
  • An experiment must reactivate when a specific element appears or when a user interacts with the page.

Utility methods

window.optimizely.get('utils') returns two methods for handling asynchronous DOM changes:

  • utils.waitUntil(condition) – Checks a condition repeatedly until it returns true, then resolves a promise. Use it to detect when an element is inserted into or removed from the DOM.
  • utils.waitForElement(selector) – Resolves when a DOM element matching the selector exists. Use it to react to dynamic element insertion.

For full method signatures, see the utils reference.

Reapply variation code when the application re-renders

Single-page applications often remove and re-create elements when the user navigates or interacts. To keep your variation in place, apply it, then use utils.waitUntil to detect removal and reapply the code:

  1. Run your variation function to insert or modify the element.
  2. Pass the element's selector to a watcher that calls utils.waitUntil with the condition !document.querySelector(selector).
  3. When the promise resolves, confirm the URL still matches the experiment's scope, then run the variation function again.
  4. Re-arm the watcher so the next re-render triggers the same cycle.

For a complete example, see the reapply-on-rerender Gist.

Reactivate an experiment when an element is removed

Use this pattern when a route change or render cycle removes an element that the experiment depends on:

  1. Call utils.waitUntil with the condition !document.querySelector(selector).
  2. When the promise resolves, confirm the URL still matches the experiment's scope.
  3. Set the page's isActive state to false, then call the activation function to reinitialize the experiment.

Reactivate an experiment on user interaction

Use this pattern when a user action triggers reactivation, such as a button click:

  1. Call utils.waitForElement(selector) with the selector for the target control.
  2. When the element exists, attach a click (or other) event listener.
  3. Inside the listener, set the page's isActive state to false, then call the activation function.

Best practices

  • Use specific conditions – Broad selectors or weak conditions in waitUntil and waitForElement cause repeated reactivation cycles and increase DOM polling cost.
  • Use robust URL matching – An indexOf check on window.location.href works for static paths. For parameterized routes, use a regular expression or a router-aware comparison.
  • Clean up event listeners and DOM changes – When the experiment deactivates or the user navigates away, remove listeners and revert DOM modifications.
  • Test in production-like states – Exercise the variation across the application's render cycles, route transitions, and interaction paths before launching the experiment.