The Local SEO Testing Problem

For national brands, A/B testing landing pages is straightforward: tools like Optimizely or Google Optimize cost a few hundred dollars a month, and you test one variant against one control for a single domain. For a multi-tenant platform like AiSalonHub, where every salon has its own landing page with unique content, location, and target keywords — traditional A/B testing tools are both too expensive and architecturally wrong.

We needed a way to test:

- Different headline structures for salon service pages

- Various CTA button colors and positions

- Content layout variations (image-first vs text-first)

- Price display formats (range vs exact)

...across 200+ unique salon landing pages, without paying $50/test or managing a complex third-party SDK.

Edge Workers as the Testing Platform

The insight was that Cloudflare Workers sit at the edge — they can modify HTML responses before they reach the browser, at zero additional latency. This makes them a perfect A/B testing layer.

```

Visitor requests salon.aisalonhub.com/studio-x

→ Cloudflare Worker intercepts request

→ Checks A/B test config in KV (which test is active for this salon?)

→ Assigns user to variant (sticky via cookie)

→ Modifies HTML response based on variant

→ Logs impression to D1 analytics table

```

Cookie-Based Assignment

We use a simple cookie approach: when a user first visits any salon page, they get assigned to a variant (A=control, B=variant, C=variant2) based on a hash of their IP + test ID. This ensures:

- **Consistent experience**: Same user always sees the same variant for each test

- **No SDK**: Zero JavaScript on the page — everything happens at the edge

- **No client flicker**: The variant is baked into the HTML before the browser renders

The Worker Modifies HTML, Not CSS

Rather than loading a bulky testing script that swaps DOM elements client-side, our Worker uses HTMLRewriter — Cloudflare's streaming HTML parser — to make surgical changes:

```javascript

class CtaHandler {

element(element) {

if (variant === "B") {

element.setAttribute("class", "cta-button cta-button--green");

element.setInnerContent("Book Now →");

} else if (variant === "C") {

element.replace(`<div class="cta-banner">${newContent}</div>`, { html: true });

}

}

}

```

This means **zero client-side JavaScript, zero layout shift, zero performance impact.**

Results From Our First Round of Tests

| Test | Variant | Conversion Rate | Lift | Statistical Significance |

|------|---------|-----------------|------|-------------------------|

| CTA Color: Blue (control) vs Green vs Red | Green | 4.2% | +18% | p < 0.05 |

| Headline: "Best Salon in [City]" vs "Top-Rated Salon Near You" | Top-Rated | 3.9% | +12% | p < 0.10 |

| Layout: Price list first vs Gallery first | Gallery | 4.5% | +22% | p < 0.01 |

| Social Proof: Testimonials above fold vs below | Above fold | 5.1% | +31% | p < 0.001 |

Cost Analysis

The entire system runs on Cloudflare Workers' free tier:

- **Worker invocation**: ~0.3ms CPU per request — fits in 10ms free allocation

- **KV reads**: 1 million/month free

- **D1 writes**: Analytics logging — 10M rows free

- **Total monthly cost**: **$0**

Compare this to SaaS tools at $100+/month or self-hosted solutions requiring a server. The edge worker approach is literally free for AiSalonHub's current scale.

What Doesn't Work

Not everything should be edge-tested. We found two categories where edge HTML rewriting falls short:

1. **Radically different layouts** — If variant B is a completely different page structure, HTMLRewriter becomes unwieldy. We reserve edge testing for cosmetic/positional changes.

2. **Checkout flows** — Multi-step booking forms need client-side state management. We use a lightweight JavaScript snippet (1KB gzipped) for form A/B tests, served from the same Worker.

Building Your Own

This pattern works for any multi-tenant platform built on Cloudflare Workers:

1. Store test configurations in KV (`ab_test:test_id` → `{ variantA, variantB, salons[], startDate, endDate }`)

2. Use a Worker middleware that intercepts HTML responses

3. Apply HTMLRewriter transforms based on assigned variant

4. Log impressions + conversions to D1

5. Query results with a simple SQL GROUP BY

No CDN config changes, no DNS updates, no third-party scripts. Just a Worker and a few lines of configuration.