google analytics8 min readBy Phloz team

The GA4 audit checklist agencies actually use

Most agency-inherited GA4 properties have at least three silent bugs. This is the 12-point audit that finds the dead conversions, the misclassified events, and the missing cross-domain config — without breaking what's working.

Inherit a GA4 property that's been managed by 4 different freelancers since GA4 launched and you'll find the same pattern: half the marked conversions are misfires from 2023, custom dimensions registered against properties that no longer exist, and a "Direct" channel that's secretly 40% Stripe redirects.

The audit is mechanical. 12 checks, ~60 minutes, no cleverness required. This is the version we run on every new client before we 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_Angeles produces day-boundary bugs in every dashboard.
  • Currency: matches the e-commerce currency the storefront sends. A property set to USD but receiving GBP purchase events 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 Settings → Data Retention. Default is 2 months for event-level data, which silently caps every YoY comparison and most cohort views. Change to 14 months (the free max). 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. Mismatched IDs are the #1 cause of "the dashboard shows nothing but Real-time works."
  • 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; e-commerce sites often want to disable scroll and video_engagement because the events overwhelm the more important ones at the GA4 free-tier event-volume cap.
  • 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. Half 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 lose the GA4-side machine-learning enrichment that recommended names get.

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.com and checkout.stripe.com
  • paypal.com
  • klarna.com
  • pay.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_type filter 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: only set if you're paying for the data export. Daily-only is free up to 1M events/day; streaming export costs real money.
  • Search Console link: enables the Search Console reports inside GA4. Easy to forget.

10. Attribution — model + lookback windows

Admin → Attribution settings:

  • Reporting attribution model: GA4 defaults to data-driven; for properties with under ~3000 conversions over 28 days, data-driven falls back to "last click" silently. Verify the property has enough volume to actually use data-driven — if not, document that the displayed model is effectively last-click.
  • Acquisition lookback window: 30 days default; bump to 90 if the client's sales cycle warrants. Acquisition is one-time per user so a wider window is rarely harmful.
  • Conversion lookback window: 90 days default. Aligned with most B2C cycles; B2B may want longer.

11. Cross-domain measurement (if applicable)

If the client's purchase flow crosses domains (example.comcheckout.example.comexample.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:

  1. Trigger the canonical user journey: home → product → add to cart → checkout → purchase (or whatever the client's primary conversion path is).
  2. Watch Realtime fire each event with the right params.
  3. Confirm the purchase event records the correct revenue value AND the right currency.
  4. Confirm the user attribution path shows the correct source/medium (this is where #6 — referral exclusions — pays off).

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 the more common 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) with health-checked edges between them. The map catches the drift before the audit does. Companion reading: the GTM container audit checklist and conversion tracking verification without trusting the dashboard.