Skip to content

Problem

GA4 revenue does not match Shopify: how to fix it

Some of the gap between these two numbers is a defect and some of it is arithmetic. Shopify reports orders as they are recorded in the store, including channels that never touch a browser, while GA4 reports purchase events collected from a page in a session that may or may not have been measured. Your job is to size each part of the gap, fix the collection failures, and then agree which number the business reports.

By CartKernel · Last reviewed 2026-09-07

Does this look familiar?

  • The analytics property consistently reports a smaller revenue figure than the store admin
  • Order counts are close but revenue totals are noticeably apart
  • The difference is larger on some days than others with no obvious pattern
  • Revenue figures diverge more sharply after a checkout, theme or consent banner change
  • Some orders appear twice in the analytics ecommerce reports
  • Totals agree in one report and disagree in an exploration built over the same dates

Causes, ranked

Why it happens, most common first

Check them in this order. The first two account for most cases we open.

  • most common

    Orders arrive through routes that never send a purchase event

    Point of sale, draft orders, phone orders, subscription renewals, wholesale channels and orders created by apps all appear in the store admin without a browser session behind them. None of them produce a web purchase event, so the analytics total is structurally lower before any tag ever fails.

  • most common

    The two systems count different components of an order

    Shipping, taxes, duties, gift cards, discounts and tips can be included or excluded on either side depending on how the purchase value is assembled. A store reporting gross sales against an analytics value built from subtotal will never reconcile, and the difference scales with order volume.

  • common

    Refunds and cancellations are handled differently

    Store reports usually net refunds against the original order or the refund date, while the analytics property only reflects a refund if a refund event is sent. Most implementations never send one, so the analytics figure stays at gross while the store figure moves.

  • common

    Consent choices and blocking prevent collection

    Visitors who decline analytics storage, use blocking extensions or leave before the tag loads produce an order the store records and the property does not. The share varies by market and device, and it rises when a consent banner is redesigned to be more prominent.

  • common

    Currency and time zone settings differ

    The property converts event values into its own reporting currency using an exchange rate, and it groups days by the property time zone rather than the store's. A store selling in several currencies, or set to a different time zone, will see daily totals that never line up even when every order is captured.

  • occasional

    Transaction identifiers are missing or reused

    The transaction identifier is how a purchase is recognised as one order. When it is absent, blank or repeated across orders, events can be counted more than once or dropped. This produces a gap in either direction and is the usual explanation for orders appearing twice.

  • occasional

    Reports are being compared that were never comparable

    Sampling in explorations, data thresholding when identity signals are enabled, and different report definitions all produce different totals from the same underlying data. Comparing a thresholded exploration with a store finance report guarantees a mismatch.

The fix

In this order

Each step is something you can do today. Do them in sequence; skipping ahead is how a review fails twice.

Prevent it next time

  • Name one system as the source of truth for revenue and use the other for behaviour and channels
  • Re-run the reconciliation after every checkout, theme, app or consent tool change
  • Keep the property time zone and currency aligned with the store's reporting settings
  • Include a purchase event check in the release test for anything that touches checkout
  1. Pick one week and one definition to reconcile

    Choose a completed week, decide whether you are comparing gross sales, net sales or subtotal, and export the store orders for those dates with their channel and their totals. Do the same in the analytics property using a standard report rather than an exploration.

  2. Remove the orders that could never be measured

    Filter out point of sale, draft, wholesale, subscription renewal and app created orders from the store export. What remains is the population the web tag could have seen. Most of the headline gap usually disappears at this step.

  3. Match the value definitions on both sides

    Confirm what the purchase value contains: whether shipping and tax are included, whether discounts are already applied, and whether gift card redemptions reduce it. Change one side so both describe the same thing, and document which definition you chose.

  4. Align time zone and currency

    Set the property time zone to the store's reporting time zone if they differ, and note that changing it does not restate history. For multi currency stores, accept that converted totals will differ slightly from store figures and reconcile in one currency only.

  5. Check the purchase event on a real order

    Place a test order and confirm the purchase event fires once, carries a unique transaction identifier, a numeric value, the correct currency code and an item array. Repeat on mobile and with an accelerated payment method, which often follows a different path.

  6. Send refunds if the business needs net revenue

    If reporting has to reflect returns, implement a refund event that carries the original transaction identifier and the refunded amount. If that is not practical, report net revenue from the store and use the analytics property for behaviour and channel mix instead.

  7. Fix consent so measurement degrades rather than stops

    Configure the consent tool to send explicit signals rather than blocking the tag, set defaults appropriate to each region, and make sure the update fires immediately when a choice is made. This preserves modelled reporting for visitors who decline.

  8. Write down the expected gap

    Once the fixable causes are closed, record the remaining percentage difference and the reason for each component. That figure becomes your monitor: when it moves, something broke, and when it holds, the reports are behaving as designed.

When to get help

Ask for help when the remaining gap is large after the structural causes are removed, or when the finance team and the marketing team are making decisions from different totals. Closing that properly usually means server side collection so the purchase is sent from the order record rather than the browser, plus a defined reconciliation report that runs on a schedule. It is also worth help when the store sells in several currencies or markets, because the reconciliation design matters more than the tag.

Get a Growth Analysis

Free. We reply within one business day.

Questions

Asked alongside this problem

By CartKernel · Last reviewed

Which number should the business report as revenue?

The store admin, because it is the system of record for orders and money. Use the analytics property to understand where demand came from and how people behaved, not to state financial results. Deciding this once removes most arguments about which report is right.

Is a gap between the two systems ever acceptable?

Yes, and expecting an exact match is the mistake. Sessionless orders, consent declines and timing differences always produce some difference. What matters is that you know the size of the usual gap and its causes, so a change in that gap becomes a useful signal.

Does server side tagging remove the difference entirely?

It removes some of it, particularly losses from blocking extensions and browser storage limits, because the event is sent from a server rather than the page. It does not create sessions for orders that never had one, and it does not change how values or refunds are defined.

Why do the totals change when I look at the same dates a week later?

Data continues to process for a period after collection, and reports that use identity or modelled data can be restated as more information arrives. Compare only completed periods, and give recent days time to settle before treating a difference as a defect.

Related problems, answers and terms

All problems
ProblemGA4 purchase event not firing: how to fix itA GA4 purchase event not firing leaves ecommerce reports empty while orders keep arriving. Trace the event from checkout to property and repair it.OpenProblemGA4 unassigned traffic: how to fix itGA4 unassigned traffic means a session's source could not be placed in any channel. Find which sessions, why, and how to give them a home.OpenProblemConversions dropped after Consent Mode: how to fix itConversions dropped after Consent Mode is usually a configuration choice, not a legal ceiling. What to check, and how to keep reporting honest.OpenProblemGoogle Ads conversion tracking not working: how to fix itGoogle Ads conversion tracking not working shows as zero, double or unverified conversions. Find which of the three you have, then fix the tag.OpenAnswerWhy does GA4 show less revenue than Shopify?GA4 reports less revenue than Shopify because it only counts purchases its tag saw and consent allowed. Where the gap comes from and how to close most of it.OpenAnswerDoes an ecommerce store need server-side tagging?Not every store needs server-side tagging. When the hosting and setup cost pays off, what it changes, what it does not, and what to fix first.OpenGlossaryServer-side taggingServer-side tagging sends browser events through a tag server on the store's own domain before GA4, Google Ads and Meta see them. Setup, benefits, pitfalls.OpenGlossaryData layerA data layer is the structured JavaScript object holding page and ecommerce event data for a tag manager. GA4 shape, a purchase example, common errors.Open

Stop the leak.

A free Growth Analysis finds what is broken and ranks it by the revenue it costs you.