GA4 revenue higher than Shopify: which causes are normal and which are faults.
- “why is GA4 revenue higher than Shopify”
- “GA4 shows more revenue than Shopify”
- “GA4 revenue double Shopify”
- “GA4 purchases more than Shopify orders”
- “GA4 duplicate purchase events on Shopify”
Baris Asa, tracking consultant, London · Last checked: November 2026
When GA4 revenue is higher than Shopify, count GA4 purchases against Shopify orders for the same week. More purchases than orders means GA4 is counting orders that don’t exist, usually because the purchase event fires twice. That is a fault. Matching counts and a gap close to your refund rate is normal: Shopify takes refunds off its sales, and GA4 doesn’t.Use a closed week: a full week that ended at least two days ago. Take test and deleted orders out of both sides; Shopify already leaves them out of its sales reports. A handful of extra purchases can be time zones. More than that is the fault, and the fix is further down.
Why is GA4 revenue higher than Shopify?
Start with the direction. GA4 normally reads below Shopify. Some visitors refuse cookies or block scripts, and Shopify’s help says Google Analytics can’t record them. Point-of-sale orders, draft orders marked as paid in the admin, and subscription renewals never pass through a browser either.
So GA4 above Shopify means something is adding revenue on the GA4 side. Refunds and test orders lift GA4 against the Shopify figure. Dates and currency move it either way. None of those need a fix, only a fair comparison. Faults are different. GA4 records purchases that are not orders, or amounts that are not what was paid, and those need fixing at the tag.
| What you see | Likely cause | On file |
|---|---|---|
| GA4 ahead by about your refund rate | Refunds not sent to GA4: normal | None |
| More GA4 purchases than orders | Purchase fires twice | F-101 |
| Counts match, revenue exactly 100x | Amount sent in pence | F-302 |
| Counts match, revenue up by tax and shipping | Tag sends the order total | F-302 |
| Too high on overseas orders only | Wrong currency label | F-302 |
| Meta also above the store | Pixel and server events not deduplicated | F-102 |
Which causes are normal?
1. You are comparing different numbers
Google’s developer reference for the purchase event says value (the amount sent with the purchase) should be price times quantity for the items. Tax and shipping go in their own parameters.
Shopify’s sales reports have three figures. Gross sales is price times quantity. Net sales is gross sales minus discounts and sales reversals (refunds, cancellations, edits). Total sales adds tax, duties, shipping and fees.
A tag built to Google’s guidance matches Shopify’s net sales with the reversals added back. Many tags send the order total instead, tax and shipping included, and then total sales is the match. To see which yours does, place one order and read the value GA4 received for it. On the GA4 side, read Purchase revenue. Total revenue adds ad revenue on top.
2. Refunds come off Shopify, not GA4
Shopify records a sale on the order date. It records a reversal as a negative amount on the day it is processed. GA4 only subtracts a refund when it receives a refund event for that order. Its Purchase revenue is net of refunds it has been told about. Gross purchase revenue is not.
If nothing sends GA4 refunds, GA4 runs ahead of Shopify’s net sales by roughly your refund and cancellation rate. It’s the normal gap I see most, and it widens in the weeks after a sale.
3. Test orders count in GA4
Shopify’s sales reports leave out test and deleted orders, including orders placed while Shopify Payments was in test mode. GA4 counts any purchase the tag sent. A launch week with a run of staff test orders shows up as GA4 purchases the store never took. Take their order numbers out of GA4 before you compare counts.
4. Days and time zones differ
GA4 dates a purchase by when the event fired, in the property’s time zone. Shopify dates it by the order date, in the store’s time zone. If the two differ, late-evening orders land on different days, and a week’s counts can be a few orders apart. Compare closed weeks, not single days. GA4 processing can take 24 to 48 hours, which is why the week needs two days to settle.
5. Currency is converted differently
GA4 converts each order into the property’s currency at the previous day’s exchange rate. Shopify reports in the store currency. On overseas orders the two drift apart slightly, in either direction. That is not a fault, as long as the currency code sent with each order is right.
How do I compare GA4 and Shopify like for like?
Put GA4 purchase revenue next to Shopify net sales first, then add refunds back, then count orders. Four checks, in order, on one closed week:
- Same report. In Shopify, open Analytics, Reports, set the Category filter to Sales, and open Total sales over time. Note net sales, sales reversals and orders. If you also sell in person, use Total sales by sales channel and read the Online Store row. In GA4, open Reports, Monetization, Transactions. If it’s not there, someone with edit access can add it from the report Library. What it shows you: the two numbers most people compare first.
- Refunds out of the way. Add Shopify’s sales reversals for the week back to its net sales. What it shows you: the gap without refunds, which GA4 usually never hears about.
- Count orders, not money. Compare GA4’s Ecommerce purchases with Shopify’s orders, test orders out of both. What it shows you: whether GA4 has extra purchases (fires twice) or the right purchases at the wrong amount (built wrongly).
- Order by order. In the Transactions report, sort by Transaction ID (the order number sent with the purchase). Look for
(not set), IDs that don’t look like your order numbers, and any order with two purchases. What it shows you: the extra purchases themselves.
| CHECK | GA4 | SHOPIFY | GAP |
|---|---|---|---|
| 1. Purchase revenue vs net sales | £44,100 | £38,400 | GA4 +15% |
| 2. Reversals added back | £44,100 | £40,000 | GA4 +10% |
| 3. Purchases vs orders | 441 | 400 | +41 |
4. (not set) removed | £40,000 | £40,000 | none |
At check 1, GA4 is 15% ahead. Adding back £1,600 of refunds explains 5 points, and that part is normal. The count then shows 41 more purchases in GA4 than orders in the store, and the Transactions report has 41 purchases with no transaction ID. That is the purchase firing twice, the second copy sent without an ID. Take those out and the two agree.
If check 3 shows extra purchases and you don’t run the tags yourself, stop there. Send the week’s figures to whoever does, or to me (details at the end).
Which gaps are faults?
A fault leaves a shape the normal causes don’t. It usually starts on a date: an app install, a new pixel, a tag added in GTM. Each is on file with the test that confirms it.
F-101 · The purchase fires twice: how to fix it
The purchase fires twice because two things send it for one order, and their transaction_ids don’t match, so GA4 keeps both. In plain terms: two of your apps or tags both report the sale. The extra can be a few per cent of orders or a full double, depending on how many orders the second sender catches.
To fix it:
- Confirm it. Place a test order with GA4 DebugView (a live view of one test session’s events) or GTM Preview open. Count the purchase events and note what sent each one.
- List every sender. The Google & YouTube app, custom pixels (Settings, Customer events), GTM, any app with its own tracking, and any Create event rule in GA4 Admin, Events, that outputs a second
purchase. Note thetransaction_ideach one sends. - Keep one. Remove the purchase from every other sender.
- Send a stable, unique
transaction_idon the one that stays. Never an empty string: GA4 then treats every empty-ID purchase as one order, and an overcount becomes an undercount.
Fixed at the source, the gap closes from that day. Revenue already inflated in GA4 stays in its reports. Not sure which apps send a purchase? Ask whoever installed them, or send me the week’s figures. The sender-by-sender hunt, on any platform, is in GA4 purchase event fires twice.
Shape: GA4 purchases run above Shopify’s orders, test orders excluded, by a steady share from a date you can name.
Why two senders. On Shopify, checkout_completed, the event most tracking hangs on, fires once per checkout: on the Thank you page, or on the first upsell page if the store runs post-purchase offers. So the double most often comes from two senders, usually the Google & YouTube app plus a GA4 tag in a custom pixel or GTM (Google Tag Manager). Inside GTM, look for a second trigger on the purchase tag, or the container loaded twice.
Why GA4 keeps it. Google’s help says GA4 deduplicates purchases with the same transaction_id on web streams, with no published time window. So two senders with the same order number don’t inflate GA4. In the accounts I’ve checked, the copy that gets through is the one with no ID or a different one. A reload of the order page that resends the same ID is dropped by GA4, though Meta and Google Ads have their own rules.
| TIME | EVENT | TRANSACTION_ID | VALUE |
|---|---|---|---|
| 12:40:31 | begin_checkout | ||
| 12:41:07 | purchase | T-88412 | £96.00 |
| 12:41:09 | purchase | (not sent) | £96.00 |
One order, two purchases two seconds apart. The second has no transaction_id parameter, and it shows in the Transactions report as (not set). Full write-up, with the test that separates each sender: F-101 .
F-302 · Counts match, revenue doesn’t: the amount is built wrongly
Shape: GA4 purchases match Shopify’s orders, but revenue is too high by a fixed ratio or a fixed part of each order.
The tag sends the right purchase with the wrong amount. Three versions turn up:
- Exactly 100 times too high. The amount went out in pence: 9600 instead of 96.00. It comes from a custom data layer (the page code that hands order details to the tags) reading a raw money field without formatting it.
- Too high by tax and shipping. The value is the order total and you are comparing it with net sales. Compare with total sales, or change the tag to send tax and shipping in their own parameters.
- Too high on overseas orders only. A store selling in several currencies sends the amount the customer paid, say 115 euros, labelled as GBP. GA4 reports £115. Send the currency the order was charged in, and GA4 converts it.
The test is the same for all three. Pick five orders, read the value and currency GA4 received for each, and set them next to the order in Shopify. Full write-up: F-302 .
F-102 · Meta is above the store too
If Meta Ads also reports more purchases than the store took, that is a separate fault with the same look. The Meta Pixel and the Conversions API both send the purchase. Meta drops the copy when both share the same event name and event_id, its recommended method. Fixing GA4 doesn’t fix Meta. Full write-up: F-102 .
Which number should I trust?
Shopify, for revenue. It is the record of what was charged and what was refunded. GA4 is for how people found and moved through the store. Its revenue is fine once it sits a little below Shopify, or above it by your refund rate, week after week.
Comparing GA4 with Google Ads rather than Shopify is a different job: GA4 and Google Ads numbers don’t match. Google Ads conversion value against Shopify’s sales has its own checks: Google Ads conversion value doesn’t match actual revenue. If the checks point at more than one fault, or none, that is a reconciliation: order by order, every remaining gap named. Email [email protected] with one closed week of GA4 purchases and purchase revenue, next to Shopify’s orders and net sales. I’ll say whether it’s a fault, a reconciliation, or nothing to fix.
Common questions
How big a gap between GA4 and Shopify revenue is normal?
GA4 normally sits below Shopify, because buyers who refuse cookies or block scripts never reach it. Above Shopify by about your refund rate is normal. Three things are faults: more GA4 purchases than orders by more than a handful, once test and deleted orders are out; revenue at an exact multiple such as 100x; or a jump from a date you can name.
Which Shopify number should I compare with GA4 purchase revenue?
Start with GA4 purchase revenue against Shopify net sales, Online Store only, then add Shopify’s sales reversals back. Google’s guidance is that the purchase value excludes tax and shipping. If your tag sends the order total with tax and shipping, compare with total sales instead.
Is a purchase firing twice the reason GA4 is above Shopify?
It is when GA4 shows more purchases than Shopify shows orders for the same closed week. Matching counts point elsewhere: refunds, tax and shipping, or currency. The sender-by-sender fix is in GA4 purchase event fires twice.
Does GA4 remove duplicate purchases?
On web streams, yes. GA4 deduplicates purchase events that share the same transaction_id, with no published time window. Not on app streams. An empty string makes GA4 treat every empty-ID purchase as one, so you undercount.
Sources
Read on 1 November 2026:
- Google Analytics developer reference, recommended events: purchase and refund (
valueis price times quantity, no shipping or tax;currencyrequired withvalue;transaction_id) - Google Analytics Help, minimise duplicate key events with transaction IDs (web streams only, no time window, empty string), Transactions report (Transaction ID, ecommerce purchases, purchase revenue, Library), currency reference (prior day’s exchange rate, property currency), dimensions and metrics (purchase revenue net of refunds, gross purchase revenue, total revenue) and data freshness (24 to 48 hours)
- Shopify Help Center, sales reports (gross, net and total sales; sales reversals dated when processed; test and deleted orders left out; Total sales over time), sales discrepancies, discrepancies with other analytics (cookies, blocking extensions, time zones) and test orders (left out of reports)
- Shopify developer docs, checkout_completed (once per checkout, Thank you page or first upsell page)
- Meta for Developers, deduplicate Pixel and server events (event name and event ID)