martechdevs has been acquired by Growth and Analytics Partners LLC

Tracking troubleshooting

Tracking break map

Walks a tracking problem from ad click to report and finds the first layer that fails (link and redirect, consent, tag manager, browser request, server container, platform processing, export, warehouse model, report). Sizes an under- or over-count against the backend, proves the failing layer with evidence and drafts the fix for its owner. For GA4, GTM, Google Ads, BigQuery and Looker Studio, with checks for Meta, Shopify and Segment.

FreeVersion 0.3.0Reviewed 20 October 2026

Finds the layer where a tracking problem starts, proves it and hands the fix to that layer's owner. The output is one break-map record: the question, the gap's size and direction against an independent source, containment, a verdict per layer with evidence, the first failing layer, the draft fix and the retest.

The rule: prove the first failing layer before changing anything downstream of it. A downstream change (a regex trigger, a channel rule, a data filter, a SQL patch, a dashboard filter) can make a chart look right while the break stays where it is.

When to use

Use this skill when:

  • Someone says GA4 is wrong, conversions dropped or doubled, or analytics no longer matches the backend, CRM, billing system or ad platform.
  • A release, redesign, CMP change, server-side migration, new redirect, CDN rule or container upgrade is followed by a change in tracked volume.
  • A tag fires in preview but nothing arrives, or data arrives in one tool and not the next.
  • Someone asks how and where tracking can break across tools.

Scope: the tests are written for GA4, web and server GTM, Google Ads, BigQuery and Looker Studio. Meta, TikTok or LinkedIn browser-plus-server routes, Shopify customer events and Segment get checks where they change a verdict; setting them up is out of scope.

Use something else once the layer is known or the question is narrower; if that skill is not installed, use the layer after "otherwise":

  • Unassigned, (not set), Direct or (other) rows with healthy volume: ga4-unassigned-not-set-diagnosis; otherwise layer 1.
  • Order-by-order purchase or revenue gaps: purchase-reconciliation; otherwise layers 3, 7 and 8 with a per-order join.
  • Consent proven to be the failing layer: consent-debugging; otherwise layer 2.
  • Server container proven to be the failing layer: server-side-tracking-debug; otherwise layer 5.
  • Meta Pixel and Conversions API deduplication design: meta-capi-setup; otherwise the layer 5 event_id check.
  • Ad platform and GA4 differ by design (attribution, dates, view-through): platform-number-reconciliation; otherwise layer 9.
  • App stream or SDK events only: mobile-attribution-fundamentals. The web layers here do not apply to app instance IDs.
  • A whole-container review with no incident: gtm-container-audit; otherwise layer 3 tests on each tag.
  • Monitoring after the fix: tracking-monitoring-and-incidents; otherwise propose the retest journey as a scheduled check in the tracking plan.

Inputs

Read these first if they exist: martech-context/stack.md (senders, containers, endpoints, owners), martech-context/tracking-plan/ (the event contract and its expected ratio to the backend), martech-context/metrics.md (the metric's definition) and martech-context/decisions.md (recent CMP, attribution, filter and timezone decisions).

Then gather:

  • The complaint as stated: report or dashboard, metric, dimension, date range, timezone, filters and what it was compared with.
  • An independent daily count of the outcome from the system that commits it (backend, billing, CRM), same days and timezone, with outcome IDs where the event carries one. If none exists, say so; step 5 then uses the repeated-journey proof.
  • The change log for the window: app releases, web and server container versions with publish times, CMP and vendor scripts, CDN and gateway routes, ad account changes, GA4 property change history, export and model changes, GTM and GA4 release notes.
  • Read-only access: GA4 (analytics.readonly), GTM Read permission or a tagmanager.readonly token, BigQuery, Google Ads and tagging-server logs.
  • A test kit: fresh flagged test identities, a clean desktop browser profile, Safari, and an iOS device on the current version.

Test-traffic rules and access details: references/test-traffic-and-access.md. Never ask for, print or store credentials or customer personal data. Redact HAR files and screenshots before saving them.

Procedure

1. Write the question as a record

Copy assets/break-map-record.yaml. "GA4 is wrong" is not a question. "GA4 sign_up per backend signup fell from about 85% to 34% from 2026-09-08 (UTC), completed days" is.

2. Size, date and contain the break before opening any configuration

  • Compare ratios, not counts: analytics outcome divided by independent outcome, per completed day. Direction: under (below the baseline band) or over (above it, or above 100% for a once-per-outcome event).
  • Completed days: GA4 processing can take 24 to 48 hours, so use days that ended more than 48 hours ago. Google Ads dates conversions by ad interaction, so recent days fill in as lag passes: compare on Conversions (by conv. time), or drop the last N days, N being the account's observed lag.
  • Baseline band: the ratio's range over the previous 28 comparable days (same weekday type, holidays excluded), not 100%.
  • First-change date: the first of at least 2 consecutive completed days outside the band, or of 3 days out of 5. A single day outside is "watch", not "break". Line the date up with the change log.
  • Offsetting errors: for an outcome event with an ID (sign_up, generate_lead, purchase), also compute per day unique-ID coverage (distinct analytics IDs found in the backend, divided by the backend count) and events per ID. Events per ID above baseline, or coverage below its band while the ratio holds: record "offsetting errors" and walk both the under- and over-count routes.
  • Split the ratio by every segment both sides share, then by analytics-only ones: page or form, sender (browser, server, Measurement Protocol, gateway, non-Google pixel), browser, device, consent state, region, channel, auth method, stream.
  • Rule out a mix shift (segment ratios hold, only the mix moved: record no break), a change to the independent source's definition, and low volume (under about 30 outcomes per daily bucket: use weekly buckets).
  • Where to start:
    • Over-count, offsetting errors, or a drop concentrated in one page, form, route or event: tag manager and browser request; for over-counts, events per outcome ID and every sender.
    • Uniform drop from a CMP or banner change: consent.
    • Uniform step change on one date with no CMP change: server hosting and logs, data filters and debug_mode, GA4 property change history, then the release notes for that date.
    • Counts fine but source or campaign wrong, a domain handoff, or Safari or iOS only: link and redirect.
    • Only Google Ads low: the Google Ads checks in platform processing, then consent and link.
    • GA4 fine, BigQuery or dashboard wrong: export, then warehouse, then report. Only a report differs: report.
  • Layers above the starting point still need pass evidence. Queries, sender inventory and guards: references/sizing-and-proof.md.
  • Contain, without waiting for the proof. When the gap is outside the band for at least 2 completed days and the affected conversion feeds Smart Bidding, audiences or automated budget rules, draft for the owners: a Google Ads data exclusion, a "provisional" annotation on affected reports, and the automations to pause. Containment changes no collection and is not a fix. Exclusion rules (click dates, account time zone, conversion delay, end date): the sizing reference, Contain.

3. Draw the path for one failing journey

List the hops this outcome takes: ad click, redirects, landing page, domain handoffs, consent, tag manager, browser request, gateway or server container, destination, platform processing, export, warehouse model, report. Mark absent layers not applicable. One journey, one event, one destination at a time.

4. Walk the layers in order

Record pass, fail, not checked or not applicable for each layer, with evidence; a verdict without evidence is "not checked". Run every journey under the test-traffic rules: a fresh flagged test identity, Preview or debug mode, TeSter-123 as the only click ID, ad conversion hosts blocked unless under test, the developer filter state read first. Tests, evidence and traps: references/collection-layers.md (layers 1 to 5) and references/processing-and-reporting-layers.md (layers 6 to 9).

  1. Link and redirect
    • Fails as: paid clicks land as Direct, Unassigned or (not set); click IDs or UTMs lost in a shortener, locale, login or checkout redirect; _gl lost at a domain boundary; a payment provider return starts a referral; Safari or iOS only loss.
    • Pass: in Chrome or Firefox the final URL and the dl of the first GA4 request carry the same click ID and UTMs, and one client ID and session cross each domain boundary. In Safari's protected modes, a page location without its query string is browser policy, not a fault.
  2. Consent
    • Fails as: a uniform drop from a CMP release; sessions without session_start; tags firing before the default; Google Ads conversions lost after the landing page.
    • Pass: per region, the default is set before any tag reads consent, the update follows the choice, and requests match the approved basic or advanced mode.
  3. Tag manager
    • Fails as: one form or path stops after a release; the tag under Tags Not Fired; preview works and production does not; duplicates; a Google-side change on a date with no publish.
    • Pass: the event has the agreed name and keys and the tag fires once, in the live version. Live version unchanged on the first-change date: the break is outside the container.
  4. Browser request
    • Fails as: tag fired but no request; a blocked or cancelled request; CSP errors; a new client ID on every page; a gateway path that stopped forwarding.
    • Pass: each event appears once across the collection requests, to the intended host with the expected ID and parameters, status 2xx.
  5. Server container
    • Fails as: events reach the server but not the platform; preview works, production does not; everything stops at once; browser and server copies of one event carry different event IDs.
    • Pass: the intended client claims, fields and consent survive, the outgoing request succeeds, and tagging-server logs show production traffic.
  6. Platform processing
    • Fails as: rows withheld; traffic removed by a data filter; key event not marked or auto-marked; (not set) for a new parameter; Measurement Protocol events missing or Unassigned; a Google Ads action inactive, secondary or out of the bid goal.
    • Pass: the test event is visible, no active filter or setting removes production traffic, and the Google Ads action is recording and still in the bid goal.
  7. Export
    • Fails as: BigQuery lower than GA4, missing or expired daily tables, intraday double counts.
    • Pass: every expected daily table exists and daily counts match GA4 within known definitional differences.
  8. Warehouse model
    • Fails as: dashboard differs from the raw export; recent days rise later; shifted day boundaries; duplicates.
    • Pass: each raw-to-model difference is explained by a documented rule.
  9. Report
    • Fails as: two reports disagree; Google Ads and GA4 disagree by date; a filter the viewer cannot see; a Looker Studio tile lags or breaks.
    • Pass: aligned reports agree, or the difference has a named, documented cause.

5. Prove the first failing layer

A layer is the first failing layer only when all three hold:

  • Every layer above it has pass evidence for the same journey.
  • The failing journey fails at this layer and a comparison journey that should pass (an unaffected path, the previous version, another browser) passes at this layer.
  • It explains the size from step 2: the failing segment's absolute gap is at least 80% of the total absolute gap. Below 80%, keep walking and record a second break.

With no independent count: the failing journey fails here in 3 of 3 runs across two browsers, the comparison passes 3 of 3, share_of_gap_explained is "not measurable", and the case stays open until a count exists.

6. Hand off the fix, then retest the same journey

  • Fix at the failing layer and its contract, as a draft (diff, change list, version note) for its owner, and stop for approval. If the app renamed a dataLayer event, the app restores the agreed name; a widened GTM trigger hides the next rename.
  • If containment did not already cover it, draft the Google Ads data exclusion now, under the same rules.
  • After release, rerun the same journey through every layer to the report, then compare completed days after the processing window.
  • Record what cannot be recovered: gap dates, affected destinations, and whether any backfill is safe.
    • Measurement Protocol backdates at most 72 hours; under the default RELAXED validation, older events are re-stamped to 72 hours ago, so a backfill misdates them.
    • Google Ads: Google advises against backfilling conversions; where an exclusion was applied, a reporting backfill waits at least 5 days after it.
    • Ad conversion recovery from stored click IDs is a separate decision (offline-conversion-import if installed). Read the click-through conversion window of the conversion action receiving the upload and Google's upload limits before promising recovery; a click older than that window fails with EXPIRED_EVENT.
  • Propose a gap annotation in each affected report.
  • Propose, do not write: a dated entry in martech-context/decisions.md, the contract and regression-test link in martech-context/tracking-plan/, and the baseline band if it changed. Wait for approval.

Common failure modes

  • "Tag fired" or HTTP 2xx read as delivery. Firing proves a trigger matched; the Measurement Protocol returns no error codes even for malformed events.
  • A frontend refactor breaks triggers that read CSS classes, element IDs or native form submit: a drop on one path from the release date, container unchanged.
  • Losses and duplicates cancel out. Lose 10 outcomes and double count 10 others and the ratio does not move; only coverage and events per ID show it.
  • A percentage without its denominator, a mix shift or one odd day read as a break.
  • Two layers changed at once, so the retest cannot say which worked.
  • A collection break "fixed" in a report with a channel rule, regex or SQL patch.
  • debug_mode left on in production: an active developer traffic filter removes that traffic permanently, and debug_mode: false does not turn it off.

Worked example

Acme, a fictional SaaS, sees GA4 sign_up fall from about 85% to about 34% of backend signups after a frontend refactor. A data exclusion is drafted at sizing. The split puts the gap in the email form on /signup; the live container predates the break, and Preview shows the form pushing signUpComplete where the trigger expects signup_complete. The fix restores the agreed name with a regression test. Full record: references/worked-incident.md.

Acceptance checks

  • Record: question, metric, scope, date range, timezone, filters, independent source and first-change date are filled. Pass: no template text remains.
  • Sizing: ratio per completed day, comparable-day band, 2-day persistence, direction, segment splits, guards, and coverage and events per ID for an event with an ID. Pass: the gap is stated as an absolute gap with its direction.
  • Containment: when the trigger is met, the drafted exclusion, annotation and automation list are in the record with dates. Pass: proposed before the proof, nothing applied without approval.
  • Test traffic: test events are labelled and kept out of every comparison. Pass: the developer filter state, or the logged test times, is in the record.
  • Layers: every layer on the path has a verdict with evidence or "not checked" with a reason. Pass: no pass without evidence.
  • Proof: the first failing layer meets step 5. Pass: a passing comparison journey and the 80% share are recorded, or the 3-of-3 runs with "not measurable".
  • Fix: a draft at the failing layer with a named owner and approval before any live change. Pass: nothing downstream was changed to compensate.
  • Retest: the same journey passes at every layer to the report, and the ratio is back inside the band for at least 2 completed days. Pass: both are recorded with dates.
  • Gap: unrecoverable dates and affected destinations are written down. Pass: report annotations and any ad data exclusion are proposed.
  • Privacy: no real email addresses, IP addresses, names, click IDs other than TeSter-123, or token-like strings in the record, HAR files or screenshots. Pass: a search of each for @, IP patterns, gclid=, gbraid=, wbraid=, token, key= and Bearer finds only test values.

Boundaries

  • Read-only. No container publishes, GA4 admin changes, filter activations, model edits or ad data exclusions. No test conversions to ad platforms or real-recipient flows. Every change is a draft that stops for human approval.
  • Consent policy belongs to the privacy owner; never set denied consent to granted to restore a number. Browser blocking is a measurement limit to report, not to route around.
  • Hand-offs and read-only modes:
    • GA4: Google's GA4 MCP server (Experimental, local, analytics.readonly) reads reports with run_report and run_realtime_report. Admin changes are made by a person.
    • GTM: Google ships no Tag Manager MCP server. Read with a container Read-only account or a tagmanager.readonly token. Stape's GTM MCP server requests publish and delete scopes and has no read-only mode; authorise it only with that account.
    • BigQuery: the BigQuery remote MCP server's execute_sql_readonly; block execute_sql with an IAM deny policy.
    • Google Ads: Google's Google Ads MCP server. Its GAQL tool is search in the "search" category, listed by clients as search_search with the bundled tools_config.yaml; the prefix follows that file.
    • Meta: Events Manager's Test Events tool and deduplication view, read by a person. Events sent with test_event_code still flow into Meta's ads measurement.
    • Server hosting: the Cloud Logging MCP server's list_log_entries for tagging servers on Cloud Run, or the provider's logs; changes through Stape's or the cloud provider's own tooling.
    • Docs: Google's Developer Knowledge MCP server for developers.google.com and docs.cloud.google.com; open help-centre pages directly.

Live docs

Platform settings, limits and menu paths change. Before stating any parameter name, limit, quota or UI path:

  • Fetch the current page from the vendor docs MCP server or llms.txt listed in sources.yaml, or open the canonical URL.
  • If the live page disagrees with this skill, follow the live page and tell the user what changed.
  • Cite the URL you used.

The entries that matter most here: GTM release notes and API references, GA4 freshness, data filters and change history, BigQuery export, the Measurement Protocol, Google's consent guides, Google Ads data exclusions and offline import, the server-side and gateway pages, and WebKit's tracking prevention and Safari posts. Facts were checked on 2026-10-17 and the review fixes on 2026-10-20.

Book a Free Call

Thirty minutes on your stack and what it needs. Free, and no pitch.

Thirty minutes, and you leave with a plan

We look at what you have, what it is costing you and what to do about it first.

  • 30 minutes
  • Video call, link on booking
  • No obligation

What we'll cover

  • Your current stack and where it hurts
  • Quick wins we can ship first
  • An integration roadmap
  • Timeline, scope and next steps

Calendar not loading? Open it in a new tab or email hello@martechdevs.com.