Split URL Testing (Different Page Versions)
Split URL testing is a variant of A/B testing where control and variant are hosted on different URLs. Unlike standard A/B testing (one page, DOM changes via JS), Split URL is used when versions are fundamentally different and impractical to keep both in one template.
When to Use Split URL Testing
- Completely new page design vs old version
- Comparing two different landing pages
- Testing new checkout flow vs old one
- Comparing different CMS/platforms for one page
- Landing page on different technologies (React SPA vs static HTML)
Setup via nginx
# Random traffic split 50/50
split_clients "${remote_addr}${http_user_agent}${date_gmt}" $split_variant {
50% "variant";
* "control";
}
server {
listen 80;
server_name company.com;
location = /landing {
if ($split_variant = "variant") {
rewrite ^ /landing-v2 last;
}
# control - stays on /landing
}
# Persist variant in cookie for consistency
location = /landing {
if ($cookie_ab_landing = "variant") {
rewrite ^ /landing-v2 last;
}
if ($cookie_ab_landing = "control") {
# keep
}
# Assign and redirect
add_header Set-Cookie "ab_landing=$split_variant; Path=/; Max-Age=2592000; SameSite=Lax";
}
}
Setup via Cloudflare Workers
addEventListener('fetch', event => {
event.respondWith(handleSplitTest(event.request))
})
const CONTROL_URL = 'https://company.com/checkout-v1'
const VARIANT_URL = 'https://company.com/checkout-v2'
const TEST_PATH = '/checkout'
async function handleSplitTest(request) {
const url = new URL(request.url)
if (url.pathname !== TEST_PATH) {
return fetch(request)
}
// Check cookie for stickiness
const cookie = request.headers.get('Cookie') || ''
const cookieMatch = cookie.match(/split_checkout=([^;]+)/)
let variant = cookieMatch ? cookieMatch[1] : null
if (!variant) {
// Deterministic assignment by IP + UA
const key = request.headers.get('CF-Connecting-IP') + request.headers.get('User-Agent')
const hash = await hashKey(key)
variant = (hash % 2 === 0) ? 'control' : 'variant'
}
const targetUrl = variant === 'variant' ? VARIANT_URL : CONTROL_URL
const response = await fetch(targetUrl, request)
// Clone response to add cookie
const newResponse = new Response(response.body, response)
if (!cookieMatch) {
newResponse.headers.append('Set-Cookie',
`split_checkout=${variant}; Path=/; Max-Age=2592000; SameSite=Lax`)
}
return newResponse
}
Canonical Tags for SEO Duplicate Prevention
Important: two URLs with similar content without canonical → duplicate issue:
<!-- /landing-v2 (test version) -->
<link rel="canonical" href="https://company.com/landing">
<!-- Or if test is temporary, add noindex on variant -->
<meta name="robots" content="noindex, follow">
If both URLs should temporarily be indexed — use rel="alternate":
<link rel="alternate" href="https://company.com/checkout-v2">
Analytics Tracking
// On both page versions — send event with variant
const variant = getCookieValue('split_checkout') || 'control'
// GA4 Custom dimension
gtag('set', 'user_properties', {
split_test_checkout: variant
})
// Or as event parameter
gtag('event', 'page_view', {
split_test: 'checkout_redesign',
split_variant: variant
})
// On conversion
gtag('event', 'purchase', {
transaction_id: orderId,
value: total,
split_test: 'checkout_redesign',
split_variant: variant
})
-- GA4 BigQuery: conversion by Split URL test variants
SELECT
user_properties.value.string_value AS variant,
COUNT(DISTINCT user_pseudo_id) AS users,
COUNT(DISTINCT CASE WHEN event_name = 'purchase' THEN user_pseudo_id END) AS converters,
ROUND(COUNT(DISTINCT CASE WHEN event_name = 'purchase' THEN user_pseudo_id END) * 100.0 /
COUNT(DISTINCT user_pseudo_id), 2) AS cvr
FROM `project.analytics.events_*`,
UNNEST(user_properties) AS user_properties
WHERE user_properties.key = 'split_test_checkout'
GROUP BY variant;
Post-Test: Promoting the Winner
If variant won — replace control and remove split:
# Remove split, serve v2 to everyone
location = /checkout {
rewrite ^ /checkout-v2 last;
}
# Or rename /checkout-v2 to /checkout
Update canonical and remove noindex/alternate tags.
Delivery Time
Setting up Split URL test with cookie stickiness, analytics, and SEO protection — 1–2 business days.







