Integrate ABlyftApplication integration

SPA navigation

Run experiments on single-page applications, where the page changes without a reload.

On a classic website, every click loads a new page and the snippet starts again. In a single-page application (SPA) the browser loads the page once, and your code swaps the content afterwards. ABlyft would then check pages and audiences only once, on the first load.

This page explains the settings and calls that make ABlyft follow your navigation.

What you need to decide

There are two ways to tell ABlyft that "the page has changed". You can combine them.

ApproachHow it worksUse it when
Page triggerABlyft watches the URL or the DOM itself and re-checks a page when something changesYou do not want to touch your application code
ablyft.reInit()Your application calls ABlyft after each navigationYour router offers a hook, or you want full control

Both need the project setting Use SPA features, described next.

Project settings for SPAs

Open your project and go to Settings → Project Settings. The section Project Activations Settings contains:

SettingWhat it does
Use SPA featuresEnables the features for dynamic websites: page triggering via URL Change or DOM Change, and Reset JS.
Run only on ablyft.reInit()The snippet is loaded, but starts only when your code calls ablyft.reInit().
Default Page TriggerThe trigger that newly created pages receive. Default: Direct.

With Use SPA features switched on, ABlyft additionally does the following:

  • Before an experiment is applied again, ABlyft first undoes its previous run: it runs the Reset JS and removes the CSS that the experiment and its variation had added.
  • On every new run of the project, the CSS that ABlyft added to the page is removed and added again, so styles do not pile up.
  • ablyft.reInit() re-initializes all experiments the visitor is already in, so that resets run and goals are applied again.

Without Use SPA features, Reset JS is never run automatically. Switch the setting on before you rely on resets.

Option 1: Let ABlyft detect the navigation

Every page has a Trigger that defines when ABlyft checks the page's targeting. You set it on the page under Targeting & Goals → Pages, in the section Trigger. The default of most projects is Direct: check once, when ABlyft starts.

For SPAs, choose URL Change (history API), URL Change (polling) or DOM Change. What each trigger does is listed in Pages & URL targeting.

At start, ABlyft checks every page once. After that, it checks the page again each time the trigger fires.

Triggers are an advanced setting. If a page runs on a normal, reloading part of your site, leave it on Direct.

What happens on each check

  1. If the page matches (URL rules and optional JavaScript rules) and is not active yet, ABlyft activates it, triggers its pageview goals, and evaluates its experiments (environments, audiences, traffic).
  2. If the page is already active and no longer matches, ABlyft deactivates it. What happens to its experiments depends on the page's deactivation mode.

Deactivation modes

The page's deactivation mode (see Pages & URL targeting) decides whether Reset JS runs and whether the page stays active.

Choose Reset for most cases: the experiment disappears when the visitor navigates away from the page.

Option 2: Call ablyft.reInit() yourself

ablyft.reInit() re-runs ABlyft on the current page: pages and audiences are checked again ("rerun condition check"). Call it from your router after the new view has been rendered.

// Example: call after your app finished rendering a new route
function onRouteChanged() {
  if (window.ablyft && typeof window.ablyft.reInit === 'function') {
    window.ablyft.reInit();
  }
}

reInit() exists only after the snippet has loaded, hence the check. Pushing goals and other commands before that works differently, see queueing.

To start from a clean state, for example after a login or language switch, use ablyft.reInit({ resetStates: true }). The options are described in the JavaScript API.

Run only on ablyft.reInit()

Turn on Run only on ablyft.reInit() if ABlyft should not start on its own. This is useful when the application must be ready first (for example, the first view is rendered or the user data is loaded). The snippet still loads and window.ablyft is available, but experiments only start with your first reInit() call.

Do not forget the call

With this setting on and no reInit() call, no experiment runs at all.

React to ABlyft runs

ABlyft dispatches the ablyft_initialized event on document on every run, including every reInit(), and supports a lifecycleEnd listener that is called after each run. Both are documented in the JavaScript API.

Reset JS

Reset JS is code that undoes what your experiment code did, so that a variation can be removed again without a page reload. You can set it in two places:

  • the experiment: Experiment Level Codes → Reset JS code,
  • a variation: Code → Reset JS code.

ABlyft runs it when an experiment is reset: before the experiment is applied again, and when a page is deactivated in the mode Reset or Force-reset (see above).

For an example with variation code and the matching Reset JS code, see A complete example.

The CSS you added to experiments and variations is removed automatically; you only need to reset what your JavaScript changed. More on code fields: Custom JavaScript.

Which setup should I choose?

Your applicationRecommendation
SPA that uses pushState routingPages with trigger URL Change (… history API), deactivation mode Reset
URL does not change, but views switch (tabs, steps)Trigger DOM Change, or a Callback / API trigger, see Dynamic content
You control the router and want precise timingablyft.reInit() in a router hook, optionally with Run only on ablyft.reInit()

Troubleshooting

  • Experiment shows on the first page but not after navigation: the page still has the trigger Direct, and no reInit() is called. Change the trigger or call reInit().
  • Changes stay when leaving the page: no Reset JS was added, or Use SPA features is off.
  • Experiment runs twice or flickers: both an automatic trigger and reInit() are in use. A page that is already active is not activated again, but pick one approach where possible.
  • Turn on debug mode and watch the console. Every page activation is logged. More in Debugging.

Next steps

On this page