Running at the edge on Cloudflare Pages

Do AI engines cite your writing, and does optimizing for them cost you human readers?

The GEO ABCD Testbed is a self-contained split-testing rig that serves four rewrites of the same article from one canonical URL, then measures whether AI engines start citing the page more, and whether humans stop reading it.

Measured across five engines
ChatGPT Perplexity Claude Gemini Copilot
4
competing variants
1
canonical URL
14-day
bot pinning window
0
runtime dependencies
New to this? Start here

What is GEO, in plain English?

A regular search engine hands you a list of blue links to click. The newer answer engines just write the answer for you. GEO is the craft of making sure that when an AI writes that answer, it uses, and credits, your words.

The catch: the same tweaks that make a page easy for a robot to quote can make it duller for a person to read. This project runs both audiences side by side and measures who wins, so optimization never quietly costs you human readers.

Being quoted is the new front page

When an AI answers a question, it may quote a handful of sources and the reader never clicks through. A citation in that answer is now prime real estate.

Four versions compete at once

This is an ABCD test: the same article, rewritten four ways, quietly served from one address. An automated reader (a crawler) or a person each get one version.

Robots and readers, measured together

The framework watches whether AI engines start quoting the page more and whether real people keep reading. Hover any highlighted term for a plain definition.

The tension

Generative engines answer instead of link. Writing for them shouldn't break the page for people.

Generative Engine Optimization (GEO) reshapes content so retrieval systems quote it. But heavier formatting can flatten the reading experience. This framework holds both truths on screen at once: citation lift and human engagement, per variant, concurrently.

Get retrieved & cited

Structure, phrasing, and machine-readable renditions that AI crawlers ingest and quote.

Keep humans reading

Session length and scroll depth tracked per variant, so degradation shows up immediately.

Prove which one won

Attribution watermarks tie a specific AI citation back to the exact variant it came from.

How the test works

Two audiences, two assignment rules

Crawlers and humans answer different questions, so they're split differently. One middleware at the edge routes both from a single URL.

🤖 AI Crawlers

Pinned by calendar window

Each 14-day window maps deterministically to one variant. Every crawler that visits during a window sees the same stable version, so each engine's index holds exactly one variant at a time.

variant = (window % 4) + 1  ·  epoch 2026-07-06 UTC
  • Deterministic & reproducible per window
  • Later AI referral clicks attribute back to the indexed variant
  • Pre-epoch requests clamp to window 0 → v1
👤 Human Readers

Split randomly, held stickily

First visit assigns a random variant via a geo_v cookie scoped to /writing/. Every return visit serves the same one, so engagement is measured cleanly per person.

cookie geo_v · Path=/writing/ · first-party beacon
  • Sticky assignment across return visits
  • Pageviews, session length & max scroll depth reported
  • ~1 KB client beacon that fails silently
Fails safe. Variant files are never addressable directly: direct hits 301 to the canonical URL, a missing variant falls back to v1 instead of a 404, and if anything in the rig throws, the reader just gets the page normally.
The four rewrites

One article, four doses of optimization

A control and three escalating levels of GEO compete head to head. All four state the same facts, only the formatting and phrasing change.

v1

Control

The original article, untouched. The baseline every other variant is measured against.

v2

Light GEO

Gentle structural nudges: clearer headings and lead sentences that read the same to a person.

v3

Balanced GEO

Moderate restructuring for retrievability while protecting narrative flow.

v4

Heavy GEO

Aggressive machine-first formatting, the ceiling of the dose-response curve.

Under the hood

Everything the framework does

A complete measurement pipeline (assignment, serving, telemetry, attribution, and analysis) all at the edge with no runtime dependencies.

Deterministic bot pinning

Calendar-window assignment keeps each engine's index on one stable variant, so citations map cleanly to a version.

Sticky human split & telemetry

A first-party geo_v cookie plus a ~1 KB beacon reports pageviews, session length and max scroll depth per variant.

Attribution watermarks

Each variant states one true fact in unique phrasing at the same position. Grep an AI answer for the string to identify the ingested variant.

Pre-compiled Markdown renditions

A static Markdown file (.md) ships beside each variant and serves on Accept: text/markdown. Deterministic, diffable, drift-free.

Edge CSS inlining

Local stylesheets are inlined at the edge via HTMLRewriter, and the content type on /.well-known/api-catalog is fixed on the fly.

Fail-silent safety valve

Every fallback logs before it degrades. If the rig throws, the reader still gets the page; missing variants fall back to v1, never a 404.

Blocker-neutral ingestion

Neutrally named beacon and endpoint dodge tracker filter lists; a server-side serve_log exposes blocker interference as a delivery gap.

Self-explaining dashboard

A hardened analytics console at /admin/geo with per-section help, glossaries, delivery colour legends, and CSV export.

CSP-hardened & self-hosted

No third-party runtime scripts. A pinned, self-compiled stylesheet and per-request nonce'd CSP lock the admin surface down.

Single source of truth

Slug, epoch, windows, bot list and watermarks all live in one config.js that the router and dashboard both import.

The attribution problem, solved

Referrers prove an engine sent traffic. Watermarks prove which variant earned the citation.

Because bot pinning rotates variants, every engine's index eventually holds all four, so a referral timestamp can't say which version was quoted. Instead, each variant phrases the same true fact uniquely. When an AI answer reproduces one of those strings, it names the source. npm run build refuses to ship if any output is missing its own watermark or carries another's.

The analytics console

Read the whole experiment on one page

The /admin/geo dashboard turns raw D1 rows into three answers, with plain-English help, click-to-explain tooltips, and a colour-coded delivery legend built in. Here is the current build, reading seeded test data:

The GEO Lab dashboard at /admin/geo reading seeded test data. A human-engagement table lists variants v1 to v4 with serves, views, delivery percentage, visitors, average session, average scroll, and bounce, with the balanced v3 badge ringed gold as the live variant. Beacon delivery by traffic source shows the AI audience lowest at 64.2 percent, and a bot-windows table counts crawler hits and AI referral clicks per fourteen-day window.
The console reading seeded sample data so every panel is exercised: balanced (v3) is live and leads on engagement, heavy (v4) draws the most crawler attention while its human numbers slip, and the AI-referred audience shows the lowest beacon delivery where the blockers cluster.
Engagement

Are humans still reading?

Pageviews, average session length and max scroll depth per variant, with "low n" flags on small samples so early numbers aren't over-read.

Delivery

Did the beacon get through?

Delivery % (pageviews ÷ server-side serves) per traffic source detects ad-blocker interference, colour-coded green / amber / red.

Bots

Which variant is indexed now?

Per-window bot hits with the current window highlighted and the live variant badge ringed in gold, plus the four watermark strings inline.

Sticky top nav & jump links Per-section help & glossary CSV export per table WCAG AA contrast & focus states Nonce'd CSP, zero inline styles Cloudflare Access gated
A close-up of the dashboard's variant-badge popover: clicking the gold-ringed v3 badge opens a card headed 'Variant v3, balanced' with a 'live now' chip, a one-line description, the variant's exact watermark string, and an 'Open preview' link that opens untracked and noindex.
Every heading and badge is click-to-explain. Opening the live v3 badge shows its role, a "live now" chip, the exact watermark string that attributes its citations, and an untracked preview link.
The stack

Built to run on the edge, forever, for pennies

Cloudflare Pages Functions on V8 workers, D1 for analytics, vanilla JavaScript on the client, and zero third-party runtime dependencies.

☁️ Cloudflare Pages Functions / V8 🗄️ D1 bot_hits · human_events · serve_log ⚡ HTMLRewriter edge transforms 📄 Vanilla JS ~1 KB beacon 🔒 Cloudflare Access admin gate 🧱 Nonce'd CSP self-hosted CSS

See the framework in the wild

Open the live test post (the edge will hand you one of four variants) or dive into the analytics console to watch citation lift and human engagement race each other in real time.