GA4 has been the only option since July 2023, but the mental model shift hasn't fully landed for a lot of practitioners. Over 14 million websites now run GA4, yet many implementations still carry the structural assumptions of Universal Analytics — the tracking fires, the data appears, but the architecture underneath reflects a framework that no longer exists, and that disconnect quietly limits what the data can actually tell you.
If you learned analytics on UA, this piece is the bridge. Not a feature comparison or a migration checklist, but an explanation of how GA4 events work in practice and why the old mental model keeps getting in the way.
What Universal Analytics taught you about events
Universal Analytics organized events around three required fields: Event Category, Event Action, and Event Label, and every event had to fit into that structure. Track a form submission? Category: "Form", Action: "Submit", Label: "Contact Page". Track a video play? Category: "Video", Action: "Play", Label: "Product Demo".
The rigidity was the point. Those three fields imposed a shared vocabulary across teams and vendors, so when an agency set up tracking and handed the container to an in-house team, everyone understood the taxonomy because UA forced consistency. Category told you what kind of thing happened, Action told you what the user did, and Label gave you the specifics.
This framework worked well for over a decade, and it trained an entire generation of analytics practitioners to think about events as rigid, pre-structured data points where the naming taxonomy was the architecture. You didn't design your event model so much as fill in the blanks that UA gave you.
The problem was that it couldn't scale. A single "Form" category with an "Action" of "Submit" and labels for each form worked fine for five forms, but for 200 forms across 12 languages and three business units, the label field became a junk drawer. The structure that imposed discipline at small scale became a constraint at larger scale, and teams worked around it with increasingly creative label strings that nobody could parse without a decoder ring.
How GA4 events actually work
GA4 replaced the three-field structure with something fundamentally different: an event name plus up to 25 custom parameters per event. No mandatory category, no required action, no label field — just a name and whatever context you choose to attach.
GA4 organizes events into four tiers, and understanding which tier an event belongs to determines how you should work with it:
| Tier | What it means | Examples |
|---|---|---|
| Automatically collected | GA4 sends these without configuration | first_visit, session_start, user_engagement |
| Enhanced measurement | GA4 sends these if you toggle them on | page_view, scroll, file_download, form_start |
| Recommended | Google-defined names with expected parameters | login, sign_up, purchase, add_to_cart |
| Custom | You define everything | lead_form_submit, pricing_calculator_used |
The recommended events matter more than they might seem. When you name your purchase event purchase and include the parameters Google expects (transaction_id, value, currency, items), GA4 populates its built-in ecommerce reports automatically. Name it completed_order instead, and you get a custom event that tracks the same interaction but doesn't feed any of the pre-built reporting — same data, different event name, meaningfully different outcome.
This is the core difference from UA: in GA4, the event name is an architectural decision that determines what reports work out of the box, whereas in UA, the reporting structure was fixed regardless of what you named things.
Enhanced measurement: what GA4 tracks automatically
Before creating any custom events, it's worth checking what GA4 is already collecting. Enhanced measurement handles several interactions that UA required manual setup for:
- Page views fire on every navigation (including single-page app route changes if configured)
- Scrolls fire when a user reaches 90% of page depth
- Outbound clicks fire when a user clicks a link to a different domain
- Site search fires when a URL contains a search query parameter
- Form interactions track
form_start(first interaction) andform_submit - File downloads fire for common file extensions (pdf, xlsx, docx, etc.)
- Video engagement tracks start, progress, and complete for embedded YouTube videos
These can be toggled individually in GA4's admin under Data Streams, though there are catches: enhanced measurement form tracking is basic (it fires on the HTML form submit event, which doesn't capture AJAX submissions or multi-step forms), and video engagement only works with YouTube embeds.
The common mistake is implementing a custom event for something enhanced measurement already handles — a custom file_download event running alongside the automatic one, for instance, means both fire on every download and your numbers double without anyone catching it until someone questions why the report shows twice as many PDF downloads as the server logs. Before writing any custom tracking, review Google's enhanced measurement documentation and cross-reference against what you're planning to build.
When to use recommended events vs custom events
Google publishes a list of recommended events organized by industry (retail, jobs, education, travel, games) and by common use case (lead generation, content engagement, search), with each recommended event including a defined name and a set of expected parameters.
The decision framework:
Use a recommended event when your interaction matches Google's definition. If someone adds a product to a cart, use add_to_cart; if someone completes a purchase, use purchase; if someone signs up for an account, use sign_up. These names unlock pre-built reports and integrations with Google Ads and other Google products.
Use a custom event when no recommended event fits. If you're tracking a pricing calculator interaction, an ROI tool completion, or a custom chatbot engagement, there's no recommended equivalent — create a custom event with a descriptive name and appropriate parameters.
Don't force a recommended event name onto a different interaction. Naming a whitepaper download purchase because you want it in the ecommerce funnel creates data integrity problems that compound over time. If the interaction isn't a purchase, don't call it one.
The limit to keep in mind: 500 distinct event names per property. That sounds generous until you discover that a property with three years of accumulated tracking from multiple teams has 200+ event names, many of which track slight variations of the same thing. This is the proliferation problem, and it's the single most common structural issue in GA4 implementations.
Parameters vs event proliferation
Event proliferation is a hedging mechanism. When someone isn't sure how to structure GA4 tracking, the safest-feeling option is to create a new event for each variation: form submission on the contact page becomes form_submit_contact, form submission on the demo page becomes form_submit_demo, form submission in Spanish becomes form_submit_spanish.
The result is a property with dozens of events that are really the same interaction with different context, which fragments reporting because each event name gets its own row. Comparing form submissions across pages means combining multiple events manually, and when marketing adds a new form, someone has to create yet another event name instead of just passing a new parameter value.
The GA4 approach to this is parameters — one event, form_submit, with parameters that capture the variation:
| Parameter | Example values | What it answers |
|---|---|---|
| form_type | contact, demo_request, newsletter | Which form was it? |
| form_location | header, sidebar, footer, popup | Where on the page? |
| form_language | en, es, fr | What language? |
Now you have one event that answers multiple questions through filtering and segmentation. Need to see all form submissions? Filter by event name. Need just demo requests? Filter by form_type = demo_request. Need demo requests from the Spanish site? Add a second filter. The flexibility that GA4 provides through parameters is exactly what UA's rigid structure couldn't offer, but it only works if you actually use it.
The technical guardrails: each event can carry up to 25 custom parameters, parameter names can't exceed 40 characters, and parameter values can't exceed 100 characters. Parameters you want to see in GA4 reports (not just BigQuery) need to be registered as custom dimensions in admin, and you're limited to 50 event-scoped custom dimensions per property. That registration step is the one people miss most often — the parameter gets sent, the data reaches GA4, but it never appears in reports because nobody registered it as a custom dimension.
The data layer
The data layer is a JavaScript object that sits on the page and holds structured information about what's happening on it. When someone adds a product to their cart, the data layer push might contain the product name, price, category, variant, and quantity, all in a clean format that GTM can read and pass to GA4 as event parameters.
window.dataLayer.push({
event: 'add_to_cart',
ecommerce: {
currency: 'USD',
value: 49.99,
items: [{
item_id: 'SKU-12345',
item_name: 'Widget Pro',
price: 49.99,
quantity: 1
}]
}
});Without a data layer, GTM has to scrape the page for information — reading prices from DOM elements, extracting product names from CSS selectors, guessing at values based on page structure — and this approach is brittle (it breaks when the page design changes), limited (it can only capture what's visible in the HTML), and slow (DOM queries add processing time).
With a data layer, the backend system pushes structured data to the page at the moment the interaction happens, GTM reads it cleanly, maps it to GA4 parameters, and sends a well-formed event. The data arrives complete and correct because it came from the source system rather than being reverse-engineered from the page.
If you're inheriting a GA4 implementation and the tracking seems incomplete or unreliable, the data layer is the first place to look. Open your browser console, type dataLayer and press enter, and you'll see every push that's happened on the current page. If the events you expect aren't there, the problem is upstream of GTM; if they're there but GA4 isn't showing them, the problem is in how GTM reads and forwards the data.
Building a data layer requires developer involvement, which is why it's often the piece that gets skipped or deferred. The practical conversation to have with your development team: "When a user does X on the site, I need these specific values available in a structured format that our tag manager can read." The developer doesn't need to understand GA4 and you don't need to write JavaScript — you need to agree on what data should be available and in what format. Google's ecommerce developer documentation provides the expected format for ecommerce interactions specifically.
Building a measurement plan
The pattern behind most GA4 implementation problems is the same: someone started building tracking before deciding what questions the tracking needed to answer. Custom events accumulated organically, parameters were named inconsistently because different people implemented different sections, and the data layer got partially built for ecommerce but nothing else.
A measurement plan is a spreadsheet that lists every event you intend to track, classifies it as automatically collected, enhanced measurement, recommended, or custom, specifies every parameter each event will carry, and documents what report or question each event supports. It takes a few hours to create and saves weeks of remediation later.
Start with the output, not the input. What would you present to your executive team? What metrics do they care about? Work backward from the reports to the events and parameters needed to populate them — if the executive dashboard needs form conversion rates by business unit, you need a form_submit event with a business_unit parameter, and if it needs revenue by product category, you need the ecommerce events with properly structured items arrays. The measurement plan connects business questions to technical implementation, and it becomes the reference document for everyone who touches the container.
TagManifest checks for the event naming problems that emerge when this planning step gets skipped: casing violations, names that exceed GA4's 40-character limit, reserved name collisions, conflicts with enhanced measurement events, and the proliferation pattern where three or more events share a prefix that suggests they should be one parameterized event. If your GA4 data quality isn't where you want it, scanning your container is a fast way to see which patterns need attention.