DEV Community

Cover image for Why your GA4 custom events break at 6 months — A 3-layer mental model
toshihiro shishido
toshihiro shishido

Posted on • Originally published at revenuescope.jp

Why your GA4 custom events break at 6 months — A 3-layer mental model

Six months after launching GA4, you open the report and notice something off. (not set) rates are climbing. The same product is firing purchase with two different parameter structures. Custom event names show up as Click_Button, click-button, and clickButton — split across three rows in the report. Has this happened to you?

I've been there. The first time I instrumented GA4 on my own product, I spent half a day six months later just figuring out why purchase was double-counting tax-inclusive and tax-exclusive revenue. The root cause was almost never technical. It was that I had blurred the boundary between GA4's three event layers from day one.

TL;DR

  • GA4 events have a 3-layer structure (automatic / recommended / custom). Each layer differs in source, editability, and parameter spec — mixing them carelessly guarantees breakage later
  • For e-commerce, lean on recommended events. Sending the 12 events to spec is what keeps standard reports, ecommerce reports, and BigQuery exports consistent
  • Lock down naming rules and parameter design before implementation. Retrofitting "verb_noun / snake_case / no reserved prefix" later is essentially a re-design of all your measurement data
  • Verification is a 3-layer process: DebugView → Realtime → BigQuery. Skip any one and you ship a system that looks instrumented but is silently broken

The 3 layers of GA4 events

The 3 layers of GA4 events

GA4 events fall into three layers based on who sends them and how GA4 recognizes them.

Layer Source Editable Examples
Automatic GA4 tag sends automatically No page_view / session_start
Recommended Your site sends, Google defines spec Name fixed view_item / add_to_cart / purchase
Custom Your site sends and defines Name & params free click_hero_cta / scroll_50pct

The most important fact for e-commerce operators: most behaviors that happen on an e-commerce site are already covered by recommended events. Reserve custom events strictly for behaviors recommended events cannot express.

The 12 recommended events for e-commerce

12 recommended GA4 events for e-commerce

The recommended events for an e-commerce site map to the user journey in 12 items. The most common implementation accident is the purchase event — if transaction_id is empty or duplicated, GA4's deduplication fails and revenue is double-counted. The Shopify thank-you-page case where purchase fires from both "thank you page view" and "app-side conversion tracking" is the most frequent failure I see.

But here's the thing: implementing all 12 recommended events correctly is not the goal. It's the raw material.

The real value shows up when you take the value from purchase and break it down by session, by channel, by landing page. Comparing Revenue Per Session (RPS = Revenue ÷ Sessions) for Google Organic versus Meta Ads visits exposes CVR and AOV gaps and combined investment efficiency in a single number.

Note that Revenue Per Session (RPS) is not yet a widely recognized industry metric, despite being mathematically equivalent to CVR × AOV. Most analytics tools, including GA4, do not surface it as a default metric — you have to construct it from raw event data.

Naming rules — the 3 things to lock down before implementing

Custom event naming rules — good vs bad

The single biggest regret in my early implementation was trying to retrofit naming conventions after events were already flowing. It's essentially a re-design of all your measurement data.

The 3 rules to lock down at design stage:

  1. verb_noun: action as verb (click / view / download), object as noun (cta / whitepaper). Compose click_hero_cta
  2. snake_case: underscores between words. Mixing clickHeroCta (camelCase) or click-hero-cta (kebab-case) splits them as separate events in GA4 reports
  3. Avoid reserved prefixes: ga_ / google_ / firebase_ are silently disabled. If you want a project-specific prefix, use a 1–2 character custom prefix like rs_click_cta

Verification is 3 layers — DebugView, Realtime, BigQuery

3-layer verification — DebugView / Realtime / BigQuery

Once you implement an event, always verify across three layers. Skip any one and you ship a system that "looks instrumented but is silently broken."

  • DebugView shows what GA4 received (seconds, real-time)
  • Realtime report shows what GA4 counted (minutes)
  • BigQuery shows the actual stored parameter structure (1 week post-launch, via SQL)

The gap between DebugView and Realtime is where silent failures hide. Visible in DebugView but not in Realtime → reserved prefix collision likely. Visible in Realtime but not in standard reports → custom dimension not registered.

Wrapping up

GA4 custom event setup is not a technical challenge. The hard part is making the 3-layer boundary explicit at the start, locking down naming rules before implementing, and verifying across all three layers (not just one). With those four steps, your measurement foundation will survive 6 and 12 months.

Full implementation walkthrough — including reserved parameter pitfalls and BigQuery verification SQL — is at GA4 Custom Event Setup Guide.


Question for you: What was the first GA4 event you set up that you later wished you'd designed differently? Curious to hear what tripped people up — and whether the 3-layer model would've helped.

Top comments (0)