type: service
status: active
timestamp: 2026-06-20
tags: [analytics, ga4, google, marketing, funnel, primary]

Google Analytics 4 (GA4)

Marketing-funnel analytics — acquisition/engagement/conversion, free, no card

Google Analytics 4 (GA4)

Role

Marketing funnel — acquisition / engagement / conversion measured against the same definitions advertisers, recruiters, and SEO tools already speak. GA4 is layer 2 of the 5-tier analytics stack: shipped on every site in the family because the recruiter-facing metric (“did the post on oriz.in/blog/... actually convert to a sign-up / link-click / GitHub star?”) is the only one expressed in GA4’s vocabulary.

Free tier

Card / subscription required?

NO. Sign-in with the same Google account; GA360 is the paid tier and we never approach its threshold.

GA4 is cookie-based and reads/writes _ga* cookies, so it is gated behind explicit consent in every region the family ships to. The consent surface is locked at security/consent-management-multi-category.md:

Per the consent decision, Klaro itself lazy-loads ONLY when CF-IPCountry lands in the EU / UK / CCPA list — non-banner-region visitors never download Klaro bytes.

GA4 always boots with the denied default so the script is safe to load before the consent answer is known:

// in <Analytics /> from @chirag127/oriz-kit, before gtag.js
gtag('consent', 'default', {
  ad_storage: 'denied',
  ad_user_data: 'denied',
  ad_personalization: 'denied',
  analytics_storage: 'denied',
  functionality_storage: 'granted',  // strictly necessary
  security_storage: 'granted',       // strictly necessary
  wait_for_update: 500
});

Klaro then calls gtag('consent', 'update', ...) once the user answers, per services/business/security/klaro.md. Hits made before consent are stored client-side and replayed on update — no data is sent until consent lands.

Per-site env-var toggle

Per the never-hit-quotas rule, GA4 is one of the five layers covered by an env-var kill-switch:

ENABLE_GA4=true|false

The <Analytics /> component in

reads this at

build time; setting false tree-shakes the GA4 script entirely (zero bytes shipped, not just blocked at runtime).

Each site additionally carries its own GA4 measurement ID (G-...) in Doppler under GA4_MEASUREMENT_ID so a single property never mixes traffic from multiple sites.

Alternatives

GA4 is the only free tool that speaks the same vocabulary as Google Ads, Search Console, recruiter analytics, and most SEO tooling — that shared definition is the value, not the feature surface.

Swap cost

Medium — every event call site uses gtag('event', ...) directly; swap = re-map event names + dimensions to the replacement vendor’s schema. The <Analytics /> component isolates the script-load surface but not the per-event call sites.

Why this is our pick

GA4 is the only free analytics tool that produces metrics in the exact vocabulary recruiters, advertisers, and SEO consoles already read. The other layers (CFWA, PostHog, Clarity, UTM) cover engineering / product / replay / attribution questions GA4 can’t, but none of them produce “acquisition channel × conversion rate” in the format an outside reader expects.

Cross-refs


Edit on GitHub · Back to index