TRACKING SPECIALIST — BARIS ASA · LONDON
Synctag
Start the check → TRACKING SPECIALIST — BARIS ASA · LONDON
THE ARCHIVE · FAULT INDEX

The fault index

The same faults turn up across the archive. Each one is defined here once: what it looks like, why it happens, where it gets caught, and what putting it right involves. The cases, the intake check and the services all cite these codes.

← back to the homepage

F-1xx — Collection & duplication

Conversions miscounted at the source: fired twice, or double-attributed across browser and server.

F-101

Duplicate conversion firing

▮▮▮▮▯
Symptom
Purchases counted twice: revenue inflated on Meta, and in GA4 and Google Ads once transaction_id goes missing or changes per fire. ROAS looks great, until finance disagrees.
Cause
The purchase tag fires more than once per order: a theme update double-injects it, a tag lives in both GTM and the platform, or a thank-you page reloads.
Found in
Tag Assistant / GA4 DebugView: two purchase events for one order, the second with a missing or different transaction_id. Or GA4 purchases running ahead of the store's own order count.
The fix
Find every place the conversion fires, consolidate to one, and key it on transaction_id so a reload can't double-count.
F-102

Platform signals not deduplicated

▮▮▮▯▯
Symptom
Meta and Google report more conversions than actually happened. The browser hit and the server hit both claim the same sale.
Cause
Server-side conversions sent without the dedup key the platform needs: Meta CAPI and the Pixel firing without a shared event_id, or Google's server and browser conversions without a shared transaction_id, so the two hits are never recognised as one sale.
Found in
Meta Events Manager showing low or zero deduplication; conversion counts running above actual order counts.
The fix
Send the matching dedup key on both browser and server: event_id for Meta, transaction_id for Google, so each conversion is reconciled and counted once.
F-103

dataLayer timing & race conditions

▮▮▮▯▯
Symptom
Parameters there one day, missing the next: items arrays empty, values intermittently zero. The same tag passes in testing and fails for real users.
Cause
Tags fire before the dataLayer is populated. The tag races the push, or fires on page view while the ecommerce object arrives a beat later.
Found in
GTM Preview: variables resolving undefined on first fire; GA4 events arriving with missing parameters on a fraction of hits only.
The fix
Re-sequence the firing: trigger off the dataLayer push itself, not the page view, and verify every variable resolves before the tag ships.
F-104

Key events & counting mis-set

▮▮▮▮▯
Symptom
The event fires, but the count is wrong: GA4 inflated by a non-sale marked as a key event, Google Ads missing a second order from the same ad click on Count: One, or a conversion counted twice or never imported.
Cause
The event was never marked as a key event, its GA4 counting method is wrong (Once per event where it should be Once per session, or the reverse), or its Google Ads Count is wrong (Every where it should be One, or the reverse). Either way, Ads imports the wrong set.
Found in
GA4 Admin: the key-events list not matching what the business calls a conversion; the Ads conversion column disagreeing with GA4 for the same event.
The fix
Mark the right events as key events, set each counting method deliberately, and import the correct set into Google Ads.

F-2xx — Signal lost in transit

The event happened, but it never reached the platform intact. Gated by consent, or stripped on the way.

F-201

Consent Mode absent or mis-wired

▮▮▮▮▮
Symptom
EU/UK customers are buying, invisibly. A banner is installed, but conversions from consented users still don't show up.
Cause
The consent banner sits in front of the tags but Consent Mode v2 was never wired, or wired backwards. Tags either fire with no signal, or never fire at all.
Found in
Consent Mode debugging: default/update states missing or inverted; a visible gap between platform sales and tracked conversions in EU traffic.
The fix
Wire Consent Mode v2 correctly to the banner, with modelled recovery for non-consenting users where volumes allow it. Compliant, with no silent data loss.
F-204

Attribution lost in transit

▮▮▮▮▯
Symptom
Traffic that clearly drove sales piling up under "direct / none", or your own payment processor sitting in the top referrals. Real channels get no credit.
Cause
Campaign parameters or the Google click id (gclid) stripped by a redirect; a cross-domain step running without GA4's linker, so the session restarts; or a payment provider's return trip overwriting the original source.
Found in
A suspiciously large "direct" channel, or a checkout/payment domain showing up as a top referral; sessions arriving from ad platforms with no campaign attached.
The fix
Preserve UTMs and the gclid across redirects, configure cross-domain linking and the unwanted-referrals list, and stop the payment round-trip from overwriting the source.
F-205

Self-referrals & session fragmentation

▮▮▮▯▯
Symptom
Your own site or your payment gateway sits in your referral report (shop.example.com "referring" www, or paypal.com / referral), and one journey is counted as two sessions at the hop.
Cause
A new session starts mid-journey: a second root domain without cross-domain measurement, a subdomain whose cookie is set on its own hostname, or a payment step that outlasts the session timeout. The new session takes the hop as its source unless that domain is on the unwanted-referrals list.
Found in
Referral reports listing your own domains or a payment gateway, often converting far above the site average; landing pages that are mid-journey URLs; users and sessions both inflated on multi-domain journeys.
The fix
Keep one cookie identity across the journey (automatic cookie domain, cross-domain measurement for second domains), list payment and own domains as unwanted referrals, and verify one session survives the whole journey end to end.

F-3xx — Ecommerce & reconciliation

Funnel events partial or mismatched, and GA4 never agrees with the store platform.

F-301

Ecommerce events partial

▮▮▮▮▯
Symptom
Funnel blind spots: you can see purchases but not where shoppers drop off. GA4 never reconciles with the store platform.
Cause
Only some of the ecommerce events are implemented (purchase but not add_to_cart / begin_checkout), or the data layer is missing item-level detail.
Found in
GA4 ecommerce reports with gaps mid-funnel; item or revenue totals that don't match Shopify/Woo/the backend.
The fix
Implement the full ecommerce event set with a complete data layer, then reconcile GA4 against the platform row by row.
F-302

Conversion value inconsistent

▮▮▮▯▯
Symptom
Every platform reports a different revenue figure for the same orders: one includes shipping, one doesn't, one has its own currency idea. ROAS depends on who you ask.
Cause
Conversion value is built separately per destination: tax and shipping in one tag, out of another; currency left to default on one platform; discounts applied in some places and not others; or the amount sent in minor units (pence, not pounds).
Found in
Row-by-row reconciliation: per-order values diverging by exactly the tax or shipping amount, or by exactly 100x; currency mismatches in multi-market accounts.
The fix
Define value once (what's in, what's out, which currency) and feed every platform the same definition from one variable.

F-4xx — Server-side & match quality

Browser-only collection, with signal lost to ITP, blockers and poor match rates.

F-401

Server-side signals absent

▮▮▮▮▯
Symptom
Conversions missing, more where ad blockers and Safari traffic run high. Meta's Event Match Quality is low and Google Ads under-matches, so the ad platforms optimise on thin data.
Cause
Collection is browser-only. Ad blockers stop some requests leaving the browser, and Safari deletes cookies written by JavaScript, so some sales never reach the platform and others can't be tied back to the click.
Found in
Low event match quality scores; a persistent gap between platform-reported and actual conversions even after consent is fixed.
The fix
Measure the gap first. If it survives consent and click-ID fixes, put a tagging server on your own domain, let it write the identity cookie, and send Purchase through the Conversions API and Enhanced Conversions with shared keys.
F-402

Enhanced Conversions not configured

▮▮▮▯▯
Symptom
Google Ads reports fewer sales than the store, and Safari and mobile buyers look worse than they are. Lead campaigns optimise on thin data.
Cause
The customer's hashed email never reaches Google in a usable form: the setting is off, ad_user_data consent blocks it, the tag fires before the email exists, or the format is wrong.
Found in
Google Ads Diagnostics: Enhanced conversions not in use, Needs attention, No recent data, Missing user-provided data; a low match rate; an empty em parameter on a test order.
The fix
Turn on Enhanced Conversions and accept the customer data terms, make ad_user_data follow the banner, push the email into the dataLayer before the conversion tag fires, send it in Google's format, and verify with a test order.
F-403

GA4 conversions not importing into Google Ads

▮▮▮▯▯
Symptom
GA4 records sales from Google Ads clicks, but Google Ads shows no GA4 conversions, or the GA4 conversion action sits at zero.
Cause
A link in the chain is broken or never made: no link or a link to the wrong Ads account, auto-tagging off or the gclid stripped, no key event, no conversion action created from it, or an import left secondary, so it shows in All conv. only and nothing bids on it.
Found in
Google Ads Goals with no Google Analytics source; GA4 Product links pointing at another customer ID; google / cpc sales with the campaign (not set).
The fix
Link GA4 to the Ads account that runs the campaigns, keep auto-tagging on and the gclid intact, create the conversion action from the key event, decide whether it is primary, and verify after 48 hours of spend.

F-5xx — Documentation & handover

Nothing written down, so every future change starts as archaeology.

F-501

Zero documentation

▮▮▮▮▮
Symptom
Nobody can say what fires, when, or why. Every future change, or staff handover, starts as archaeology.
Cause
The container grew by accretion: tags added under deadline, no naming, no record of what each one is for or what depends on it.
Found in
A container full of unnamed tags and triggers; no measurement plan; the previous setup's logic living only in someone's head.
The fix
Write the tracking documentation: a measurement plan, a map of every tag in the container, and a change log. Rename the container to match, and hand over a record your team can change against.

F-6xx — Configuration & data integrity

Collected, but corrupted: unregistered dimensions, internal noise, and data that shouldn't be there at all.

F-601

Parameters sent, never registered

▮▮▮▮▯
Symptom
A parameter DebugView shows on the event is missing from the report picker, or reads "(not set)" on every row. It is being sent; the report just can't see it.
Cause
Event parameters pushed faithfully into the dataLayer and collected by GA4, but never registered as custom dimensions or metrics in admin, or registered under a name the tag doesn't send. Collected, stored, invisible.
Found in
DebugView showing the parameter on the event while reports can't offer it or show (not set); a custom-definitions list far shorter than the measurement plan.
The fix
Register every reporting parameter as a custom dimension or metric, scoped correctly, and retire the ones nobody reads.
F-602

Internal & bot traffic counted

▮▮▮▮▮
Symptom
Sessions look healthy until you realise a chunk of them are you: the office, the dev team, the agency, and a swarm of bots dressed as customers.
Cause
Internal-traffic filters never defined or left sitting in "testing"; staging and preview domains feeding the production property; known-bot exclusion assumed to catch what it doesn't.
Found in
Geography reports starring the office's city; conversion spikes that match deploy days; the hostname report listing staging URLs.
The fix
Define and activate internal-traffic filters, exclude dev and staging hostnames, and baseline how much of the "traffic" was never customers at all.
F-603

Email addresses (PII) leaking into GA4

▮▮▯▯▯
Symptom
Customer email addresses sitting in GA4 page URLs and event parameters, splitting your page reports and breaking Google's PII policy.
Cause
Forms passing email or phone into the URL on submit; success pages carrying PII in query strings; other tags on the same page reading the same URL.
Found in
Page reports with @ in the URL; query parameters like ?email=; Data redaction switched off on a property created before the feature, or no query parameters listed.
The fix
Close the source (form method, redirects, email links), switch on GA4's Data redaction for the web stream, then remove what is stored with a data deletion request.

R-5xx — Reporting & dashboards

The numbers exist but nobody trusts them. Definitions disagree from one viewer to the next.

R-501

Reporting nobody trusts

▮▮▮▯▯
Symptom
Dashboards exist, but every meeting argues about whose number is right. The report gets opened once, then ignored.
Cause
No agreed definition per metric: "revenue", "conversions" and "sessions" mean different things in different tiles, pulled from sources that don't agree.
Found in
Two dashboards showing different totals for the same thing; metrics with no documented definition or owner.
The fix
Write a metric register: one definition, one source and one owner per number. Rebuild the tiles to it and label what each number means.
R-502

GA4 (other) rows, thresholds & sampling unexplained

▮▮▯▯▯
Symptom
An (other) row swallows part of a breakdown, rows vanish when you drill down, or the same report shows different numbers on different days, and nobody can say why.
Cause
(other) from tables past their row limit, usually a high-cardinality custom dimension; data thresholds withholding small rows; sampling above the event quota; dashboards hitting Data API quotas. Nobody labelled which applies where.
Found in
An (other) row in a report with secondary dimensions; the thresholding notice or sampling percentage nobody reads; rows that come back when the date range widens; dashboard totals that disagree with the GA4 UI itself.
The fix
Clean high-cardinality dimensions at source, keep queries inside the sampling and API quotas (BigQuery export where it matters), and label every tile where (other), thresholds or sampling can apply, so a missing row has a stated reason.

U-0xx — Unmeasured / no baseline

You can't say what is and isn't tracked. There's no ground truth to argue from.

U-001

Unmeasured, no baseline

▮▮▮▮▯
Symptom
Nobody can say what is and isn't tracked. Decisions run on gut because there's nothing to check them against.
Cause
Tracking was installed and never checked against the store's orders. Tags were added over years by different people, and nobody holds the full list.
Found in
This is the starting state, not a single bug. A tracking baseline, usually the first output of a tracking audit, turns U-001 into a known list of specific faults.
The fix
Build a tracking baseline: list every tag and app that sends data, place one test order, match a full week of store orders with GA4 purchases on transaction_id, and record the Google Ads and Meta figures for the same week. Every later fix is measured against it.

Recognise two or more in your own setup? The intake check speaks the same codes, or open a case directly.