adop.tools
Guides /

GA4 Events 102: Advanced Parameters, the dataLayer and Ecommerce

GA4 events

GA4 Events 102: Advanced Parameters, the dataLayer and Ecommerce

The advanced layer of GA4 events: naming that survives growth, quotas and cardinality, cleanup patterns, feeding events from the dataLayer, and the ecommerce event set.

14 min read

Events 101 covered what events are, the standard set, parameters and key events. This is the layer for accounts that are past the basics: keeping names sane as the account grows, staying under the quotas, cleaning up sprawl, wiring events from the dataLayer, and the ecommerce event set that powers revenue reporting.

Naming conventions that survive growth

Naming feels like the least important decision you'll make when setting up GA4. It isn't. The names you pick on day one are the names you'll be staring at in the Events report two years later, after a dozen new pages, three developers, and a marketing team that fired tracking through whatever felt natural at the time. Good names are quiet: you never think about them. Bad names cost you an afternoon every reporting cycle.

This guide is one opinionated house style. Adopt it whole, write it down, and apply it to every event and parameter you send. The specific rules matter less than the fact that everyone follows the same ones.

The Cost of Inconsistent Names

Here is what a property looks like when nobody owns the naming. Three people wanted to track sign-ups, and over eighteen months you ended up with all of these in the Events report:

  • signup
  • sign-up
  • SignUp
  • sign_up_complete
  • newsletter_signup

To GA4 these are five completely different events. There is no "sign-up total" anywhere in the interface, because GA4 has no idea these are the same thing. To report on sign-ups you now have to remember all five names, build a comparison or a custom dimension that lumps them together, and re-do it every time someone adds a sixth variant. The same rot shows up in parameters: lead_form on one event, leadform on another, form on a third. Each spelling is a separate column you have to reconcile by hand.

None of this is recoverable cheaply. GA4 does not backfill renamed events, so the day you finally standardise, your history splits into "before" and "after." The fix is to never let it happen.

The Core Rules

Six rules cover almost every case. Apply them to event names and parameter names alike.

1. Lowercase snake_case, always

Words separated by underscores, everything lowercase: view_item, add_to_cart, form_submit. This matches Google's own recommended events, so your custom events sit naturally alongside the automatic ones. No spaces, no hyphens, no camelCase, no PascalCase. GA4 treats names as case sensitive, so Purchase and purchase are two different events: lowercase removes the ambiguity entirely.

2. The verb_object pattern

Lead with a verb describing the action, then the thing it acted on: view_item, submit_form, start_checkout, select_promotion. This reads cleanly in a list and keeps related events sorted together. A noun-only name like form or video tells you nothing about what happened.

3. Present tense, no past tense

Use complete_purchase, not purchase_completed or purchased. Events describe something that just happened; present-tense verbs keep every name in the same grammatical shape so they line up predictably.

4. No PII, ever

Never put personal data in a name or a value: no email addresses, names, phone numbers, or user IDs. Sending PII into GA4 is a Terms of Service violation and a privacy risk, and it makes names explode in cardinality. If you need to tie behaviour to a person, that belongs in your own systems keyed on a non-identifying ID, not in the event name.

5. No volatile values baked into names

The event name is a constant. Anything that changes per occurrence goes in a parameter, not the name. Do not create view_product_4821, view_product_4822, and so on: fire view_item and pass item_id as a parameter. Names that embed IDs, dates, or prices generate thousands of distinct events and make every report useless.

6. Be specific, but not redundant

Name the thing precisely enough that you never have to guess: submit_contact_form beats submit_form if you have several forms, but you can also keep submit_form and pass form_name as a parameter. Pick one approach and use it consistently. What you must avoid is two events that mean the same thing with slightly different words.

Naming Parameters Consistently

Parameters need the same discipline as events, and they fail more quietly because the inconsistency hides inside the event rather than in a top-level list. Use snake_case here too, and reuse the same parameter name for the same concept everywhere. If "which form" is form_name on submit_form, it is form_name on view_form as well, never form or formName or form_id standing in for the same idea.

Match Google's parameter vocabulary where one exists. The eCommerce schema already defines item_category, item_brand, coupon, value, and currency: use those exact names rather than inventing product_category or discount_code. For more on getting parameters to actually appear in reports, see GA4 event parameters.

Reuse Google's Recommended Events First

Before you invent a custom event, check whether Google already has a recommended one for it. GA4 ships a list of recommended event names (login, sign_up, search, view_item, add_to_cart, purchase, generate_lead, and many more) that unlock pre-built reporting and behave predictably with Google's own features. Using sign_up instead of your own user_registration means GA4 understands the event and you spend zero of your custom-definition budget on it. Only invent a name when nothing recommended fits.

The Cheat Sheet

Print this and stick it next to whoever writes tags. The pattern is always the same: snake_case, verb first, value in a parameter.

Bad Good Why
SignUp sign_up Lowercase snake_case; matches a recommended event
sign-up sign_up Underscores, not hyphens
formSubmit submit_form No camelCase; verb leads the name
purchase_completed purchase Present tense; recommended name exists
view_product_4821 view_item + item_id Volatile value belongs in a parameter
click_jane@acme.com select_content Never put PII in a name or value
leadform / lead_form form_name (parameter) One spelling for one concept, everywhere
video start_video + video_title Verb_object; the specific value is a parameter

When you're unsure between two good names, pick the one closest to Google's recommended vocabulary. It costs nothing, frees up custom-definition budget, and means a future analyst inherits names they already recognise.

Event and parameter names are capped at 40 characters, may contain only letters, numbers, and underscores, and must not start with a digit. Stay well inside that limit: a short, readable name ages better than a maxed-out one.

Governance: One Owner and a Tracking Plan

Conventions only hold if someone is responsible for them. Name a single owner of the measurement schema, the person who decides what a new event is called before it ships. Back them with a tracking plan: a simple shared document (a spreadsheet is fine) listing every event, its parameters, where it fires, and what question it answers. Every new event gets added there first and named there second, before a single tag is built. The plan is the source of truth; GA4 is just where the data lands.

Common Mistakes

  • Letting developers and marketers name events independently, so the same action gets two names.
  • Mixing cases (Purchase and purchase) and assuming GA4 merges them. It does not.
  • Encoding IDs, prices, or dates in the event name instead of a parameter, exploding cardinality.
  • Inventing a custom name when a recommended event already exists, losing free reporting.
  • Renaming events later to tidy up, which splits your history with no backfill.
  • Naming parameters loosely so the same concept arrives under three spellings.

Start Now, Not Later

Naming conventions are cheapest the day before you ship your first event and most expensive every day after. Write the house style down, name an owner, build the tracking plan, and hold the line. None of it is hard. It only requires deciding once and then refusing to drift.

Advanced parameters: registration and scope

Two facts separate parameter dabbling from parameter mastery. First, a parameter is invisible in reports until you register it as a custom dimension (Admin › Custom definitions) — GA4 collects it regardless, but reports only show registered ones, and registration is not retroactive. Second, the dimension’s scope decides what it describes — an event, a user, or an item — and a wrong scope produces confidently wrong numbers. Scope has its own section in Useful GA4 breakdowns; the short version is: describe the action → event scope, describe the person → user scope, describe a product → item scope.

How many events is too many

Somewhere in most GA4 properties there is an event that fires thousands of times a month and has never once appeared in a report. Maybe it was added "just in case." Maybe a developer instrumented every button on a redesign. Maybe an old campaign needed it and the campaign ended two years ago. Whatever the reason, it is still firing, still counting against your quotas, and still cluttering every dropdown you open in Explore.

The instinct behind event sprawl is understandable: data you didn't collect is data you can never get back, so collecting everything feels like insurance. But GA4 is not a bucket you pour data into for free. Events and parameters come with hard ceilings, and the cost of crowding those ceilings is paid in the one place that matters: the reports you actually build.

The "Track Everything" Trap

The argument for tracking everything sounds airtight. You can always ignore an event you don't need, the reasoning goes, but you can never analyse one you forgot to collect. So you instrument every interaction, register every parameter, and tell yourself you'll sort it out later.

Later never comes. What you get instead is a property where the event report runs to dozens of rows, half of them named things like click, gtm.click, or element_visible, and nobody on the team can say with confidence which ones are trustworthy. More events did not make the data richer. They made it harder to find the events that matter.

The honest version of the insurance argument is narrower: collect the events that map to questions you can already articulate, plus a small margin for the obvious near-future ones. Everything beyond that is not insurance. It is debt.

The Limits That Actually Bite

GA4 enforces real ceilings, and they are easier to hit than most teams expect. The exact numbers shift over time and differ between standard and 360 properties, so treat the figures below as the well-documented standard-tier values and confirm against current Google documentation before you architect around them.

Limit Roughly where it sits What happens when you cross it
Distinctly named events No limit on web data streams; 500 per app (Firebase) data stream A website won't stop collecting new names, but every extra name still widens reports and tempts another custom-definition slot
Custom parameters per event 25 per event Excess parameters are silently dropped, with no warning in the UI
Registered custom dimensions / metrics 50 event-scoped + 25 user-scoped + 10 item-scoped dimensions, plus 50 metrics (higher on 360) You run out of slots to register the parameters you actually report on
Dimension cardinality High unique-value counts on a single dimension Excess values get bucketed into an (other) row, hiding the long tail

Two of these are subtle in a way that catches teams out. The custom-definition quota is a budget you spend slowly and then suddenly run dry, often when you finally need to register the one parameter the client has been asking about. And high cardinality does not throw an error at all; it quietly folds your rare values into (other), so a page_path or transaction_id dimension can look complete while hiding most of its detail.

On the web there is no cap on how many distinct event names you collect, so sprawl never blocks a new event outright. The ceiling that actually bites is the custom-definition budget: fill those 50 event-scoped, 25 user-scoped, and 10 item-scoped slots with parameters from junk events and there is none left for the one the client is asking about.

Signal Versus Noise

Here is the test that cuts through every debate about whether to keep an event: does anyone report on it? An event that never appears in an Exploration, a custom report, a key-event count, or an audience definition is not neutral. It is pure cost. It clutters the events report, it widens every dimension picker, and it dilutes the average analyst's trust in the property because they cannot tell your real events from your dead ones.

Volume is not the same as value. An event firing fifty thousand times a month with no report attached is worth less than an event firing two hundred times that drives a key business decision. Counting is cheap; meaning is the scarce resource. When you evaluate an event, ask what decision it informs. If the answer is "none, currently," it is noise wearing the costume of data.

How to Audit What You Have

You cannot prune what you cannot see, so start with an inventory. The fastest read is the standard Events report: it lists every event name your property has collected, with counts. Sort by volume and scan for names you do not recognise or cannot justify.

Then cross-reference against actual usage:

  • Open your saved Explorations and custom reports and note which events and parameters they reference. Anything not referenced anywhere is a prune candidate.
  • Check your key events list. Events marked as key are by definition in use; leave them.
  • Look at your registered custom dimensions and metrics. Any definition pointing at a parameter you no longer send, or no longer report on, is dead weight occupying a scarce slot.
  • Watch for auto-generated noise. Enhanced measurement and loose GTM triggers (gtm.click, generic click, scroll fragments) are the usual sources of events nobody chose.

The goal of the audit is a simple two-column list: events with a report attached, and events without. The second column is your worklist.

How to Prune Safely

Pruning does not mean deleting data. GA4 keeps what it already collected; you are changing what gets collected and registered going forward. Move carefully, because the wrong cut loses history you cannot rebuild.

The highest-value move is consolidation. Most sprawl is near-duplicate events that differ only by where they happened. Ten event names like hero_cta_click, footer_cta_click, and nav_cta_click collapse cleanly into one cta_click event carrying a cta_location parameter whose value is hero, footer, or nav. You keep every distinction you cared about, you cut nine redundant event names, and you turn a scattered set of rows into one event you can break down on demand.

Before deleting any event name, recreate its distinctions as a parameter on a parent event. One cta_click with a cta_location param beats ten separate names: same insight, a fraction of the quota, and a single clean dimension to report on instead of ten rows to reassemble.

Sequence the work so you never lose signal. Ship the consolidated event alongside the old ones first, confirm the new parameter is populating, then retire the originals once you have a few weeks of overlap. For dead events with no report and no consolidation path, simply stop firing them; there is nothing to preserve.

What to Never Cut

Restraint applies to pruning too. Leave these alone:

  • Anything marked as a key event, or feeding one. These drive conversions and attribution.
  • eCommerce events (purchase, add_to_cart, view_item and friends). They power revenue reporting and the item-scoped schema.
  • Events referenced by an active audience, conversion import, or Ads link. Cutting these breaks downstream systems quietly.
  • Automatically collected and enhanced-measurement events you actually rely on (scroll, file download, outbound click) where the report exists.

When in doubt, consolidate rather than delete. Folding several names into one parameterised event almost never loses signal, whereas removing an event you misjudged starts its history over from zero.

The Right Number of Events

There is no magic count, but there is a principle: every event should earn its place by answering a question someone actually asks. The right number is "enough to report on, and no more." That is almost always far fewer event names than a sprawling property carries, because most of what looks like richness is just the same handful of interactions split needlessly across many names.

Audit once, consolidate the near-duplicates into parameters, retire the dead weight, and protect the events that drive decisions. You will end up with a property an analyst can read at a glance, comfortable room under every quota, and reports that say something rather than merely counting.

Grouping scattered events into clean conversions

Open the events report on almost any real GA4 property and you'll find the same mess: a row for learn_more_a, another for learn_more_b, a lead_form_header sitting two rows below lead_form_footer, and a handful of half-named variants from a tag someone shipped in a hurry. Each one fired honestly. Each one counts something a person actually did. And yet when your client asks the only question that matters, "how many leads did we get?", there is no number to point at.

That's the problem with events as GA4 stores them. They are atomic by design: one name, one count, one row. Nobody set out to fragment your conversions. It happens because forms get duplicated across templates, A/B tests spawn suffixed events, and three different people tagged the same button over two years. The data is fine. The shape is wrong.

Why a Single "Leads" Number Doesn't Exist

Consider a lead-gen site with a contact form in the page header and a second copy in the footer, plus two "Learn more" call-to-action variants from a campaign test. You end up with four events doing one job:

  • lead_form_header: submissions from the top-of-page form
  • lead_form_footer: submissions from the footer form
  • learn_more_a: the control CTA
  • learn_more_b: the variant CTA

Every one of those is a legitimate signal of lead intent. But GA4 reports them as four separate rows, four separate counts, four separate trend lines. To get a "Leads" total you're adding them up by hand in a spreadsheet, and you're redoing that addition every time someone ships a fifth variant. The number your client actually cares about is the one number GA4 refuses to give you.

Why GA4 Makes This Hard Natively

You might expect GA4 to have a grouping dimension for this. It doesn't. There is no built-in "event group" the way there's a default channel grouping for traffic. Events are the grain, and the platform has no native concept of "these five names are really one conversion."

The closest tool is marking events as key events. You can flag all four of the events above as key events, which is useful, but they still report as four separate rows. Marking them does nothing to merge them; it just promotes four fragments instead of one. Key-event status is a label on each event, not a relationship between them.

GA4 does ship grouping for other things. Default channel grouping rolls raw source/medium pairs into Organic Search, Paid Social, and so on. Content grouping lets you bucket pages. Both prove the pattern works. Neither extends to events. The one dimension where fragmentation hurts most is the one with no grouping layer.

The Workarounds, and What They Cost

There are two common ways teams try to solve this, and both have a real bill attached.

Rename and standardise upstream. The "do it properly" answer is to fix the tagging: collapse lead_form_header and lead_form_footer into a single generate_lead event with a form_location parameter, retag every variant, and ship it. It's the cleanest end state, but it's a development project, it has to clear QA, and, the part people forget, it does not backfill. Your historical data keeps the old fragmented names. You get a clean number going forward and a seam in every year-over-year comparison.

Rebuild it per report. The faster answer is to stay in GA4 and stitch the events together in each report: a calculated metric that sums the four counts, or an Explore segment that ORs the event names together. This works until you build your next report, where you do it all again. The logic lives inside one report, invisible and unshared. Add a fifth event and every calculated metric and segment you ever wrote silently undercounts, with nothing to warn you.

Approach Where the grouping lives Cost
Rename / standardise upstream In the tagging, before data is sent Dev work and QA; no history backfill; a seam in year-over-year
Per-report Explore or calculated metric Inside one report, not reusable Rebuilt every report; fragile; silently undercounts when a new event appears
Rule-based grouping (reporting layer) A named rule over the raw events Define once; no re-tagging; full history; raw events stay intact

Both workarounds are answering the wrong question. They treat fragmentation as something you fix at the source, when the fragmentation isn't really a tagging fault. It's a reporting need: you want to view four events as one conversion without throwing away the fact that there were four.

Grouping events into a conversion is a reporting-layer job, not a re-tagging job. The raw events are correct; what you're missing is a view that reads them as one.

What Rule-Based Grouping Looks Like

The reporting-layer answer is to define a conversion as a rule over a set of event names, and let the report apply that rule at read time. "Leads" becomes a named thing that means lead_form_header OR lead_form_footer OR learn_more_a OR learn_more_b. The total is computed when the report renders, from whatever the raw events currently say.

Two properties make this better than either workaround. First, it's defined once and reused everywhere, so your scorecard, your trend chart, and your breakdown table all read the same definition, change the rule in one place and every view updates. Second, it works on history. Because the rule runs at read time over events that were always being collected, a "Leads" group you define today reports correctly for last quarter too. There's no seam and nothing to backfill.

Grouping is additive, never destructive. The underlying events, learn_more_a, lead_form_footer, and the rest, stay exactly as GA4 recorded them. The group is a view layered on top, so you can always drop back to the individual events to see which one is actually driving the total.

That last point matters more than it sounds. A grouped "Leads" number tells you the headline; the raw events tell you the story. If leads jump 30% this month, you want to know whether it was the footer form or the campaign variant that moved, and you can only answer that if the components were never thrown away.

Where to Start

Don't begin in the tag manager. Begin with the question, "what conversions does this client actually report on?", and write down the short list: leads, signups, purchases, key downloads. Then, for each one, list the GA4 events that already represent it, fragments and all. That mapping is your grouping definition. Most sites need three to six groups to turn a sprawling events report into the handful of numbers anyone actually asks about.

Renaming events upstream is still worth doing for the worst offenders, and over time it makes the raw layer cleaner. But it's a slow, forward-only fix. Rule-based grouping gives you the clean conversion number today, across all your history, without waiting on a tagging release, and it keeps every underlying event for the day you need to know which fragment moved.

Feeding events from the dataLayer

Hand-coding gtag() calls works until the third person touches the site. The scalable pattern is the one covered in GTM & the dataLayer: the page pushes facts into the dataLayer (dataLayer.push({event: "generate_lead", form_id: "contact"})), and GTM turns those pushes into GA4 events. The division of labour is the point — developers publish facts once, marketers map facts to events without code deploys, and the push timing rules from that guide decide whether your parameters actually arrive.

Ecommerce events: the items array

Ecommerce reporting is not one event but a chain of recommended events tracing the funnel: view_itemadd_to_cartbegin_checkoutpurchase. What makes them special is the items array: every event in the chain carries a list of the products involved, each with its own item-scoped fields.

A purchase event, unpacked
event: purchase
transaction_id: "T-1042"  ·  value: 129.90  ·  currency: "NZD"
items: [
{ item_name: "blue_widget", price: 64.95, quantity: 2 }
]

The same structure appears at every funnel step, which is what lets GA4 compute cart-to-purchase rates per product. It is also exactly the nesting you meet again in the BigQuery export.

Three rules keep ecommerce data trustworthy: send transaction_id on every purchase (it is GA4’s only dedupe key), send value with currency or revenue reports stay empty, and populate the items array on the whole chain — a purchase-only implementation gives you revenue but no funnel.

Advertisement

i