TLDR: If you're pulling GA4
pagePathdata via the Data API and usingmatchType: CONTAINS, your click counts are probably wrong. UseEXACT. For A/B variant pages, useinListFilter— it deduplicates across variants for free.
The Setup
I'm building an internal dashboard for an ecommerce business's webinar ops — tracks all the key metrics for a live event: affiliate revenue, halo-effect sales, and "Clicks to Registration Page."
That last one matters a lot.
It feeds the registration rate, and the registration rate is what the team uses to evaluate every webinar's front-end performance.
So it needs to be right.
The Number That Felt Off
I was testing the GA4 pull against a study results webinar and the click count looked… high.
Not obviously wrong. Just inflated in that quiet way that doesn't trip any alarm unless you're suspicious.
I was suspicious.
Turns out I had matchType: CONTAINS on the pagePath filter, matching anything that contained -rego in the path.
That was the bug. Two distinct failure modes:
- Shopify web-pixel sandbox paths. Shopify emits pageview events from its tracking sandbox with paths like
/web-pixels@<hash>/custom/web-pixel-…/sandbox/modern/pages/<slug>-rego. Same user, duplicate event, completely different-looking path.CONTAINScatches all of it. - Sibling pages share the slug stem. The thank-you page is
-ty. The replay sales page is-replaysales. The A/B variant is-rego-b. Every one of those paths contains the word-regoin some form. You're not filtering the reg page — you're filtering a family reunion.
What Finally Fixed It
Switch to matchType: EXACT on the canonical path only: /pages/202605-af-studyresults-lweb-500-rego.
Done. Sandbox dupes gone. Sibling pages gone.
But then I hit the A/B variant problem.
We run A/B tests on the reg page, so there's a -rego-b path too. I can't just ignore it — those are real users. But if I query them separately and add the numbers, I'll double-count anyone who hit both variants.
The right move: inListFilter with both paths and no pagePath dimension in the response. GA4 collapses it to one row and deduplicates by totalUsers across the whole set.
Real numbers from the event:
-regoalone → 9,984 users-rego+-rego-bviainListFilter→ 11,933 users (deduped — less than the naive sum because some hit both)- Registrations: 5,079
- Registration rate: 42.6%
That's the number I can actually hand to the team.
Why This Matters to Me
The reg rate isn't a vanity metric — it's the signal an ecommerce business uses to optimize every webinar's acquisition funnel.
A wrong number here means bad decisions. Quietly, invisibly bad.
The lesson I'm carrying forward: never assume your slug is unique in a platform's event stream. Shopify, GA4, any system that emits tracking events automatically — they inject paths you never authored. Substring matching trusts you own the namespace. You don't. Match the exact identifier, and when you need to union variants, use a filter that deduplicates by entity instead of summing rows.
P.S. The second non-obvious GA4 landmine from this build — service accounts can't be added to a Workspace-org property, so OAuth-as-user is the only path. That one's a post for another day.