Help

Why GA4 purchases don't match Shopify orders

The two numbers are counted by different systems at different moments, so they are rarely identical. Some of the difference is expected. This page lists the causes CommerceTrace allows for, and what it does when it meets each one.

Shopify records an order when checkout completes. GA4 records a purchase only if a tag in the shopper's browser (or a server) sends one to Google, and Google then has to process it. CommerceTrace reads both records for the same period and compares them order by order. See what each verdict means.

1. GA4 has not finished processing

An order placed a few minutes ago may not be in GA4 yet. CommerceTrace treats an order younger than 6 hours as inconclusive, not missing. After GA4's own limit for late events (more than two calendar days, plus today), a purchase that is still absent can no longer arrive. The 6-hour figure is a deliberately cautious choice by CommerceTrace; Google does not publish a fixed processing time.

2. GA4 counts the item subtotal, not the order total

GA4's purchase value is the price of the items after discounts. It excludes tax and shipping. CommerceTrace compares GA4's value with the order's discounted item subtotal. If GA4 holds the order total instead, it says so by name, because that is a common and fixable setting.

3. The currency differs

CommerceTrace compares in the currency the shopper was charged (the presentment currency), not the store's home currency. Separately, a GA4 property has a reporting currency, and the Data API returns revenue converted into it. When that currency differs from the one the store charges in, per-order values cannot be checked against Shopify from that report. CommerceTrace states this as a property setting, not a tracking fault. When value, tax and shipping all differ by the same ratio, it marks the order inconclusive with that explanation rather than as a wrong value.

4. Orders that never went through the online checkout

A point-of-sale sale, a sale from the Shopify iPhone or Android app, and a subscription renewal have no online checkout, so no browser tag could have sent a purchase. When GA4 has no purchase for one, CommerceTrace sets it aside with that reason instead of calling it missing. If GA4 does have a purchase for it (sent from a server, for example), it is compared like any other order. A draft order paid through an invoice link does go through the online checkout, so it stays in the comparison.

On a live store, Shopify test orders are left out of the comparison too, and shown as not counted. On a development store they are included, because they are all it has.

5. Refunds and edits after the purchase

GA4 keeps the value recorded at checkout. A later refund, return or edit does not change it. CommerceTrace compares GA4 with the order's original subtotal and notes that the order changed afterwards.

6. The transaction ID is written differently

Shopify shows an order as #1001, but GA4 may hold 1001, the order ID or the confirmation number. CommerceTrace accepts the order name with or without the #, the order ID and the confirmation number. A GA4 purchase with no transaction ID at all cannot be attached to an order, so the order is marked inconclusive with that reason.

7. A repeated hit looks like a duplicate

The browser can resend a hit when delivery is uncertain. CommerceTrace counts that as one purchase. It reports a duplicate only when two separate hits are observed. A GA4 report row with an event count above one, or two rows for one ID, does not prove two tag fires, so it is shown as an unverified duplicate signal and graded inconclusive.

8. GA4's own report limits

GA4 can fold transaction IDs into an (other) row, withhold rows under thresholding, or sample a report. In each case an order missing from the report is not proof it is missing from GA4, so CommerceTrace marks it inconclusive and names the limit. The false-alarms guide covers these in detail.

9. Another store sends to the same GA4 property

A staging or second Shopify store that shares your property records purchases that have no order here. CommerceTrace reads the host each purchase was recorded on. When it is another *.myshopify.com store, the purchase is set aside and the other host is named, rather than counted as a problem.

What is left

An order that has no GA4 purchase under any of its IDs, is old enough for GA4 to have processed it, and is not one of the cases above, is reported as missing. CommerceTrace shows the order, its value and the evidence. It does not say why the purchase never reached GA4: a tag that did not fire, a shopper who declined analytics consent and a blocked request all look the same from the order's side. When there are enough orders it also shows whether the missing ones share a payment method or sales channel, which is where to start testing.

What each verdict means · What CommerceTrace can and can't see