The GA4 audit checklist agencies actually use
The 12-point GA4 audit that finds dead conversions, misclassified events, and missing cross-domain config — without breaking what works.
Inherit a GA4 property that's been managed by 4 different freelancers since GA4 launched and odds are you'll find the same pattern: marked conversions that have been misfiring since 2023, custom dimensions registered for parameters nothing sends any more, and Stripe checkouts posing as a traffic source.
The audit is mechanical. 12 checks, ~60 minutes, no cleverness required. Run it on every new client before you touch a single optimisation.
Before you start
Get viewer access at minimum, editor if possible — some checks need to see the data-retention setting or the link configurations, which are admin-scoped. Pull the property in incognito + signed in to the agency Google account, not the personal Gmail. Several of the panels render differently based on which roles your account has across multiple properties.
Open a clean tab for the live site you'll cross-reference against. You'll need it for the Realtime check and for confirming that event triggers actually fire on real user actions.
The 12 checks
1. Property settings — time zone, currency, industry, data retention
Admin → Property settings. Four things:
- Time zone: matches the client's business reporting timezone, NOT the agency's. A US-based agency managing a UK client and leaving the property on
America/Los_Angelesproduces day-boundary bugs in every dashboard. - Currency: matches the e-commerce currency the storefront sends. A property set to USD but receiving GBP
purchaseevents shows revenue as 1.23 USD per £1.00. - Industry category: cosmetic but used by GA4 to seed benchmark comparisons. Set it correctly.
- Data retention: Admin → Data collection and modification → Data retention. Default is 2 months for event-level data. It doesn't touch the standard reports, which keep their aggregates, but it caps every exploration and funnel report — so a YoY exploration or a cohort built there silently stops at two months (Analytics Help). Change to 14 months (the most a standard property allows). Do this on day one of a new engagement; it doesn't backfill.
2. Data streams — measurement ID + enhanced measurement
Admin → Data Streams → click the web stream. Check:
- The Measurement ID (
G-XXXXXXXXXX) matches what GTM is sending. A mismatched ID sends the data to some other property. - Enhanced measurement toggles (the gear icon): page changes, scrolls, outbound clicks, site search, video engagement, file downloads. Each toggle has its own opinion. The defaults are usually fine for content sites; some e-commerce sites turn off
scrollandvideo_engagementso they don't eat into the daily BigQuery export's 1M-event cap (check #9). - For app streams (iOS / Android): the bundle ID / SHA1 fingerprints, and whether the Firebase project link is still live.
3. Conversion events — what's marked, what should be
Admin → Events → Conversions column. Three buckets to triage:
- Real conversions that match the client's business outcomes (purchase, generate_lead, qualified_demo_booked). These stay.
- Vanity conversions (page_view-as-conversion, scroll, every form submit including the unsubscribe form). These get unmarked. Much of the value of GA4 attribution depends on the conversion set being meaningful; "everything is a conversion" = nothing is.
- Stale conversions from old campaigns (Black Friday 2023 promo events). Unmark + archive.
Also: confirm conversion events use the GA4 recommended event names (purchase, sign_up, generate_lead, begin_checkout) where applicable. Custom names work but miss the reporting that recommended events unlock, now and as Google adds more (Analytics Help).
4. Custom dimensions + metrics — registered vs used
Admin → Custom definitions. Two things:
- Cardinality: the free tier caps user-scoped dimensions at 25 and event-scoped at 50. A property at-cap can't add new dimensions without deleting an old one. Check the count and prune unused ones.
- Registered but never sent: open the dimension's "explore" view. If no rows have a value in the last 30 days, the GTM tag that's supposed to set the param is broken (or was removed). Either fix the tag or delete the dimension.
5. Audiences — orphans + bloat
Admin → Audiences. List view. Look for:
- Promo-campaign audiences that haven't been used since the campaign ended. They cost nothing to keep but clutter the picker in Google Ads + DV360 audience selection.
- Overlapping audiences ("Visited /pricing in last 7 days" + "Visited /pricing in last 14 days" + "Pricing page viewers"). Consolidate where the targeting strategy actually differs.
- Audiences with 0 users: definition probably uses a dimension that doesn't fire anymore.
6. Referral exclusions — the Stripe / PayPal / Klarna trap
Admin → Data Streams → click stream → "Configure tag settings" → "List unwanted referrals." Confirm the payment processors the client uses are listed:
stripe.comandcheckout.stripe.compaypal.comklarna.compay.google.com,apple.com(for Google Pay / Apple Pay flows)- Any 3-D Secure issuer domains your specific client routes through
Without this, every successful payment looks like a Stripe referral instead of a continuation of the original session, and your attribution data is silently corrupted.
7. Internal traffic filter — defined AND active
Admin → Data Streams → click stream → "Configure tag settings" → "Define internal traffic." Two failure modes:
- Defined but inactive: filter is created but the corresponding
traffic_typefilter under Data Filters is paused. Test mode counts as "inactive" for production. - Defined too narrowly: a single IP for the agency, missing the client's office IPs (which they use for QA). Their team's testing pollutes the funnels.
8. DebugView — does it work?
DebugView → check that at least one device is currently visible. Then on a clean browser tab, install Google Analytics Debugger (or pass ?_dbg=1 if the site supports it), reload the live site, and confirm:
- The browser shows up in DebugView within ~10 seconds.
- The critical events you care about (the purchase flow, the lead form) appear with all expected event_params, not just the event names.
- No
(not set)values on parameters that should always be populated.
This is the single fastest check for "is the dataLayer push shape correct?" — faster than waiting 24 hours for the standard reports.
9. Linked products — Google Ads, BigQuery, Search Console
Admin → Product Links. Confirm each is connected AND active:
- Google Ads link: enables conversion import + audience export to Ads. Common failure: the link was created when the Ads account was under a different MCC, then re-parented; the link goes "auth required" silently.
- BigQuery link: the export itself is free — BigQuery bills storage and queries beyond its free monthly allowance, and the streaming export at $0.05 per GB. The daily export takes up to 1M events a day on a standard property; streaming has no cap (Analytics Help). A link to a sandbox project (no billing) expires its tables after 60 days and can't stream (Google Cloud), so it can look set up while keeping two months.
- Search Console link: enables the Search Console reports inside GA4. Easy to forget.
10. Attribution — model + lookback windows
Admin → Data display → Events → Key events attribution:
- Reporting attribution model: GA4 defaults to data-driven, which uses the property's own data to work out each click's contribution (Analytics Help). A property with few key events gives it little to learn from, so on a low-volume client compare it with last click in the attribution models report before you lean on its split.
- Acquisition lookback window: 30 days default, and 7 days is the only alternative — it covers
first_visitandfirst_open(Analytics Help). - Conversion lookback window: 90 days default, which is also the maximum (30 and 60 are the alternatives) — a B2B cycle longer than that can't be covered here.
11. Cross-domain measurement (if applicable)
If the client's purchase flow crosses domains (example.com → checkout.example.com → example.com/thanks), cross-domain measurement keeps the session unbroken:
- Admin → Data Streams → click stream → "Configure tag settings" → "Configure your domains."
- List every domain involved in the user journey.
- Test by clicking from one to the other with
?_gl=URL parameters; they should appear automatically.
Without this, the checkout step looks like a new session originating from your own domain.
12. Realtime + a real user journey end-to-end
Finally, the big-picture check. Reports → Realtime. With the live site open in a clean browser:
- Trigger the canonical user journey: home → product → add to cart → checkout → purchase (or whatever the client's primary conversion path is).
- Watch Realtime fire each event with the right params.
- Confirm the purchase event records the correct revenue value AND the right currency.
- Confirm the user attribution path shows the correct source/medium (this is where #6 — referral exclusions — pays off). If source/medium values look fragmented (Facebook vs facebook vs fb), run the client's campaign URLs through our free UTM audit tool — it finds every case split and unmapped medium across the whole link set at once.
If any step doesn't appear, you have a broken tag or a misconfigured trigger. Fix it before touching anything else; the rest of the audit is meaningless against broken instrumentation.
What to do with what you find
Don't try to fix everything at once. Sort issues into three buckets:
- Now: misclassified conversions, missing payment-processor referral exclusions, broken cross-domain config. These corrupt attribution data live and cost the client money in misallocated ad spend every day.
- This sprint: data-retention bumped to 14 months, custom-dimension cleanup, audience consolidation, internal-traffic filter.
- Documented + deferred: everything that's working but suboptimal (vanity conversions someone's old report still relies on, a stale Google Ads link that hasn't been actively used in 9 months). Keep these in your tracking-map handoff doc; they're agency-level technical debt, not bugs.
The whole audit takes ~60 minutes on a property in average shape, ~2 hours on one that's been through five owners. Run it on every new client. Run it again every 6 months on retained clients, because GA4 properties drift even when nobody is actively editing them — new ad campaigns leak conversions in; recommended-event names change with Google's docs; data retention silently expires.
Where this fits with the rest of the tracking stack
GA4 is one node in the bigger picture. The audit above catches GA4-internal issues, but a whole other bug class is integration drift between GA4 and the rest of the stack: GTM is sending an event but GA4 isn't receiving it (broken measurement ID), GA4 has it but Google Ads doesn't (broken product link), Meta is also receiving a duplicate (no event_id for dedup).
That's exactly the moat Phloz was built around: a typed graph of every tracking node (GA4 property, GTM container, ad pixels, conversion APIs) and the connections between them, audited against 20 rules every week. The map doesn't watch GA4 for you — it shows which parts of the setup nobody has checked lately. Companion reading: the GTM container audit checklist and conversion tracking verification without trusting the dashboard.