Integrate ABlyftApplication integration

Dynamic content

Run experiments on content that appears after the page has loaded, such as modals, tabs and AJAX content.

Not everything a visitor sees is there when the page loads. Modals, cart drawers, tabs, checkout steps and content from an API call appear later, often without changing the URL. This page shows how to make ABlyft wait for them.

There are two separate questions:

  1. When should the experiment become active? Solved with the trigger of a page.
  2. When can my variation code change an element? Solved with helper functions in your code.

Make the page wait: choose a trigger

Each page has a Trigger that defines when ABlyft checks the page's targeting. Open Targeting & Goals → Pages, edit the page, and go to the section Trigger.

TriggerUse it when
Direct (immediately when ABlyft runs)The content is part of the page at load (default for most projects)
DOM Change (when something on the page is changing)The page should be active as soon as certain elements exist
Callback (when the callback function is called)You decide in a small piece of JavaScript when the page starts
API (manual activation by an API / JavaScript call)Your own application tells ABlyft when the page starts
URL Change …The URL changes, see SPA navigation

DOM Change trigger

With DOM Change, ABlyft checks the page once at start and then again every time the page changes (elements are added, removed or their attributes change). Changes caused by ABlyft's own code are ignored.

To use it, combine the trigger with JavaScript rules that describe the dynamic content. Open Advanced Targeting in the section Targeting of the page and write a condition that returns true when the content exists:

// Page is active as soon as the cart drawer is open
return document.querySelector('.cart-drawer.is-open') !== null;

The condition is valid if your JavaScript returns true. Inside it you can use ablyftTools.

Two options in Advanced Targeting help with late content:

OptionEffect
Poll on rulesABlyft checks the condition again and again for up to 2 seconds before it gives up. Use it when the element appears shortly after the trigger.
Always embed in snippetUsually not needed. Only enable it if your setup requires it.

DOM Change runs often

A busy page changes its DOM many times per second, and ABlyft checks the page every time. Keep JavaScript rules short and fast, and avoid heavy work in them.

Callback trigger

With Callback, you write the logic. A field for JavaScript appears below the trigger. ABlyft runs your code when it starts (and again on every re-run, for example after ablyft.reInit()). Call activate() when the page should be active. You can also use ablyftTools and page (an object with the page id).

// Activate the page when the checkout step 2 is rendered
ablyftTools.waitForElement('.checkout-step-2', () => {
  activate();
});

Call activate(false) to deactivate the page again, for example when a modal is closed:

document.addEventListener('modal-opened', () => activate());
document.addEventListener('modal-closed', () => activate(false));

activate() still checks the page's URL rules and JavaScript rules. It does not activate the page if they do not match.

API trigger

With API, your own code activates the page with an activatePage call, for example in the handler that opens your modal, and deactivates it with deactivatePage. Setup and calls are described in the Page API.

What happens when the page deactivates

The deactivation mode of the page (Advanced Settings → Deactivation mode) controls whether Reset JS runs and whether the page stays active. See SPA navigation.

Make the code wait: helper functions

Even on an active page, an element may not exist yet. In variation code, use the tools, available as ablyftTools. The variation editor shows a Code Helper with ready-made snippets for the most common ones.

FunctionUse it to
waitForElementRun code for every element that matches a selector as soon as it exists, also elements added later
elementIsInViewRun code when an element scrolls into the viewport
domChangedRun code on every DOM change
domLoadedRun code when the DOM is ready
poll / checkWait for any condition you define
// Variation JS: change a button that is rendered later
ablyftTools.waitForElement('.add-to-cart', (button) => {
  button.textContent = 'Add to basket';
});

waitForElement calls your function once per element. If the element is replaced by your application (for example, re-rendered), the new element is handled too.

Dynamic data: re-check audiences

Audiences are evaluated when an experiment starts. If a value becomes known later, for example a cookie is set or a data layer entry is pushed, tell ABlyft to look again:

ablyft.push({ eventType: 'reevaluateAudiences' });

ABlyft then re-evaluates the audiences of experiments on currently active pages that are not running yet. Visitors who were already excluded from an experiment stay excluded.

For audiences that depend on something happening on the page, you do not need to call it yourself. Audience rules of the type JavaScript Trigger (call activate() when the audience should match) and dataLayer Event trigger the re-check automatically. See Data layer events.

Troubleshooting

  • Page never activates: check the JavaScript rules in the console of your browser and turn on debug mode. Activated pages are logged.
  • Page activates, but the change is not applied: your selector does not match, or the element appears after your code ran. Wrap the change in ablyftTools.waitForElement.
  • Change disappears when the app re-renders: use waitForElement instead of a one-time change, so every new copy of the element is changed.

Next steps

On this page