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.