Pageviews and attribution
PostHog capture settings (SPA pageviews, page-leaves, dead clicks, web vitals) and first-touch attribution - the first_touch cookie, the user field it lands on, and the person properties it feeds.
Two pieces of PostHog plumbing decide what growth queries can see: the capture settings pinned in apps/web/instrumentation-client.ts, and the first_touch cookie apps/web/proxy.ts stamps on every new visitor.
PostHog capture settings
The client init pins defaults: "2025-05-24" and opts into richer capture explicitly:
| Setting | Effect |
|---|---|
capture_pageview: "history_change" | SPA route changes emit $pageview - without it only full page loads count |
capture_pageleave: true | $pageleave on page exit - powers bounce rate and time-on-page |
capture_dead_clicks: true | $dead_click where a click visibly changed nothing |
capture_performance: { web_vitals: true } | $web_vitals (LCP, CLS, INP, FCP) per route |
Session recording, heatmaps, and surveys stay PostHog remote-config toggles - nothing forces them in code. Pageviews for every other provider come from that provider's own script.
The first_touch cookie
Set on a new visitor's first page request - first touch, never overwritten, attached to redirect responses too, so a UTM-carrying old backlink still counts.
| Attribute | Value |
|---|---|
| Contents | JSON: UTM tags (source, medium, campaign, term, content), gclid, fbclid, ref, referrer, landingPage, ts |
| Lifetime | 90 days |
| Scope | path=/, SameSite=Lax, Secure in production |
httpOnly | No - deliberately. Three same-origin readers need it: client JS (identify person properties), the signup hook, and checkout metadata. |
| Skipped for | Markdown/agent requests |
It holds no IP address, no fingerprint, and no identifier - where the visit came from, not who the visitor is - so it is written independently of the consent banner.
Where attribution flows
| Where | What happens |
|---|---|
| Signup | The auth hook persists the cookie JSON on the user row (user.firstTouch) |
| Identify | PostHog receives $set_once person properties: first_touch_source, first_touch_medium, first_touch_campaign, first_touch_term, first_touch_content, first_touch_gclid, first_touch_fbclid, first_touch_ref, first_touch_referrer, first_touch_landing_page, first_touch_ts. Providers with plain traits get the same keys merged into traits |
| Checkout | Checkout creation forwards the attribution alongside the affiliate metadata |
- Attribution rides the same consent gate as identify traits: with a banner required, it reaches providers only after consent (Cookie consent).
- Break funnels and revenue down by
first_touch_source- the queries live in AI-driven analytics review.
Built-in events
The complete catalog of analytics events the boilerplate fires on its own - client events from useAnalytics() and server events from payment webhooks, credit settlement, and auth hooks - with the properties each carries.
Google Ads conversions
Wire Google Ads conversion tracking onto the gtag.js that GA4 already loads with the ads key under config.analytics.google - conversion ID, per-event labels, and the Consent Mode v2 signals.