Consent-safe shared-site analytics

Honesty artifact

Assumptions: GA4 property G-L6CXTTSPV2 remains the intended measurement property, the normal shared layouts plus the three named standalone funnels are the active measurement scope, and GitHub Pages deploys the rendered includes. Known gap: production deployment and real GA4 receipt remain unproved until the merged Pages SHA is observed. No analytics improvement or commercial impact is claimed before that evidence.

Pre-merge verification on 27 August 2026 used an isolated Ruby 3.2 / GitHub Pages 232 toolchain on the local non-Tailscale volume. The real Jekyll build passed. Rendered /, /player-diagnostic/, /session-plan/, /which-product/, and /privacy-policy/ each contained exactly one analytics loader, with the default-denied consent command before it. Focused unit tests passed and the executable browser suite passed 3/3, including no Google request before consent, idempotent accept/config/page-view, unsafe legacy-event suppression, withdrawal cookie expiry, and an unmodified outbound navigation.

The static 360TFT site declared GA4 but had no deployed consent mechanism or loader, so existing gtag callers were inert. The shared contract now defaults all analytics and advertising consent to denied, loads GA4 only after an affirmative choice, and provides a persistent Cookie Settings control for withdrawal. Rejecting analytics leaves the site fully usable.

Outbound events contain only the current pathname and a bounded destination category. Query strings, link text, form content, email addresses and user IDs are never included. The gateway drops all legacy events except bounded cta_click and begin_checkout schemas, and initialises GA4 once, preventing duplicate page views.

Production completion requires independent review, merge, observed Pages SHA, and browser proof that reject sends no Google requests, accept sends one page view plus a bounded outbound event, and withdrawal stops subsequent events.

The first production check at SHA e48e59a found that the Google library loaded but did not collect: sanitized commands had been queued as ordinary arrays, not the arguments-shaped commands used by the gtag protocol. That deployment is not credited. The follow-up uses an arguments-preserving queue adapter and must show a real Google collection request after consent before this PRD can close.

Production proof

Completed 27 August 2026 at Pages/main SHA 0e3b5c479eba09db28739a524858e150cc630024 after independent review passed the follow-up commit. The normal Action was a billing non-start, so the direct GitHub Pages build API was used; Pages reported the exact SHA as built.

Live checks found exactly one loader, ordered after default-denied consent, on /, /player-diagnostic/, /session-plan/, /which-product/, and /privacy-policy/. A clean production browser produced zero Google requests before consent and after rejection. Acceptance produced the Google loader GET and a region1.google-analytics.com/g/collect POST. A bounded outbound click queued only route, destination category, and beacon transport and produced a second collection POST; withdrawal suppressed the next click. This proves the production collection path, not downstream GA reporting, customer conversion, or revenue impact.