GA4 Purchases Don't Match Shopify? Why, and the Fix
Why doesn’t GA4 match Shopify’s orders?
GA4 and Shopify count different things: Shopify records every order, while GA4 records only the purchase events a browser or server sends it. GA4 falls short when shoppers decline analytics cookies, block Google’s tag or a purchase tag fails, and runs over when two tags report one order under different IDs. Compare orders, not sessions, and check transaction IDs.
A gap of some size is normal. Shopify’s own discrepancies page lists the usual causes: Google can count only visitors whose browsers run JavaScript and accept cookies, browser extensions can stop Google Analytics tracking sessions and purchases, and the two tools may report in different time zones.
| Shopify | GA4 | |
|---|---|---|
| What it counts | Every order, from the order record | Purchase events that a tag or server sends |
| Shoppers who decline analytics cookies | Counted | Not counted where consent is required |
| Ad blockers and privacy extensions | No effect | Can block Google’s tag |
| Revenue | Total sales adds taxes, duties, shipping and fees | Whatever the tag sends as the purchase value |
| Refunds | Subtracted on the day they’re processed | Subtracted only if a refund event is sent |
Sources: Shopify’s sales reports and Google’s purchase event reference, checked 24 September 2026.
How does Shopify send purchases to GA4?
Through the Google & YouTube app, if you use Shopify’s own route. You connect a GA4 property in the app (Shopify), and the Google tag it installs sends GA4 your storefront, cart, checkout and purchase events from the shopper’s browser (Google).
Google’s list of the events the app sends (last updated 28 July 2026) runs from page_view and view_item through begin_checkout and add_payment_info to purchase. It has no refund event. The app’s pixel is listed under Settings → Customer events, and Shopify loads pixels on the storefront, checkout, Thank you page and Order status page (pixels overview).
The purchase itself depends on Shopify’s checkout_completed event. It fires once per checkout, usually on the Thank you page, or on the first upsell offer page if you show one. If that page fails to load, the event doesn’t fire at all.
A GA4 tag pasted into Additional scripts no longer reaches the purchase. It stopped when Shopify replaced the old Thank you page, and the deadline for stores not on Plus was 26 August 2026 (see Additional scripts stopped running). A tag in your theme can’t reach it either, because a theme’s layout applies only to non-checkout pages. Tracking on today’s checkout runs through app pixels and custom pixels, compared in app pixels and custom pixels.
What makes GA4 miss purchases?
Anything that stops the purchase event leaving the shopper’s browser: declined consent, a blocked tag, a Thank you page that never loads, or a tag that no longer runs.
- Declined consent. Where you require consent, usually the EEA and the UK, Shopify runs a pixel only when the shopper has given the permissions it needs, and new pixels need analytics and marketing permission by default (Shopify). A shopper who declines is an order in Shopify and nothing in GA4.
- A banner that never tells Shopify. Your consent banner must pass the shopper’s choice to Shopify’s Customer Privacy API. In an August 2026 Community thread, an EU store had page views but no purchases in GA4 after reinstalling the Google & YouTube app. Replies traced it to a banner that never passed consent to Shopify, so the app’s pixel stayed blocked at checkout while a tag in the theme kept sending page views.
- Blocked tags. Browser extensions, ad blockers among them, can stop Google Analytics tracking sessions and purchases, as Shopify’s discrepancies page notes.
- The page never loads. A shopper who pays but never reaches the Thank you page, or whose upsell page fails, fires no
checkout_completed. - An empty transaction ID. GA4 treats every purchase sent with an empty
transaction_idas a copy of the first and drops the rest (Google). - It hasn’t arrived yet. GA4 can take 24–48 hours to process data, and reports can change meanwhile (data freshness).
What makes GA4 count too many?
Two tags sending the same purchase to one GA4 property under different transaction IDs. Google documents deduplication only for purchases that share a transaction ID, and only on web streams.
The second sender is usually one of these: the Google & YouTube app plus Google’s tag or Tag Manager left in the theme, a custom pixel, or another app sending to the same Measurement ID. Google’s guide to the app tells you to check for duplicate tags when you have conversions in the app and in the storefront or a custom pixel (Google), and Shopify’s migration guide names tracking the same event more than once as a common problem. In a 2023 Community thread, merchants running GA4 through both Tag Manager and Shopify’s Google channel reported doubled purchases and revenue, and one fixed it by pausing the Tag Manager copy.
Two patterns give it away:
- One order, two transaction IDs. For example, one tag sends the order ID and another the order number, so GA4 sees two sales.
- Doubled page views while revenue looks right. Two senders that use the same transaction ID are deduplicated on the purchase, but page views and add-to-carts have no ID to match, so they double.
The same problem on Meta and TikTok is covered in why Meta counts purchases twice.
Can the Measurement Protocol fill the gap?
Partly. Google’s Measurement Protocol lets a server send GA4 events such as the purchase, so an order can reach GA4 when the browser tag didn’t, but Google built it to add to the Google tag, not replace it.
What Google’s documentation says (checked 24 September 2026):
- The Measurement Protocol is meant to augment tag-based collection, and sending events with it alone may give only partial reporting.
- For a web stream, the
client_idshould match the ID the Google tag set on your site (sending events). - A server event shares the visit’s source, medium and campaign only if it carries that visit’s
session_idand arrives within 24 hours of the session starting (use cases). - Events can be backdated by up to 72 hours.
- The endpoint returns no HTTP errors, even for malformed events, and Google’s validation server doesn’t check the API secret (validating events). A wrong secret fails silently.
So a server purchase helps with blocked tags and Thank you pages that never load, and it can send refunds, which aren’t on Google’s list for the Google & YouTube app. It can’t help with consent: moving a declined shopper’s purchase to a server doesn’t make it consented. It also needs a client ID and session ID from the shopper’s browser to land in the right visit, which leads to the next problem. For how server events work on other platforms, see server-side tracking on Shopify.
Why does GA4 show (not set) after server-side tracking?
Because the server sent events that GA4 couldn’t tie to a visit. GA4 takes a Measurement Protocol event’s source and campaign from what the Google tag collected in the same session, and its location from the same visitor’s tagged events unless the server sends one. With no matching client ID and session ID, those columns read (not set).
Google’s documentation (checked 24 September 2026) gives the rules:
- For Measurement Protocol events reported as (not set) / (not set), Google’s fix is to send the
session_idwith a valid value from the client-side event (Google); the 24-hour limit above still applies. - GA4 joins the most recent location and device information from tagging to Measurement Protocol events with the same
client_id(changelog). A server can send location itself inuser_locationorip_override; without either, GA4 takes it only from tagging (reference).
So the usual cause is a visitor whose Google tag never ran, typically because a blocker stopped it: GA4 has nothing to join, and if the server sends a client ID it made up, GA4 records a new user with no source or location. The fixes follow from Google’s rules: send the client ID and session ID the Google tag set, send promptly, and where consent allows, send the shopper’s location in user_location or ip_override. Note the date you changed your setup, and leave the days around it out of before-and-after comparisons.
How do I check GA4 is receiving purchases?
Place a real order and watch it arrive in GA4’s Realtime report, then compare a whole day of Shopify orders with GA4’s purchases, transaction ID by transaction ID.
- Place an order on your storefront with a real payment method.
- In GA4, open the Realtime report. The purchase usually appears within a few minutes.
- Two days later, once processing has settled, open Explore and build a free-form table with the Transaction ID dimension and the Ecommerce purchases metric, which counts
purchaseevents only (Google). - Set the same date in Shopify’s order list, keep to orders from your online store, and check both tools use the same time zone.
- Match the lists.
| What you see | Likely cause |
|---|---|
| An order missing from GA4 | Declined consent, a blocked tag, or a Thank you page that never loaded |
| Missing orders cluster in the EEA or UK | A consent banner that doesn’t pass the choice to Shopify |
| Two transaction IDs for one order | Two senders using different ID formats |
| Far fewer purchases than orders, under one repeated or empty ID | An empty or reused transaction ID, which GA4 collapses into one purchase |
| Page views doubled, revenue about right | A second sender on the same property |
Where does cPixel fit?
Sending the purchase from Shopify’s order record helps when the browser purchase never fires. Start with the Google & YouTube app, which is enough for many stores, and remember that no tool should fill a gap that comes from declined consent.
cPixel, which we build, sends GA4 purchases and refunds from its servers through the Measurement Protocol. It builds them from Shopify’s order, with the order as the transaction ID, so GA4’s own deduplication applies. Every other GA4 event goes from the shopper’s browser through cPixel’s pixel, and if one never leaves the device, cPixel sends that single event from its servers instead and marks it in its Live view. cPixel doesn’t send GA4 the shopper’s IP address or location, so a recovered event gets its location only from that visitor’s earlier hits, and reads (not set) when there were none.
The server purchase carries the client ID and session ID that cPixel keeps for the shopper from the storefront into checkout, which is what Google needs to credit the purchase to the visit that led to it. Google keeps that credit only for events sent within 24 hours of the session starting, so purchases sent later, for example with When the order ships in cPixel’s Settings, can lose their campaign. A checkout with no browser session isn’t sent: Live shows Not enough data to build the payload for this destination. A shopper who declines analytics cookies isn’t sent to GA4 either.
Setup needs your Measurement ID and a Measurement Protocol API secret. Without the secret, GA4 receives no purchases from cPixel, and because GA4 never reports a wrong secret, confirm with a real order: connect GA4 to cPixel. Send each GA4 property from one tool only. If the Google & YouTube app also sends to it, page views and other browser events are counted twice. More about cPixel, which sends Shopify purchases to seven ad platforms.
Frequently asked questions
Why is GA4 revenue lower than Shopify’s?
Usually because some purchases never reached GA4, and because the two totals are built differently. Google asks for a purchase value that covers the items without shipping or tax, while Shopify’s Total sales adds taxes, duties, shipping and fees. Check what your tag sends as the value, then compare against the Shopify figure built the same way. Refunds pull the other way: Shopify subtracts them, and GA4 does only when a refund event is sent.
Did Shopify’s September 2026 sessions change affect GA4?
No. Between 21 and 23 September 2026, Shopify changed how its own reports count sessions: a session now ends after 30 minutes of inactivity instead of at midnight UTC, and identified bot sessions are filtered out by default (Shopify). Shopify says orders, sales and customer counts are unaffected. GA4 counts its own sessions, which by default also end after 30 minutes of inactivity (Google). If Shopify’s sessions fell from 21 September while GA4’s didn’t, that change is the likely reason.
Does GA4 exclude bots?
Known ones, automatically. GA4 excludes traffic from known bots and spiders using Google’s research and the IAB’s International Spiders and Bots List, and you can’t turn that off or see how much was excluded (Google). A list can’t catch bots that pass themselves off as ordinary browsers, but they rarely buy, so they inflate sessions rather than purchases. What they look like on a Shopify store: bot traffic on Shopify.