The problem
Browser-side tracking was quietly bleeding data.
Between iOS privacy changes, ad blockers, and shorter cookie lifespans, the pixel was undercounting conversions. Shopify's own reports, GA4, and the ad platforms all told different stories, so budget decisions were effectively guesswork.
What the audit found
I reviewed the GA4 property, the existing GTM setup, and each ad account pixel before touching anything. The core issues:
- Purchase events fired twice in GA4, once from a hardcoded tag and once from GTM, inflating conversions.
- The Meta pixel ran browser-only with no Conversions API, so blocked and dropped events were lost outright.
- No shared event ID between the pixel and any server event, meaning deduplication was impossible even if CAPI were added.
- Checkout and thank-you page tracking was tied to the legacy checkout and set to break on Shopify's checkout extensibility migration.
- UTMs dropped on redirect, so attribution was inconsistent across channels.
The rebuild
I stood up a server-side GTM container and rebuilt the measurement layer around it.
GA4 was reconfigured cleanly across web and server so each event fired once. Meta's Conversions API was added and deduplicated against the browser pixel using a shared event ID. Customer email and phone were hashed and normalized before being passed, keeping the match quality high without handling raw PII improperly.
Consent mode was wired in so tracking respected user choices, and the full ecommerce funnel was mapped end to end, from product views through add-to-cart, checkout steps, purchases, and refunds. Checkout tracking was rebuilt to survive the extensibility change.
Proof
Nothing went live as "trust me."
I ran test purchases and validated them in GA4 DebugView and Meta's Events Manager, confirmed deduplication held on the event ID, and checked the event match quality score. Shopify, GA4, and the ad platforms were reconciled until they agreed within a sensible tolerance.
Outcome
Recovered about 14% of purchase conversions that the browser-only setup had been dropping, mostly from iOS traffic and ad-blocked sessions. Meta event match quality climbed from 4.2 to 8.6 once hashed customer data was passed server-side.
The gap between Shopify's reported orders and Meta's attributed conversions narrowed from roughly 30% down to under 5%, so the three sources finally agreed within a tolerance the team could live with.
Cost-per-acquisition in Ads Manager dropped noticeably in the weeks after, not because acquisition changed, but because the platform could now see conversions it had been blind to.
The bigger win
The team got a full setup document alongside it, so the tracking stays maintainable without me.
Before vs. after
Browser-only pixel, duplicate GA4 purchases, no deduplication, and checkout tracking set to break on migration.
Server-side GTM, Conversions API deduplicated on a shared event ID, and hashed customer matching.
Why it mattered
The team was pausing and scaling campaigns on these numbers. Once the sources agreed, those decisions could be made from data the team trusted.
What I delivered
Stack: Server-side GTM, GA4, Meta Conversions API, Shopify checkout extensibility, consent mode, hashed customer matching.
The takeaway
Ad platforms can only optimise on the conversions they can see.
Moving tracking server-side gave Meta and GA4 the data the browser was losing, and gave the team numbers that matched Shopify.
Is your pixel missing conversions?
I’ll check your tracking against your Shopify orders and show you where data is being dropped.
Get a free tracking health check →