GA4 and Shopify Revenue Don't Match: Every Cause, Ranked by How Often It's the Culprit
Shopify says one revenue number, GA4 says another. Here is every cause of the gap, ranked by how often we actually find it, and the variance benchmark we hold clients to.
Priya runs Meadowlane Ceramics, a handmade homeware brand on Shopify doing about $1.1M a year. In June, Shopify reported $84,300 in sales. GA4 reported $71,900. She found the gap on a Tuesday night while building a board deck, and by Wednesday morning she’d convinced herself her agency had broken the tracking.
They hadn’t. Nothing was broken at all, in fact. The 14.7% gap was, almost line for line, the sum of six ordinary causes that show up on nearly every store we audit.
A freelance analyst we hopped on a discovery call with last month put it bluntly: “Few of my clients have both connected and the numbers almost never match.” He’s right, and the interesting part isn’t that the numbers differ. It’s that the causes are so predictable you can rank them.
So that’s what this post is. Every cause we find in the wild, ordered by how often it turns out to be the main offender, with rough size estimates so you can do the reconciliation math on your own store.
Two systems that were never counting the same thing
Shopify counts orders. The moment checkout completes, the order exists in the admin, whether the customer’s browser fired a single tracking event or not. Refund it later and Shopify’s reports adjust.
GA4 counts purchase events. A purchase event only exists if a browser (or a server) successfully sent it. No event, no revenue, as far as GA4 is concerned.
That single difference in worldview explains most of what follows. One system is a ledger, the other is a telescope. The ledger records everything by definition. The telescope only sees what light reaches it, and plenty of things block the light.
Once Priya’s team internalized that framing, the panic dropped. The question stopped being “which number is wrong” and became “what’s blocking the telescope, and how much.”
Consent banners and ad blockers, the silent 10 to 15 percent
This is the number one culprit, and it isn’t close.
If you sell into the EU, UK, or any region where your consent banner defaults analytics to off, every visitor who declines (or just ignores the banner) completes their purchase invisibly. Shopify records the order. GA4 records nothing, or a modeled ghost of it if you have consent mode configured. Ad blockers and Safari’s tracking prevention pile on top of that, killing the GA4 tag before it loads for a meaningful slice of desktop and nearly all privacy-browser traffic.
On stores with EU traffic we routinely attribute 8 to 12 points of the gap to consent alone. Add blockers and you’re at 10 to 15. And not by a little on some stores; one supplements brand we audited was losing 19% of purchase events this way because their banner defaulted everything off globally, not just where the law required it.
You can claw some of this back with server-side tagging, but you can’t get to zero. Declined consent means declined, full stop.
The thank-you page is doing more work than it can handle
The classic setup fires the GA4 purchase event from the order status page. Which works, right up until the customer doesn’t load that page.
They close the tab the second the “order confirmed” email lands. They pay with a redirect method like iDEAL or Klarna and the return hop fails. They’re on a flaky mobile connection in a checkout flow that took ninety seconds too long. Each of those is a Shopify order with no GA4 purchase.
This one’s worth fixing properly because it’s actually fixable. Shopify’s web pixels API fires the checkout_completed event from a sandboxed pixel rather than depending on a page render, and the native Google & YouTube channel integration uses it under the hood. Stores still running a legacy thank-you-page script from 2022 are usually carrying 3 to 6 points of avoidable gap. Migrating is an afternoon of work.
Refunds, cancellations, and orders GA4 never sees adjusted
Shopify’s sales reports are net of what happens after the order. GA4’s purchase revenue, by default, is frozen at the moment of the event.
Customer orders $180 of ceramics, returns the vase, gets $60 back. Shopify now shows $120 for that order. GA4 still shows $180 forever, unless someone is sending refund events, and in our experience almost nobody is. Cancelled orders, fraud declines that happen post-capture, and edited orders all behave the same way.
Here’s the twist though. This one inflates GA4 relative to Shopify, so it partially masks the consent losses pushing the other way. A store with heavy returns and heavy EU traffic can show a deceptively small net gap made of two large opposing errors. Priya’s store had exactly this: a 14.7% net gap that was really a 19% undercount and a 4% overcount shaking hands.
Attribution models quietly reshuffle the credit
This one doesn’t change the revenue total, but it changes every per-channel number, and per-channel is where people actually make decisions.
Shopify’s channel reporting leans last-click within its own tracking window. GA4 defaults to data-driven attribution, which fractionally redistributes credit across touchpoints, with its own lookback windows on top. So when your marketing lead says “GA4 shows email drove $12k but Shopify says $19k,” nothing is broken. The two systems are answering different questions about the same orders.
We flag it here because a third of the “revenue mismatch” tickets we get are actually attribution mismatch tickets wearing a disguise. Check whether the total gap or the channel-level gap is what’s bothering you before you spend a single hour debugging tags.
Taxes, shipping, currency, and the time zone trap
The boring settings, and honestly the fastest wins in the whole list.
GA4’s value parameter may or may not include tax and shipping depending on who wired it up, while the Shopify report you’re comparing against has its own definition. A store charging 20% VAT that includes tax in one system and not the other has a built-in 20% gap that took a checkbox to create. Multi-currency stores add conversion-rate drift on top, since GA4 converts at its own daily rate, not the rate Shopify captured at order time.
Then there’s the time zone trap, our favorite dumb one. Shopify store set to America/New_York, GA4 property on UTC, and every month-end comparison is off by a few hours of orders. It made one client’s “GA4 is missing a day of revenue” mystery evaporate in a fifteen-minute call. Marco emailed, we checked the property settings, that was the whole fix.
Pull these levers first, before anything that involves a developer. They cost nothing to check, take an hour to fix, and they’re the difference between comparing apples to apples and comparing apples to a currency-adjusted, tax-inclusive fruit basket that somebody configured differently three years ago and forgot about.
Bots, test orders, and the long tail
Everything else lives here, and it’s rarely more than a point or two.
Draft orders and wholesale orders that skip online checkout show up in some Shopify reports and never fire pixels. Staff test orders do the opposite when someone forgets to filter internal traffic in GA4. Aggressive bot filtering on GA4’s side occasionally eats real purchases from data-center IP ranges, corporate VPNs mostly. Duplicate purchase events, from a customer refreshing an old-style thank-you page, nudge GA4 upward if there’s no transaction deduplication.
Worth an hour of checking. Not worth a week, and definitely not worth the custom deduplication project one client’s previous agency had quoted at eleven grand.
How close is close enough
Here’s the benchmark we hold clients to, and it’s the most useful paragraph in this post: a well-configured store should see GA4 within 5 to 10 percent of Shopify, stores with heavy EU traffic within 10 to 15. Tighter than 5% is possible with server-side tagging and refund events, but the effort curve goes vertical.
The real health metric isn’t the size of the gap. It’s the stability. A steady 11% variance is a known optical property of your telescope; you can factor it into every decision. A variance that jumps from 11% to 23% in a week is a tracking incident, and that’s the alarm worth wiring up.
One number, one owner, checked monthly. That’s the whole monitoring program.
What we keep telling clients
Pick your source of truth and say it out loud. For money, it’s Shopify, because it’s the ledger that matches your bank deposits. GA4 is for behavior, channels and funnels, and it’s allowed to disagree with the ledger the way a telescope is allowed to miss things a ledger records.
Spend your fixing budget in frequency order. Consent setup and pixel migration first, the settings sweep second, refund events third if you’ve got the appetite. Skip straight to BigQuery exports or server-side infrastructure only when the cheap fixes are done and the remaining gap still costs you real decisions, which for most stores under $5M it doesn’t.
And stop re-litigating the gap every month. Document the expected variance, put a threshold alert on it, and move the meeting on. The stores that get this right spend fifteen minutes a month on reconciliation. The ones that don’t spend fifteen hours and end the month trusting neither number, which is the worst possible outcome.
Priya’s ending is the one we’d wish on everyone. We migrated her purchase event to the web pixel, fixed a tax-inclusion mismatch, and documented an expected variance of 9 to 12 percent. The gap didn’t disappear. It became boring. Her July board deck had one footnote under the revenue chart and nobody asked about tracking at all.
Questions we get every week
Should I just use the Google & YouTube channel app instead of custom GA4 tags?
For most merchants, yes. The native integration fires purchases from the checkout pixel rather than the thank-you page, handles the transaction plumbing correctly, and survives checkout updates. Custom setups only earn their keep when you need enhanced ecommerce events the app doesn’t cover.
Will server-side tracking make GA4 match Shopify exactly?
No. It recovers events lost to ad blockers and some browser restrictions, typically tightening the gap by a few points. Consent declines, refunds, and attribution differences remain, so plan for closer, never identical.
Which number do I report to my board or investors?
Shopify, always, because it reconciles to payouts and accounting. Use GA4 for channel efficiency and funnel behavior, and if both numbers appear on one slide, footnote the expected variance so nobody discovers it live in the meeting.
Is a 20 percent gap ever normal?
It can be, on stores with majority EU traffic, strict consent defaults and no server-side recovery. But treat 20% as a prompt for the settings sweep in this post before you accept it, because more often than not a third of it is a fixable configuration issue.
Tired of explaining the gap to your CFO every month? Talk to us about a two-week tracking audit and we’ll reconcile Shopify, GA4 and your ad platforms down to a stable variance you can defend.