Back to Blog
Implementation Guide

A/B Testing with Cloudflare Workers

Updated December 2026
15 min read
TL;DR

Cloudflare Workers A/B testing: Use Workers to intercept requests, assign variants via cookie, and rewrite HTML at the edge. Benefits: zero flicker, runs globally, minimal latency. Limitations: 50ms CPU limit, no DOM manipulation (use HTMLRewriter). Best for: testing different pages or server-rendered content.

Why Edge-Based Testing?

Benefits

  • • Zero flicker (server-side)
  • • Global distribution (300+ locations)
  • • Low latency (<50ms overhead)
  • • Works without JavaScript

Limitations

  • • 50ms CPU time limit
  • • No visual editor
  • • Requires coding
  • • Limited DOM manipulation

Basic Implementation

// Cloudflare Worker
export default {
  async fetch(request, env) {
    const url = new URL(request.url)
    
    // Get or create user ID
    const cookie = request.headers.get('Cookie') || ''
    let userId = getCookie(cookie, 'user_id')
    if (!userId) {
      userId = crypto.randomUUID()
    }

    // Assign variant
    const hash = await hashUserId(userId)
    const variant = hash % 2 === 0 ? 'control' : 'variant'

    // Fetch original response
    const response = await fetch(request)
    
    // Modify HTML based on variant
    if (variant === 'variant') {
      return new HTMLRewriter()
        .on('h1', {
          element(element) {
            element.setInnerContent('New Headline')
          }
        })
        .transform(response)
    }

    // Set cookies
    const newResponse = new Response(response.body, response)
    newResponse.headers.append('Set-Cookie', `user_id=${userId}; Max-Age=31536000`)
    newResponse.headers.append('Set-Cookie', `experiment_variant=${variant}; Max-Age=31536000`)
    
    return newResponse
  }
}

Using HTMLRewriter

Cloudflare's HTMLRewriter lets you modify HTML as it streams through the edge:

new HTMLRewriter()
  // Change headline
  .on('h1.hero-headline', {
    element(el) {
      el.setInnerContent('New Headline Text')
    }
  })
  // Change CTA button
  .on('button.cta', {
    element(el) {
      el.setAttribute('class', 'cta cta-variant')
      el.setInnerContent('Get Started Free')
    }
  })
  .transform(response)

Note: HTMLRewriter uses CSS selectors. Works well for simple changes, limited for complex modifications.

Tracking Conversions

You'll need to track which variant users saw:

// Client-side tracking
const variant = document.cookie
  .split('; ')
  .find(row => row.startsWith('experiment_variant='))
  ?.split('=')[1]

// Send to analytics
analytics.track('conversion', {
  experiment: 'pricing-headline',
  variant: variant
})

Easier Alternative

Cloudflare Workers are powerful but complex. For most teams, ExperimentHQ offers:

  • • Visual editor (no code needed)
  • • Automatic tracking
  • • Statistical analysis built-in
  • • <5KB script (minimal flicker)

Choose Your Approach

For zero-flicker edge testing: Implement with Cloudflare Workers (requires engineering)

For quick visual tests: ExperimentHQ with minimal setup

Share this article

Ready to start A/B testing?

Free forever plan available. No credit card required.