Ryan Perez · Analytics layer

Nothing ships untracked.

Every site and every funnel built from this library carries the same measurement layer. Not because analytics is interesting, but because the funnel system measures state transitions — and a transition you cannot observe is a claim you cannot defend. This page is the required install, not an optional add-on.

The stack Consent defaults → GTM → GA4 → Meta Pixel → product analytics → server-side conversions
Order is not optional

Six things in the head, in this sequence

The tag manager reads the consent state when it initialises. If consent defaults land after it, tags fire before the visitor has chosen — which is both a compliance failure and unusable data.
{{ s.n }}
{{ s.t }} {{ s.where }}
{{ s.why }}
{{ c.t }} {{ c.where }}
{{ l.t }}
{{ c.note }}
Auto-tracking

Five things the tracker does unasked

One component mounted inside the router. Everything here fires automatically, so per-page instrumentation is only needed for genuine conversion events.
{{ a.t }} {{ a.event }} {{ a.how }}
Dispatch

One call, four destinations

{{ l.t }}
Safe wrappers check the global exists before calling it, so an ad blocker or a slow script never throws inside product code.
{{ d.call }}
{{ d.t }} {{ d.why }}
Standard-event mapping {{ m.a }}→{{ m.b }}
Baseline

Thirteen events every site gets

These are universal. A site missing one of these has an incomplete container, not a customised one.
{{ e.a }}{{ e.b }}
By site type

What gets added on top

{{ s.t }}
{{ e.a }} {{ e.b }}
The bridge

Every funnel transition needs its event

This is why analytics belongs inside this library rather than beside it. The funnel system measures transitions, and each transition here names the event that proves it happened.
Transition Event Fired from
{{ b.a }} {{ b.b }} {{ b.c }}
Anything after purchase — activation, outcome, retention, referral — must fire server-side. A client event cannot prove a delivered outcome.
Naming

Seven naming rules

{{ r.t }}
Strip on adaptation

What never carries between sites

When a container is cloned as a template, these belonged to the source and will quietly pollute the new property.
{{ s.t }}
Also strip any duplicate tag carrying a “(2)” suffix, and every outbound-link filter still naming the source domain.
Default state

Denied, before anything loads

{{ l.t }}
Functionality and security stay granted — they are not tracking. Everything advertising or analytics related starts denied.
Propagation

One choice, three platforms

{{ l.t }}
Session recording must be stopped and started, not merely masked. It is separate from the consent API the ad platforms expose.
Consent rules

Nine that are not negotiable

{{ r.a }} {{ r.b }}
Escape hatch

The ads-today path

When the brief is genuinely “I need conversions recorded today and the banner can come later”, this is the only sanctioned shortcut. Say out loud that it is one, and get it confirmed.
{{ r.t }}
Runtime

What happens, in order

{{ r.n }} {{ r.t }}
Container

Export shape

{{ l.t }}
Keep the export format version at 2 and every required field present. Use "0" as the placeholder for account, container and version ids.
Vocabulary

Types worth memorising

{{ g.t }}
{{ r.a }}{{ r.b }}
Two delivery routes

File import, or the API

{{ r.t }} {{ r.when }}
{{ s.n }}{{ s.t }}
{{ r.gotcha }}
Preferred

Server-side conversions

Fire the conversion API from the backend route that already processes the conversion. Ad-blocker proof, build-safe, debuggable from server logs.
{{ l.t }}
Identifiers

Four things people mix up

{{ i.t }}{{ i.shape }}
{{ i.what }}
Never in a design file Real measurement ids, pixel ids, client secrets, refresh tokens and conversion-API tokens live in environment variables and the credential store. This page carries placeholders only, on purpose.
Learned the hard way

The one that takes a site down

Conversion-API code in the shared tracking bundle silently breaks the production build The symptom is the worst kind: the bundle returns 200, the syntax is valid, the console is clean — and the app never mounts. The root element stays empty on production and preview alike. It is reproducible, and it is not worth diagnosing while the site is down.
{{ r.label }} {{ r.t }}
Revert first, diagnose second. If a tracking commit blanks the site, revert and push before investigating anything.
Pitfalls

Grouped by where they bite

{{ g.n }}{{ g.t }}
{{ i.a }} {{ i.b }}
Ship checklist

Before any tracking change is pushed

{{ c.t }}
Working practice

How this gets done to a client's site

{{ p.t }}
Parity rule Multiple sites under one business share the same event names, the same container patterns and one pixel — so attribution works across domains and a single report answers questions about all of them.