Add hero CTA A/B test (hero_cta: control vs free_emphasis)

Sticky 50/50 variant assignment via gw_ab_hero cookie, server-rendered
so no flicker. Tracks exposures, CTA clicks, and booking conversions
to ab_events (table self-creates on first POST). Bot UAs are dropped;
exposures/clicks dedupe per session.

- ?ab=control / ?ab=free_emphasis forces and persists a variant
- /owner/experiments shows per-variant CVR and relative lift
- AB only runs on the marketing surface

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 08:14:18 +12:00
parent a7f8a619b1
commit 171b193498
14 changed files with 534 additions and 8 deletions
+9
View File
@@ -1,5 +1,6 @@
import type { Handle } from '@sveltejs/kit';
import { resolveSurface } from '$lib/server/surface';
import { resolveAnonId, resolveHeroVariant } from '$lib/server/ab';
const ADMIN_PATH = '/owner/welcome';
@@ -7,6 +8,14 @@ export const handle: Handle = async ({ event, resolve }) => {
const { surface } = resolveSurface(event.url, event.cookies);
const path = event.url.pathname;
// Sticky A/B assignment, marketing surface only — no point polluting the
// owner/clients hosts with marketing-experiment cookies, and it skews
// exposure counts when staff hit the public site from the dashboard.
if (surface === 'marketing') {
event.locals.anonId = resolveAnonId(event.cookies);
event.locals.abHero = resolveHeroVariant(event.url, event.cookies);
}
// The admin host (cp.*) serves the dashboard at its root.
if (surface === 'cp' && (path === '/' || path === '')) {
return new Response(null, {