GA4 Not Tracking All Shopify Purchases? How to Find and Recover Missing Transactions
Why GA4 shows fewer purchases than your Shopify orders, how to reconcile them order by order, three ways to close the gap, what it means for Google Ads, and what our app GapFill does and costs.
In one client store where we run the ads, we matched Shopify orders against GA4 purchases one by one and found that about 20% of orders weren’t in GA4 at all. Reviewing the tag setup didn’t close the gap.
When GA4 undercounts purchases, your ads and channels look worse than they are. The bigger problem isn’t the lower number itself. It’s that you can’t tell which channels are being undercounted, or by how much.
This article explains why GA4 misses Shopify purchases, how to check for missing purchases in your own store, and how to close the gap. The second half introduces GapFill: GA4 Server Tracking, the Shopify app we built for this problem. It’s our own product, so keep that in mind. Specs and pricing are as of October 2026.
Why does GA4 miss Shopify purchases?
GA4 misses Shopify purchases because the GA4 purchase event only fires when tracking runs in the buyer’s browser. If it never fires, GA4 never hears about the purchase.
| Cause | What happens | Can a tag fix recover it? |
|---|---|---|
| Off-site / redirect payment gateways (PayPal, Klarna, etc.) | The buyer pays, then closes the tab instead of returning to the thank you page | No |
| Buyer leaves before the thank you page loads | They close the page mid-load or lose connection | No |
| Ad blockers and browser privacy features (Safari ITP, Firefox ETP, Brave) | The tag is blocked from loading or sending | No |
| Agentic and in-app checkouts (e.g., ChatGPT Instant Checkout, TikTok Shop) | No store page is ever opened | No |
| Subscription renewals | Orders are created automatically; the buyer never visits | Up to the store |
| Buyer didn’t consent to analytics | They declined in the cookie banner | Shouldn’t be recovered |
| Tag misconfiguration or duplicate tags | Purchases aren’t sent, or are sent twice | Yes |
The first four have nothing to do with how tracking is set up. They’re purchases where the purchase event never gets a chance to fire in the buyer’s browser.
Subscription renewals are a little different. The buyer didn’t visit your store, so sending them to GA4 adds purchases without visits. Conversion rates and ad results will look higher, so each store has to decide whether to include them.
Fix the bottom row first. It’s a setup error, and only what’s left after you fix it comes from the causes above.
If purchases dropped suddenly after August 26, 2026
If GA4 purchases dropped suddenly after August 26, 2026, suspect the tags on your thank you page first. Shopify has been upgrading the Thank you and Order status pages to checkout extensibility, and the deadline for non-Plus stores was August 26, 2026. The “Additional scripts” field in checkout settings became read-only on August 28, 2025. Script tags added by apps also stopped working on the order status page: on August 28, 2025 for Plus stores, and on August 26, 2026 for everyone else.
If you used to put a GA4 purchase tag in Additional scripts, it may not be sending purchases anymore. Shopify now expects tracking to run through the Google & YouTube app or through custom pixels and app pixels in Settings > Customer events, which subscribe to standard events such as checkout_completed. Stores that track only with the Google & YouTube app weren’t affected by this change.
Other reasons Shopify and GA4 revenue don’t match
Missing purchases aren’t the only reason Shopify and GA4 revenue differ. Even when both tools record the same purchase, they can report different amounts or counts.
| Reason | How the numbers differ | How to check or fix |
|---|---|---|
| Tax and shipping | Whether purchase revenue includes tax or shipping depends on the tag | Compare Shopify amounts and GA4 purchase revenue for a few orders |
| Refunds | Shopify subtracts refunds; GA4 only does if refund events are sent | Compare pre-refund amounts on both sides |
| Time zone | Orders near the date boundary land on different days | Set Shopify and GA4 to the same time zone |
| Payment gateway self-referrals | Buyers returning from an off-site gateway (PayPal, Klarna, etc.) are credited to the gateway | Add a referral exclusion under Configure tag settings > Show all > List unwanted referrals in your GA4 web data stream |
| Attribution rules | GA4 and ad platforms credit the same purchase to different channels | Use each number for its own purpose rather than forcing them to match |
| Redirects dropping UTMs | Ad traffic ends up as “direct” | Check ad landing URLs and any redirects |
How to check for missing purchases in your store
Check for missing transactions by reconciling Shopify order IDs against GA4 transaction IDs, not by comparing totals. Totals can look close even when missing orders and double-counted purchases cancel each other out.
Before you start, find out what your GA4 transaction IDs contain. Depending on the tag, it may be the Shopify order number (like #1001) or the long numeric order ID. Compare a few GA4 transactions with Shopify orders. Also make sure Shopify and GA4 use the same time zone.
- In the Shopify admin, go to Orders, pick a date range, and export the orders as CSV. GA4 needs time to process data, so end the range two or three days ago.
- Clean up the CSV. Orders with multiple line items span multiple rows, so reduce them to one row per order using the “Name” column (the order number). Remove canceled orders (any value in “Canceled at”) and POS and draft orders (check the “Source” column).
- In GA4, open Explore, start a Free form exploration, and add “Transaction ID” as the dimension and “Transactions” and “Purchase revenue” as the metrics, over the same date range. The table shows 10 rows by default, so raise “Show rows” to the maximum (500; split the date range if you have more orders), then click the “Export data” icon in the top right.
- Match the two lists by order number and pull out the orders missing from GA4. XLOOKUP in a spreadsheet is enough. If one side has the ”#” and the other doesn’t, normalize first with a formula like
=SUBSTITUTE(A2,"#",""). - Break the missing orders down by the “Payment Method” and “Source” (sales channel) columns. If they cluster around a particular payment method or channel, that points to the cause.
- In the other direction, any transaction ID with 2 or more transactions in GA4 was counted twice. Suspect a duplicate tag.
If the gap widened suddenly at some point, note whether you added a payment method, changed themes, or swapped apps around that time. Don’t compare the periods before and after such a change as if nothing happened. A jump in the gap may reflect a tracking change, not a real change in sales.
Three ways to close the gap: client-side fixes, server-side GTM, and the Measurement Protocol
There are three ways to close the gap: audit and fix your client-side tracking, move to server-side GTM (sGTM), or send missing orders with the Measurement Protocol. Only the Measurement Protocol covers purchases that never went through a browser.
| Method | What it covers | What it doesn’t | Effort |
|---|---|---|---|
| Client-side tracking audit (Google & YouTube app, Customer events) | Misconfiguration, duplicate tracking | Purchases where the event never fires in the browser | Low |
| Server-side GTM | Some ad-blocker losses, first-party cookies that outlast Safari’s 7-day cap | In a typical setup, purchases with no browser event at all | High. Tracking moves to a server, and it needs ongoing maintenance |
| Send orders with the Measurement Protocol | Orders missing from GA4, including those that never went through a browser | Purchases from buyers who declined consent (which shouldn’t be sent) | Medium. To send every purchase, you’d have to turn off your current purchase tag |
Server-side GTM receives events captured in the browser on your own server first, then forwards them to GA4 and other tools. It still assumes the first signal comes from the browser. In a typical setup, a purchase that never produced a browser event can’t be recovered, because there’s no original data to forward. You can build a setup where server-side GTM receives Shopify order webhooks, but then deduplication and consent handling are up to you.
In Meta Ads, the equivalent way to send conversions from a server is the Conversions API.
What is the Measurement Protocol?
The Measurement Protocol is Google’s way to send events to GA4 directly from a server. Because it can start from order data, it can deliver purchases that never went through a browser. Google says the Measurement Protocol has reached a mature, finalized state and has no plans to deprecate it, and recommends the Data Manager API for new server-to-server integrations.
For payloads, timing rules and validation in detail, see the GA4 Measurement Protocol guide. If you build it yourself, these are the usual sticking points:
- You need to store the buyer’s GA4 client ID (the identifier GA4 assigns to each browser) and session ID at checkout. Google’s documentation asks that the client ID match the one created by the site’s GA4 tag. Without it, the purchase won’t connect to the original visit.
- You can backdate events by up to 72 hours. For attribution to work as expected, though, Google recommends delivering them within 48 hours of the original event.
- The Measurement Protocol returns a 2xx response even for malformed requests, so you need the Measurement Protocol validation server (or DebugView, with debug_mode set) to check that your events are valid.
- To avoid overlapping with late-arriving client-side purchase events, you need to check that GA4 doesn’t already have the order before sending it.
- You need to make sure purchases from buyers who didn’t consent aren’t sent.
What purchases sent later mean for Google Ads
If GA4 is linked to Google Ads, key events sent with the Measurement Protocol are exported to Google Ads too. Google lists requirements, such as sending within 63 days of the most recent online activity and arriving within the attribution window of that key event.
Watch out for double counting here. If both the Google & YouTube app’s purchase conversion action and the GA4-imported purchase are set as primary conversion actions in Google Ads, the purchases you recover will be counted twice, and Smart Bidding will optimize toward inflated numbers. Make one primary and the other secondary before you start. If you send subscription renewals, decide first whether they should count as ad results too.
On the Google Ads side, enhanced conversions are another way to improve conversion tracking. They help match purchases where the tag fired but couldn’t be tied to a click; they can’t recover purchases where it never fired.
Why most stores kept things as they were, even after finding the gap
In our ads and tracking work, clients have asked us many times to “fix the missing purchases.” Few of those projects went anywhere. After hearing the options, most clients decided to leave things as they were, because every option meant giving something up.
- Moving to server-side GTM means rerouting all tracking through a server, which takes real work. The switch can change how GA4 identifies users, and then you can’t compare with past data. In practice, you’re starting your tracking over.
- Sending purchases with the Measurement Protocol while keeping your current purchase tag means the same purchases arrive twice. So you’d have to turn the purchase tag off first.
- If GA4 runs through the Google & YouTube app, which is how most Shopify stores set it up, there’s no setting to turn off just the purchase event. You either have GA4 or you don’t.
Knowing you have a gap, but deciding it isn’t worth rebuilding your tracking to close it, is a perfectly reasonable call. Still, it was frustrating to watch these clients set budgets based on ad results that looked worse than they really were.
We wanted a third option: keep the current tracking as it is, and send only the purchases that slipped through. That’s why we built the Shopify app GapFill. It works alongside your existing tags and recovers only the purchase events GA4 missed, server-side. You don’t have to turn off your purchase tag or start your tracking over.
What GapFill does
GapFill: GA4 Server Tracking is a Shopify app that runs the Measurement Protocol approach alongside your existing tags. We released it on the Shopify App Store in October 2026. See the GapFill page for how it works and what it looks like.
Our Shopify appGapFill: Recover missing GA4 purchase events server-sideWorks alongside your existing tags. Free missing purchases report.See GapFill →- Missing purchases report (free): matches Shopify orders with GA4 purchases by transaction ID and shows how many orders, and how much revenue, are missing from GA4, broken down by channel, source / medium, and payment method. It’s the matching process described above, run continuously by the app.
- Sending to GA4 (Standard plan): orders still missing from GA4 26 hours after they were placed are sent with the Measurement Protocol. GapFill uses the client ID and session ID captured at checkout by its app pixel (a Shopify web pixel extension, listed under Settings > Customer events), so GA4 treats the purchase as part of the original visit by the same person. For orders without those IDs, the source is set from the referral information saved on the order.
- Agentic and in-app checkouts (orders placed inside AI assistants or social apps): these can be sent with a source and medium based on the sales channel.
- Subscription renewals, refunds, and cancellations: send only what you need.
- Works alongside your existing tags: no need to remove the Google & YouTube app or your GA4 tag.
GapFill waits 26 hours so it doesn’t collide with late-arriving client-side purchase events. Before matching, it checks that GA4 has data for that time window. If it can’t verify that, it matches and sends once 50 hours have passed. Orders older than 70 hours are never sent. Orders placed before you installed the app, and orders that passed 70 hours before you approved sending, won’t reach GA4. As Google’s documentation notes, attribution may not work as expected for purchases sent more than 48 hours later.
Pricing
| Plan | Monthly | Includes |
|---|---|---|
| Free | $0 | Missing purchases report |
| Standard | $19 | Missing purchases report, sending to GA4 (up to 200 events a month) |
Beyond 200 events a month on Standard, each event costs $0.05 for 201–1,000, $0.03 for 1,001–5,000, and $0.02 from 5,001. For example, sending 500 events in a month costs $19 + 300 × $0.05 = $34. Every purchase, refund, or cancellation sent counts as one event. There’s a 14-day free trial, and nothing is charged during the trial or before you approve sending. See the billing help page for details.
What to watch when sending purchases to GA4 later
There are four rules for sending purchases to GA4 after the fact: don’t count anything twice, don’t send before approval, respect consent, and don’t compare before and after directly. Here’s how GapFill handles each.
Don’t count anything twice. The GA4 help center says purchases with the same transaction ID from the same user are treated as duplicates for web data, but it doesn’t say whether that also applies to server-sent purchases. So GapFill checks that GA4 doesn’t already have the order before sending. Three to ten days after sending, it checks whether that order’s revenue has doubled in GA4, and if more than 5% of at least 10 orders checked in the last 30 days were duplicated, it stops sending.
Don’t send before approval. Choosing the plan doesn’t start sending. GapFill first builds a list of what it would send, and only starts after someone at the store reviews and approves it.
Respect consent. Orders from buyers who didn’t consent to analytics are not sent. Orders from regions that require consent, such as the EU, are not sent unless consent was confirmed. GapFill also sends the Consent Mode signals (ad_user_data and ad_personalization) with each event.
Don’t compare before and after directly. Purchases from buyers who didn’t consent aren’t sent, so they never reach GA4, and the gap never goes to zero. Also, the day you install GapFill, the way GA4 counts purchases changes. Note that date, so nobody reads a simple before-and-after comparison as “purchases went up.”
How to get started with GapFill
- From the GapFill page, go to the Shopify App Store listing and install the app.
- On the app home, click “Connect with Google,” sign in, and choose the GA4 property you use for tracking.
- Use the missing purchases report to see where, and how much, you’re missing.
- To send purchases, choose the Standard plan, review the list of orders to be sent, and approve it.
The GapFill help pages walk through each step with screenshots.
Sources
- Send Measurement Protocol events to Google Analytics (Google for Developers)
- Measurement Protocol reference (Google for Developers)
- Measurement protocol use cases (Google for Developers)
- [GA4] Minimize duplicate key events with transaction IDs (Google Analytics Help)
- Non-Plus - Upgrading and replacing your Thank you and Order status pages (Shopify Help Center)
- Order status script tags (Shopify.dev)
- Exporting orders (Shopify Help Center)
FAQ
Why don't Shopify and GA4 revenue or purchase counts match?
There are two kinds of reasons. The first is missing purchases: when the purchase event never fires in the buyer's browser, for example because they paid through an off-site gateway and never came back or use an ad blocker, GA4 never sees the purchase. The second is counting differences: Shopify and GA4 can differ on whether tax and shipping are included, whether refunds are subtracted, time zones, and which channel gets the credit. In one of our client stores, about 20% of orders were missing from GA4.
GA4 shows only about half of my Shopify purchases. Is my setup broken?
If roughly half are missing, check your setup first. The purchase tag may not be firing on the thank you page, an old tag may have stopped working after Shopify's August 26, 2026 deadline, or a consent banner may be blocking tracking. Whatever gap remains after fixing the setup is the part a browser tag can't capture. To tell the two apart, match orders one by one and look for patterns in the missing ones.
What is the Measurement Protocol?
It's Google's way to send events to GA4 directly from a server. Because it doesn't go through the buyer's browser, it can deliver purchases the browser tag missed. You can backdate events by up to 72 hours, and Google recommends sending them within 48 hours of the original event for attribution to work as expected.
If I send purchases to GA4 later, won't they be counted twice?
They can be. The GA4 help center says purchases with the same transaction ID from the same user are deduplicated for web data, but it doesn't say whether that applies to server-sent purchases. So you need to check that GA4 doesn't already have the order before sending it. GapFill checks before sending, checks again afterwards, and stops sending if duplicates exceed a set rate.
Do purchases sent later still get the right traffic source?
Yes, as long as you store the buyer's GA4 client ID and session ID at checkout. GapFill stores both and sends them with the purchase, so GA4 treats it as part of the original visit by the same person. For orders without those IDs, GapFill sets the source from the referral information saved on the order.
Does GapFill send purchases from buyers who didn't consent to analytics?
No. Orders from buyers who didn't consent to analytics, based on Shopify's Customer Privacy API, are not sent. Orders from regions that require consent, such as the EU, are not sent unless consent was confirmed.
- GA4 only records a purchase when the purchase event fires in the buyer's browser. Off-site gateways with no return, ad blockers, and agentic or in-app checkouts can't be captured by fixing client-side tracking.
- Non-Plus stores hit their thank you page upgrade deadline on August 26, 2026. Tags added the old way may have stopped there.
- Check for missing transactions by reconciling Shopify order IDs against GA4 transaction IDs, not by comparing totals.
- There are three ways to close the gap: fix client-side tracking, move to server-side GTM, or send orders to GA4 with the Measurement Protocol. Only the third covers purchases that never went through a browser.
- Purchases sent later are also exported to Google Ads. If both the Google & YouTube app's purchase conversion action and the imported GA4 purchase are primary conversion actions, they'll be counted twice.
- GapFill turns the third method into a Shopify app. The report is free; sending requires the Standard plan ($19/month, 200 events included).
Written byRyushi Nagata
CEO, ULTRO Inc. (Tokyo)Shopify Partner. Ryushi handles Shopify store builds, maintenance, advertising and CRM end to end, and has managed more than ¥4 billion in ad spend over his career. He holds Google Ads certifications (Search, Display, Video, Shopping, Apps, Performance Max, Measurement) and the Google Analytics certification.
How many purchases is GA4 missing in your store?
GapFill matches your Shopify orders against GA4 purchases, shows what GA4 missed, and recovers those purchase events server-side. It works alongside your existing tags, and the missing purchases report is free.