GA4 custom events and dimensions: capturing the data the defaults miss
GA4's automatic events don't capture what makes your client's business unique. How to design custom events, send the right parameters, and register them as custom dimensions — plus the gotcha that makes half of them invisible.
TL;DR
GA4's automatic + Enhanced Measurement events (page views, scrolls, clicks) are generic — they don't capture the actions that matter to this client's business. Custom events do, and they follow a three-step chain that everyone gets two-thirds of: (1) fire a custom event with descriptive parameters, (2) register those parameters as custom dimensions in GA4 Admin, and (3) use them in reports/explorations/audiences. The gotcha that wastes the most time: a parameter you send but never register as a custom dimension is invisible in reports — the data arrives and GA4 silently drops it from the UI. Register it, mind the cardinality and the 50-custom-dimension limit, and design events from your measurement plan rather than tracking everything that moves. Below: the chain, the limits, and the gotcha.
Every client has actions that signal value but aren't in GA4's default kit: a quote request, a plan selected, a video watched to 75%, a filter applied, a specific lead type. Capturing those is what makes analytics this client's analytics instead of a generic dashboard. It's also where people get stuck — usually because of one invisible step. Here's the whole chain.
Step 1 — Fire a custom event with useful parameters
A custom event is just an event with a name you choose (quote_requested, plan_selected), sent via GTM or gtag. The event name alone is weak; the value is in the parameters you attach:
event: 'plan_selected'
params: { plan_name: 'pro', billing_period: 'annual', plan_price: 290 }
Parameters are the detail — which plan, which period, how much — that turns "an event happened" into "here's what happened." Design them deliberately: a flat handful of meaningful parameters beats a sprawl of everything you could technically capture.
Two naming rules that save pain later: use snake_case, and keep names consistent across events (plan_name everywhere, not planName here and plan there). GA4 also reserves some event/param names — don't reuse page_view, session_start, etc.
Step 2 — Register parameters as custom dimensions (the step everyone skips)
Here's the gotcha that derails more GA4 setups than any other: sending a parameter does not make it appear in reports. Until you register it as a custom dimension (GA4 Admin → Custom definitions → Create custom dimension, mapped to the parameter), GA4 collects the value but won't show it in standard reports or most explorations. People send plan_name for weeks, go to build a report, find nothing, and conclude the event is broken — when the data was arriving the whole time, just unregistered.
- Event-scoped custom dimension → a parameter on the event (
plan_name). - User-scoped → a property that describes the user across sessions (
customer_tier).
Register the parameters you'll actually report on, and do it early — custom dimensions only collect from the point they're created forward (not retroactive), so a late registration means a gap.
Step 3 — Use them in reports, explorations, and audiences
Once registered, custom dimensions become available as dimensions in explorations, as breakdowns in reports, and as conditions for audiences. Now "how many pro annual plans were selected by users from paid search?" is answerable — the custom event captured the action, the parameters captured the detail, the registration made it visible.
The limits that bite
- 50 custom dimensions per property (event-scoped) — a hard cap, so don't register parameters you won't use. This is why "track everything" backfires: you burn the budget on noise.
- Cardinality. A custom dimension with too many unique values (high cardinality — e.g. a raw timestamp or a full URL with query strings) gets bucketed into
(other)in reports, making it useless. Keep dimension values categorical and bounded. - Not retroactive. Both the dimension registration and the audience definitions only apply going forward — set them up before you need the data, not after.
Design from the plan, not the page
The discipline that keeps custom events useful is the same one that keeps all tracking sane: start from what the client cares about, not from what's trackable. Each custom event should trace to a goal in the measurement plan; each parameter should be something you'll actually report on or build an audience from. Tracking every click "just in case" burns your 50-dimension budget, spikes cardinality, and buries the signal — the opposite of the goal. And as always, verify it in DebugView: fire the event, confirm the parameters arrive with the right names and types, then confirm the registered dimension populates a day later.
Where this fits
Custom events are how a client's GA4 stops being generic — and they're also one more thing to get right, keep consistent, and not let drift as the site changes. Phloz models each client's events, parameters, and the conversions they feed as part of the tracking-infrastructure map, so the custom-data layer is documented and health-checked rather than living in one person's memory of "what we set up." The CRM for SEO agencies and pricing pages cover the workflow — but the chain is the thing to remember: fire the event, register the parameter, then use it. Skip the middle step and the data's there but invisible.