Data collection is about whether GA4 is actually seeing what happens on the site. Problems here are invisible in the reports — a page that doesn't fire the tag looks like a page that nobody visits, not like a broken page.
Chapter 2 of 6 · GA4
Layer 1: Data Collection Audit
Check whether GA4 is actually capturing events on every page type, including tag coverage, enhanced measurement, and dataLayer. Chapter 2 of the GA4 Best Practice guide.
2 min read
What a healthy hit looks like: the tag shows as fired on the page, and the hit carries the event name and parameters you expect.
| Check | What to look for | How to verify | Fix if failing |
|---|---|---|---|
| Tag coverage | GA4 fires on every page type: home, product, blog, checkout, confirmation | Real-time report while browsing each page type, or Tag Assistant Chrome extension | Add missing GTM trigger or page-level tag inclusion |
| Single tag | Only one GA4 tag firing per page (duplicate tags double-count events) | Tag Assistant: check for multiple G-XXXXXXX hits on the same page | Remove duplicate tag from GTM or from hardcoded script |
| Enhanced measurement | Which auto-events are on: scroll, outbound clicks, site search, video, file downloads | Admin: Data Streams: Enhanced Measurement settings | Turn off any auto-events already captured by custom tags (prevents double-counting) |
| Dev/staging separation | Test and development environments are not sending data to the production property | Check hostname in the Pages report — staging URLs should not appear | Use a separate GA4 property for staging, or add a hostname filter to exclude non-production domains |
| dataLayer structure | If using GTM, the dataLayer pushes are formatted correctly and firing at the right point in the page lifecycle | Browser console: window.dataLayer after triggering an event |
Fix push timing (push before GTM fires, not after); fix key casing (snake_case throughout) |
Correct order
dataLayer.push({...})→GTM container loads→GA4 tag fires✓ value captured
The value is already in the dataLayer when the GA4 tag reads it.
Broken order
GTM container loads→GA4 tag fires→dataLayer.push({...})✗ value missing
The push lands after the hit has been sent, so GA4 never sees the value.
Push dataLayer values above the GTM container snippet, before it loads, never after.
Advertisement
i