Split URL Testing

Overview

Split URL tests route visitors to entirely different pages (URLs) to compare performance. Convert supports two ways to run them:

  1. Split URL Experience Type (recommended) — Handles everything automatically
  2. Manual redirects — Using convert.redirect() and convert.refresh() in other experience types

How Split URL Bucketing Works

Unlike standard A/B tests where variations modify the current page, split URL tests require navigation — the visitor must be sent to a different URL. This creates a challenge: how do you count the visitor if the redirect might fail?

Convert solves this with a deferred bucketing mechanism:

sequenceDiagram
    participant V as Visitor
    participant S as Script
    participant C as Cookie
    participant B as Backend

    V->>S: Loads original page
    S->>S: Decides variation
    S->>C: Stores decision in _conv_sptest (15s TTL)
    S->>V: Redirects to variation URL (or refreshes original)
    V->>S: Loads target page
    S->>C: Reads _conv_sptest
    S->>B: Sends bucketing event
    S->>C: Deletes _conv_sptest

The Three Phases

  1. Decision — The script decides which variation the visitor gets and stores the decision in the _conv_sptest cookie (15-second TTL)
  2. Navigation — The visitor is redirected (variation) or the page is refreshed (original)
  3. Tracking — After the page loads, the script reads the split cookie, sends the bucketing event, and deletes the cookie

Key insight: The visitor is only counted after navigation succeeds. If the redirect fails (network issue, JavaScript blocked, visitor closes tab), the visitor is never counted. This prevents Sample Ratio Mismatch (SRM).

Why We Refresh the Original

You might wonder: why does the original variation also require a page refresh? The answer is symmetry.

If only the variation redirects, then:

  • Original visitors are counted immediately (no navigation barrier)
  • Variation visitors are counted only after successful redirect
  • This creates SRM because the original includes visitors who would have abandoned during redirect

By refreshing the original, both variations go through the same flow:

  • Both break page execution
  • Both require successful navigation to be counted
  • Failed navigations are excluded equally from both groups

Manual Redirect API

When using A/B or Multivariate experience types with manual redirects, use these methods:

convert.redirect(url)

Navigates the visitor to the specified URL. Use in Variation JavaScript.

// Variation JS
convert.redirect('/new-landing-page');

convert.refresh()

Reloads the current page. Use in Original Variation JavaScript to pair with the redirect.

// Original Variation JS
convert.refresh();

Correct Pattern

// Original Variation JS
convert.refresh();

// Variation JS
convert.redirect('/new-landing-page');

Common Mistakes

MistakeWhy It Causes SRM
Putting redirect() in ExperienceJS instead of VariationJSOriginal visitors bypass the navigation barrier entirely
Missing refresh() in Original VariationJSOriginal is counted immediately; variation is counted after redirect
Conditional redirect logic (if (url === X) redirect(Y))Some visitors redirect (counted after), others stay (counted immediately)

The Split Cookie

The _conv_sptest cookie has a deliberately short lifetime:

  • 15-second TTL — Prevents stale bucketing data from persisting
  • Always written — Even when cookie consent hasn't been given (it's strictly functional)
  • Deleted after use — Removed once the bucketing event fires

If navigation doesn't complete within 15 seconds, the cookie expires and the visitor is bucketed fresh on the next page load.

When to Use the Split URL Experience Type

The dedicated Split URL experience type is recommended because it:

  • Handles refresh/redirect pairing automatically
  • Prevents the common SRM mistakes listed above
  • Supports "Transfer Original URL variables to the variation URL" for query parameter preservation
  • Handles all edge cases without custom JavaScript

Use manual redirects only when you need complex conditional logic that the Split URL experience type can't express.

When a Browser or Extension Blocks the Redirect

A split URL test only counts a visitor once the navigation succeeds, so anything that stops the
navigation costs you that visitor. Before the redirect, the script cancels the page's own in-flight
requests so a heavy entry page cannot starve its own redirect. That cancellation cannot be undone —
so if something then blocks the navigation, the visitor is left on a page that stopped loading
part-way through.

In practice this is rarer than it sounds, and most of the conditions that sound alarming turn out to
be harmless. What matters is that losing a visitor from your counts and showing that visitor a
broken page are two different outcomes
, and the common conditions cause only the first.

ConditionWhat the visitor seesEffect on your test
An ad blocker or privacy extension blocks the Convert script — by far the most common setupThe normal page, exactly as if no test were runningThe visitor is never entered into the test at all, so your split stays balanced
An extension blocks the destination URL itself (for example uBlock Origin's strict blocking)The extension's own block page, with an option to proceedThe visitor is not counted — a possible source of SRM
An extension or a script on your own site cancels programmatic navigationThe original page, stopped part-way through loadingThe visitor is not counted — a possible source of SRM
Your page is served with a Content-Security-Policy: sandbox policy that allows scripts but not top-level navigationThe original page, stopped part-way through loadingThe visitor is not counted — a possible source of SRM
Firefox's accessibility.blockautorefresh setting is enabledThe destination page — the redirect still worksNone

Two things bound the risk:

  • Only a redirect that runs during page load can leave a partly-loaded page. A
    convert.redirect() you trigger later — from a click handler or a timer, once the page has
    finished loading — has nothing left to interrupt.
  • The visitor needs both halves. They have to be assigned to a redirect variation and have the
    navigation blocked while the script itself was allowed to run. A browser or extension aggressive
    enough to block the navigation usually blocks the Convert script first, which is the harmless
    first row above.

Content Security Policy Is Not a Factor

If you run a strict CSP, it does not interfere with split URL redirects. No CSP directive restricts
where a page may navigate — the navigate-to directive was removed from the specification in
September 2022 and never shipped in any browser, and form-action applies to form submissions only.

Two CSP settings are worth knowing about, both unusual:

  • script-src (or sandbox without allow-scripts) blocking the Convert script stops the test
    running at all. Visitors see your normal page and are not entered into the test.
  • sandbox with allow-scripts but without allow-top-navigation is the one policy that
    lets the script run and then refuses the redirect. If you serve a sandbox policy on the pages
    under test, add allow-top-navigation.

Separately, connect-src and img-src can block the script's own reporting requests. That does not
affect the redirect, but it does hide the evidence — so rule it out before concluding a redirect
failed.

What to Do About It

There is nothing to fix in your test setup for the common cases, and no configuration on Convert's
side changes them — the navigation is refused by the visitor's browser. What helps:

  • Serve the script from a first-party domain. This is the single biggest lever, because it moves
    the most common condition (the script being blocked) out of play.
  • Check your own site's scripts. If anything on your pages intercepts or cancels navigation, it
    will cancel a split URL redirect too.
  • Prefer the Split URL experience type over manual redirects, and keep convert.refresh() in
    the original, so both arms face the same navigation barrier and blocked navigations drop out of
    both groups instead of one.
  • Read SRM in context. Some loss to blocked navigation is expected and affects both arms. Treat
    a persistent, one-sided gap as an implementation problem first — the mistakes table above — not as
    blocker interference.

Debugging

  • SRM warning in the Convert app — Check if Original has significantly more visitors than expected
  • Inspect _conv_sptest — Should appear briefly (15 seconds) after page load
  • Network tab — Bucketing events (/track/ requests) should appear only after redirect/refresh, not before
  • Quick test — If you can trigger bucketing without a page reload, the implementation is incorrect

Did this page help you?