type: decision
status: active
timestamp: 2026-06-20
tags: [analytics, decisions, architecture, clarity, ga4, posthog, cloudflare-analytics, utm]

Analytics — 5-tier stack (CFWA + GA4 + PostHog + Clarity + UTM)

Five analytics layers in parallel on every site \ \u2014 Cloudflare Web Analytics (raw load), Google Analytics 4 (marketing funnel),\ \ PostHog (product + session replay + flags), Microsoft Clarity (heatmaps + Microsoft-side\ \ session replay), UTM tracking (attribution convention). Each layer covered by\ \ an `ENABLE_<TOOL>` env-var kill-switch so no single quota pinch can break a site."

Analytics — 5-tier stack (CFWA + GA4 + PostHog + Clarity + UTM)

Decision

Every site in the family runs five analytics layers in parallel, each covering a different question with no overlap. All five are free, no card, and each can be killed by a per-site ENABLE_<TOOL>=true|false env-var without affecting the others.

#LayerServiceQuestion it answers
1Edge / raw loadCloudflare Web AnalyticsHow many real visitors, from where, on what URL? (cookieless)
2Marketing funnelGoogle Analytics 4 (GA4)Acquisition / engagement / conversion against the same definitions advertisers use
3Product analyticsPostHogFunnels, retention, feature-flag usage, session replay (product side)
4Heatmaps + session replay (vendor-redundant)Microsoft ClarityWhere do users click / scroll / rage-click; second replay so a PostHog quota miss never blinds us
5Attribution conventionUTM trackingWhich channel / campaign drove this session — read by tiers 2-4 from the URL

Why five and not fewer

The user’s direction was: “I want to use all of the analytics and all of the Google practices, Microsoft Clarity and everything … I want a free service for everything.” Picking only one layer leaves real questions unanswered:

The five layers together answer every operationally interesting question with vendor redundancy on session replay (PostHog + Clarity) and funnel redundancy (GA4 + PostHog). Each layer preserves the family’s no-card-on-file rule and each runs at a different vendor, so a single outage / quota trip never goes dark across the board.

Quota safeguards (per rules/interaction/never-hit-quotas.md)

Each layer has a per-site env-var kill-switch:

ENABLE_CFWA=true            # Cloudflare Web Analytics (no real cap)
ENABLE_GA4=true             # GA4 — sampled past 10M events/mo (free)
ENABLE_POSTHOG=true         # PostHog — 1M events/mo, 5K replays/mo
ENABLE_CLARITY=true         # Microsoft Clarity — no documented cap
ENABLE_UTM_HELPER=true      # <UtmLink> validation in @chirag127/oriz-kit

Set any to false per site if a quota cliff approaches. The <Analytics /> component in reads these flags at build time and tree-shakes the unused scripts.

Implications

Cross-refs


Edit on GitHub · Back to index