Skip to content
Back to blog
GA4Jul 10, 2026 · Ludde Nyström · 16 min read

GA4 Revenue Doesn't Match Shopify? Every Cause, Ranked by Likelihood.

Why GA4 revenue doesn't match Shopify, ranked from most to least likely: tag placement, consent, ad blockers, refunds, test orders, and duplicates.

GA4 Revenue Doesn't Match Shopify? Every Cause, Ranked by Likelihood

Marketing pulls up Shopify and sees $42,000 in sales for the week. Someone opens GA4 for the same date range and sees $31,000 — or $58,000. Nobody touched a tag, nobody shipped a deploy, and the question is always the same: which number is real, and why don't they match?

Usually both are telling the truth about different things. Shopify's number is money that changed hands, recorded server-side the instant a payment is captured. GA4's number depends on a browser successfully loading a script and completing a network request before anyone closes the tab, declines a cookie banner, or has an ad blocker in the way. A gap between the two isn't automatically a bug — until it's outside a normal range, at which point it usually is.

Quick answer

GA4 revenue almost never matches Shopify exactly, and a gap of roughly 5-15% is commonly considered normal for a reasonably well-configured store. Ranked by how often each one actually explains a real mismatch: the GA4 tag not running on part of checkout (especially during Shopify's 2026 checkout-extensibility migration), consent-mode losses from EEA visitors who decline tracking, ad blockers and privacy browsers silently dropping the purchase ping, test orders and POS/other-channel sales that never touch a browser, refunds and order edits that move Shopify's number after GA4 already recorded it, and timezone or currency settings that differ between the two admins. If GA4 shows more revenue than Shopify instead of less, the cause is almost always a duplicate purchase tag — a different problem, covered below.

Cause #1: Is Your GA4 Tag Actually Running at Checkout?

Before chasing anything statistical, rule out the mechanical explanation: the event might just not be firing where you think it is. There are effectively three ways a Shopify store gets purchase data into GA4, and most real discrepancies trace back to confusion about which ones are actually active.

Shopify's native integration lives under Settings → Customer events → Google & YouTube app. When enabled, it fires GA4's standard e-commerce events, including purchase, using Shopify's own server-confirmed order data — accurate values, but still delivered through a sandboxed script running in the customer's browser. A custom GTM pixel — the current supported path for checkout-adjacent tracking — is added the same way, at Settings → Customer events → Add custom pixel, using Shopify's Web Pixels API, which exposes a checkout_completed event you can forward into GTM. And then there's the legacy method: pasting a GTM container snippet or a raw purchase script directly into Settings → Checkout → Additional scripts, or editing checkout.liquid directly — an approach many older Shopify implementations still depend on.

That legacy method is actively being shut off in 2026, and this is the single most time-sensitive item on this list. Shopify Plus stores hit their deadline on August 28, 2025; since January 2026, Shopify has been auto-upgrading any Plus stores that still hadn't migrated off the legacy Thank You / Order Status pages by then, with a 30-day notice ahead of the forced cutover. Non-Plus stores (Basic, Shopify, Advanced) run on a separate, later clock: the stated final deadline is August 26, 2026 — after that, Additional Scripts, checkout.liquid customizations, and any script tags on the Thank You or Order Status pages stop firing, on every plan. (Confirm the current date against Shopify's own help center before you act on this — deprecation timelines occasionally shift, and if you're reading this well after mid-2026 the cutover may have already happened.)

The practical risk: if a store's purchase tracking was ever built by pasting a snippet into Additional Scripts, that tracking is either already gone or on a countdown — and because a checkout page rarely gets manually re-tested once it "works," this is a genuinely common way for purchase tracking to go dark without anyone noticing until someone compares GA4 to Shopify and finds a gap that started on a specific, unremarked-upon day. Fix: confirm which mechanism is actually live under Settings → Customer events, migrate anything still depending on Additional Scripts to a custom pixel before the deadline forces it, and re-verify in GA4 DebugView or GTM Preview that purchase actually fires on one real, completed, paid order — not a value someone eyeballed when it was first set up. If preview or DebugView shows nothing at all, start with our GTM tag not firing troubleshooting guide before assuming the cause is statistical. For the full setup walkthrough, including how the native pixel and a GTM container are meant to split responsibilities, see our Shopify GA4 tracking guide.

Cause #2: Is Consent Mode Quietly Modeling Away EEA Purchases?

If your tag is confirmed firing correctly, consent is usually the next-biggest lever, and it's structural rather than a bug to fix. Consent Mode v2 initializes with analytics_storage denied by default; until a visitor explicitly accepts, GA4 either doesn't record a normal measurable hit for that session or sends a stripped-down, cookieless ping. Google's own system then tries to close the resulting gap in aggregate reporting using conversion modeling — a statistical estimate built from the behavior of visitors who did consent, not a literal recount of what the declined visitors actually purchased. Even where that modeling recovers most of the aggregate conversion volume for reporting purposes, it isn't reconstructing any individual declined session's exact order — which is exactly the kind of gap that shows up as "missing" revenue when you compare a specific week to Shopify's exact figure.

How much this affects your specific store depends heavily on two things that vary enormously from site to site: your EEA traffic share, and how your consent banner is actually built. A banner that makes rejection needlessly difficult sees a very different decline rate than a neutral one, and a store that's mostly US traffic will barely notice this cause at all while a store with heavy German or French traffic can see it dominate the whole gap. Rather than trusting a generic industry percentage — the honest ones vary too widely to be useful for your specific store — check your own consent management platform's accept/reject reporting (most CMPs surface this directly) and weigh it against your EEA share of orders. That gives you a real, store-specific number instead of an internet average.

Cause #3: Are Ad Blockers and Privacy Browsers Eating the Purchase Ping?

Even with tags placed correctly and consent granted, GA4 still needs a browser to load a script and complete a network request before anything counts — and Shopify's confirmation of the order has zero dependency on that happening. The payment is captured server-side the moment checkout completes, whether or not the browser ever executes another line of JavaScript afterward. Ad blockers, tracking-protection browsers (Safari, Brave, Firefox in strict mode), corporate network filters, and a customer simply closing the tab before the confirmation page finishes loading all produce the identical symptom: Shopify has the order, GA4 never saw the ping.

There's no reliable, single industry-wide percentage worth quoting here, and we'd rather say that plainly than hand you a number that isn't really about your store. Ad-blocker and privacy-browser adoption varies enormously by audience — a technical or privacy-conscious customer base blocks at a meaningfully higher rate than a mainstream consumer one — and it isn't something you can look up, only estimate. A useful diagnostic: compare the GA4-vs-Shopify gap across channels with very different audiences, for example email or SMS traffic (typically lower ad-blocker usage) against paid social to a tech-savvy segment (often much higher). If the gap moves a lot between the two, ad blockers are a real piece of your specific number. If it stays flat across channels, look elsewhere first. Either way, this is a structural floor, not something to chase down to zero.

Cause #4: Are Test Orders, POS, or Other Sales Channels Padding Shopify's Number?

Shopify's own help documentation is specific about this: test orders are excluded from Sales reports, but they are included in the Orders list and export. So if whoever pulled the "Shopify number" for comparison read it off the Orders page rather than the actual Sales report, test orders placed through the Bogus Gateway — to verify a new checkout flow, a payment gateway swap, or a theme change — can be quietly inflating the Shopify side of the comparison before GA4 even enters the picture.

Separately, in-person POS sales and orders from other channels — a wholesale or B2B channel, Facebook or Instagram Shop, Amazon via Shopify, a manually created draft order — all post as real Shopify revenue with zero browser session behind them. GA4 is fundamentally a browser-behavior tool; it was never going to see these, by design, not because anything is misconfigured. Fix: when reconciling, filter Shopify's Sales by channel report down specifically to "Online Store" rather than comparing against Total sales, and double-check that whoever pulled the Shopify figure used the Sales report and not the Orders list.

Cause #5: Did a Refund or Order Edit Move Shopify's Number After GA4 Already Recorded It?

GA4 doesn't learn about a refund on its own. The Shopify Web Pixels standard event set has no refund event type, for a structural reason: a refund happens inside the Shopify admin, or via the Admin API, well after the customer's browser session has ended — there's no page left for a pixel to fire from. So GA4's purchase revenue for a given order is effectively frozen at the moment of checkout, while Shopify's own reported number for that same order can keep moving for weeks afterward: a partial refund, a cancelled order, a manually adjusted total. Pull both numbers on different days and you can see what looks like a fresh discrepancy purely because Shopify's side is still settling.

Shopify's own documentation even flags an internal version of this same timing effect: its Sales by channel report can show a refund as a positive amount while it's still pending, then flip to negative only once the refund actually completes — meaning Shopify's own two views of the same order can visibly disagree with each other for reasons that have nothing to do with GA4 at all. Fix: compare GA4's purchase revenue against Shopify's gross sales figure, not net-of-refunds, unless you've deliberately built a refund event into your e-commerce tracking — typically via a custom pixel paired with an Admin API webhook, or a server-side Measurement Protocol call triggered on refund. Without that build, GA4 and Shopify's net revenue will never fully tie out, and that's expected, not broken.

Cause #6: Are Your Timezone and Currency Settings Actually Aligned?

GA4's reporting timezone lives at Admin → Property → Property details → Reporting time zone, alongside the property's Currency setting on the same screen. Shopify's lives at Settings → General → Store defaults → Time zone. Nothing forces these two settings to match, and by default they frequently don't — Shopify defaults to whatever the store owner picked during onboarding, GA4 defaults to whatever was selected (or left untouched) when the property was created, sometimes by a different person entirely.

The effect: an order placed at 11:40pm can land on different calendar dates in each system's "today" if the two timezones disagree, which shows up as a same-day comparison that looks off by roughly one night's worth of orders — worse the more volume clusters near midnight in either timezone. Currency compounds this on stores with meaningful non-primary-currency volume: GA4 converts every transaction not already in the property's reporting currency using the exchange rate for the day before the transaction, and re-runs that conversion every time a report is generated, which is a different methodology and a different exchange-rate snapshot than however Shopify settles and reports its own multi-currency orders. That produces a small, permanent, cents-level gap that will never fully reconcile — and isn't worth chasing. Fix: align both timezones first, before touching anything else on this list. It's free, takes five minutes, and a mismatch here can manufacture the appearance of a much bigger problem than actually exists.

What If GA4 Shows MORE Revenue Than Shopify?

Everything above explains GA4 running lower than Shopify. If it's consistently higher — not just noisy, but reliably above — that's a different and much more mechanical failure: almost always a duplicate purchase tag. The most common version is the native Shopify pixel and a separately-built GTM purchase tag both live and firing on the same order; the second most common is two GTM tags both bound to a trigger that matches the same checkout-completion event. Shopify's own documentation explicitly discourages running a GTM-based purchase tag alongside its native Google & YouTube app pixel at the same time, precisely because of this risk.

Because the native pixel and a hand-built GTM tag frequently generate different transaction_id values for the same order — Shopify's own order token versus whatever variable the GTM tag happens to reference — GA4's built-in deduplication, which matches on transaction ID, doesn't catch it. Every real order gets recorded twice: revenue, purchase count, and conversion rate all inflate together, roughly in step. That's often the tell that separates this cause from the others above, which move revenue but rarely double the purchase count to match. Our Shopify tracking guide covers this exact failure mode — and the fix — in more depth, and our GA4×GTM cross-checks post explains why it's invisible from inside either product looked at alone.

Catch duplicate tags before they double your revenue

NiceLookingData's 61-check GA4 audit runs alongside a dedicated GA4×GTM cross-check chapter — 3 checks that only exist because they compare both products at once, including a specific check for GTM tags double-firing the same GA4 key event. It won't reconcile against your Shopify order data directly — nothing that only reads GA4 and GTM can — but it will catch the config-side bug behind most "GA4 shows more than Shopify" reports before months of doubled revenue distort every report built on top of it. Run a free audit.

Does GA4's Attribution Window Change the Revenue Number? (No — Here's What It Actually Does)

This one is worth debunking directly because it causes a specific, avoidable kind of confusion. GA4's attribution settings — Admin → Attribution settings, covering the reporting attribution model and a lookback window that defaults to 30 days for acquisition events like first_visit and 90 days for other key events including purchase (adjustable to 30 or 60 days) — decide which marketing touchpoint gets credit for a conversion in attribution and channel reports. They do not decide whether a purchase event was recorded, or change its dollar value, anywhere in the core Monetization or e-commerce reports. Total purchase revenue is event-scoped: it is what it is, independent of which attribution model is selected.

The confusion usually starts when someone compares Shopify's total against a GA4 number pulled from a channel-split exploration or an Advertising-section report — views where attribution modeling genuinely does reshuffle which row gets credit — instead of the plain Monetization → Overview → Total purchase revenue figure. That reads as a Shopify-vs-GA4 mismatch when it's actually a same-property, same-underlying-data reporting-view mismatch inside GA4 itself. Fix: always reconcile against the flat, unattributed total purchase revenue number, not a channel-attributed view, when comparing to Shopify. Attribution-window confusion shows up even more often one layer over, when GA4's own numbers don't match Google Ads' reported conversions — a related but genuinely different discrepancy from the one this article covers.

So What Discrepancy Is Actually Normal?

Practitioners commonly cite something in the range of 5-15% as an unremarkable gap for a reasonably well-configured store with an ordinary audience mix — small enough that engineering time is usually better spent elsewhere. Other write-ups put the acceptable ceiling a bit higher, closer to 20%. There's no single authoritative number here, and we'd rather say that honestly than hand you a false-precision benchmark: treat any percentage in this space, including ours, as a rough anchor for a gut check rather than a target you're failing if you miss it.

What legitimately shifts your normal higher: heavy EEA traffic behind a genuinely strict consent banner, a meaningful POS or wholesale mix, or a customer base that skews toward ad blockers and privacy browsers. A simple heuristic: if GA4 runs lower than Shopify by an amount inside that range, and the gap is stable month over month, that's very likely the structural tax described above rather than a bug worth hunting. If the gap is unusually large, growing suddenly, or trending the wrong direction — or if GA4 is higher than Shopify at all — treat it as a real, fixable problem and work through the checklist below. This is one specific branch of a broader question; if the symptom you're actually chasing is different from a Shopify mismatch, our symptom-by-symptom GA4 diagnosis covers direct traffic spikes, missing conversions, and a dozen other patterns with the same "most likely cause first" approach.

The 5-Step Reconciliation Checklist

Work through these in order. Each earlier step can manufacture a gap that looks exactly like one of the later causes until you've ruled it out, so starting at the bottom of the list wastes time.

  1. Verify tag placement. Confirm exactly which mechanism sends GA4 the purchase event today — native pixel, a GTM tag via Additional Scripts or checkout.liquid, or a GTM custom pixel via the Web Pixels API — by checking Settings → Customer events directly rather than trusting how it was described when it was built. Then confirm in DebugView or GTM Preview that purchase fires on one real, completed order. This is the most time-sensitive step given Shopify's 2026 checkout migration.
  2. Check consent. Pull your consent management platform's own accept/decline rate and weigh it against your EEA share of orders, so you know roughly how much of any gap is the structural consent-mode floor before treating it as a bug.
  3. Rule out duplicates. Confirm only one mechanism is actually firing purchase — native pixel or a GTM tag, never both — and watch DebugView on a real order for a session that fires the event twice.
  4. Reconcile refunds. Compare against Shopify's gross sales figure, not net-of-refunds, unless you've explicitly built a refund event. Otherwise a recently-refunded order will read as a false "GA4 too high" signal for as long as the refund is settling.
  5. Match timezone, and note currency. Set GA4's Reporting time zone (Admin → Property → Property details) to match Shopify's Settings → General → Store defaults → Time zone. If you run multi-currency, expect a small permanent cents-level gap from differing conversion methodology, and don't chase it.

Whatever gap survives all five steps is very likely the structural tax — consent, ad blockers, POS and other channels — described above. If it's still well outside the 5-15% range after this pass, that's the point to dig into a specific order-by-order comparison rather than guessing further.

Frequently Asked Questions

Why is my GA4 revenue lower than Shopify's?

In roughly descending order of likelihood: the GA4 tag isn't running on part of the checkout flow (increasingly common during Shopify's 2026 checkout-extensibility migration), Consent Mode is modeling away purchases from EEA visitors who declined tracking, ad blockers or privacy browsers are silently dropping the purchase ping before it reaches GA4, or the Shopify figure you're comparing against includes POS, wholesale, or other non-storefront channel sales that never had a browser session for GA4 to see in the first place. Rule these out roughly in that order — start with confirming the tag actually fires, since that's the only one that's a genuine bug rather than an expected structural gap.

Why is my GA4 revenue higher than Shopify's?

This is a different failure mode from the causes above, and it's almost always a duplicate purchase tag: the native Shopify pixel and a separately-built GTM tag both firing purchase on the same order, or two GTM tags both bound to the same checkout-completion trigger. Because the two paths often use different transaction_id formats for the same order, GA4's built-in deduplication doesn't catch it, so every real order gets recorded twice — and revenue, purchase count, and conversion rate typically inflate together in step, which is the pattern that distinguishes this from a timezone or currency mismatch.

What's a normal discrepancy between GA4 and Shopify revenue?

Practitioners commonly cite somewhere around 5-15% as unremarkable for a reasonably well-configured store, though other sources put the acceptable ceiling closer to 20% — there's no single authoritative benchmark, so treat any number here as a rough anchor rather than a hard pass/fail line. Stores with heavy EEA traffic behind a strict consent banner, a meaningful POS or wholesale mix, or a customer base that skews toward ad blockers can reasonably run higher than that range without anything being broken. What matters more than hitting a specific percentage is whether the gap is stable over time — a steady 8% is a different story than a 3% gap that jumped to 18% last week.

Does GA4 track Shopify refunds automatically?

No. Shopify's Web Pixels API has no standard refund event, because refunds happen in the Shopify admin or via the Admin API well after the customer's browser session has ended — there's no page left for a pixel to fire from. GA4's purchase revenue for an order reflects the amount at checkout and doesn't update when that order is later refunded, partially refunded, or cancelled, unless you explicitly build a refund event — typically through a custom pixel combined with an Admin API webhook, or a server-side call to the GA4 Measurement Protocol triggered when a refund is issued. Without that build, always compare GA4 against Shopify's gross sales figure rather than net-of-refunds.

Written by
Ludde Nyström — Founder, NiceLookingData

Analytics consultant turned founder. After years running the same GA4 and GTM audits across client engagements, Ludde built the audit into a product — so the pattern-matching takes a minute, not a meeting. More about Ludde →

Free tool

Run a free GA4 audit.

Connect your Google Analytics 4 property. Our auditor runs 61 checks and gives you an instant health score with a plain-English action plan.

Thanks for reading.