WooCommerce CRO Technique

Why GA4 revenue doesn’t match WooCommerce orders

This technique is a structured reconciliation check between GA4 purchase data and WooCommerce order reporting. It helps when GA4 revenue, purchase count or both drift away from WooCommerce because of mismatched definitions, date settings, missing or duplicated tags, consent loss, or reporting artefacts rather than a real trading problem.

Summary

Bottom Line: GA4 will only line up with WooCommerce if you compare like with like: the same timezone, the same date basis, the same included order statuses, and the same revenue definition.

  • Start with definitions, not tags. For most WooCommerce stores, GA4 purchase revenue should be compared to a WooCommerce comparable net item revenue view, not blindly to WooCommerce Total Sales, because Woo Total Sales adds taxes and shipping back in.
  • In GA4, a valid purchase event needs transaction_id, value, currency and items, with item_id or item_name at item level. If any of those are wrong, revenue and purchase counts can go missing or misstate.
  • Duplicate or blank transaction_id values distort the picture in opposite directions: reused IDs can cause undercounting through deduplication, while regenerated IDs on refresh or repeat hits can overcount.
  • WooCommerce comparison settings matter. WooCommerce Analytics lets you choose excluded statuses and the Date Type used for Revenue and Order reports, so you can create a mismatch before you even open GTM.
  • If you need order-level truth, use GA4 BigQuery export plus Woo order data, not a thresholded report or a sampled exploration. Google explicitly says BigQuery export is raw event and user-level data and can differ from the GA4 interface because the interface adds value on top.

How To Implement

  • Freeze the comparison rules before touching any tags

    In GA4, confirm the property reporting timezone and currency. In WordPress, confirm Settings → General → Timezone. In WooCommerce, go to WooCommerce → Analytics → Settings and note the Date Type plus which order statuses are excluded. If you compare GA4 in one timezone and WooCommerce in another, or compare Woo “Date Paid” to GA4 event date without noticing, you will create a fake mismatch. Use a settled date range rather than judging same-day data.

  • Choose the correct WooCommerce comparison metric

    In WooCommerce → Analytics → Revenue, note that WooCommerce defines Gross Sales as item sales before refunds, coupons, tax and shipping; Net Sales as gross minus returns and coupons; and Total Sales as gross minus returns and coupons plus taxes and shipping. GA4’s purchase.value should be the sum of item prices times quantity and should not include shipping or tax, so as a working comparison GA4 purchase revenue is usually closer to WooCommerce Net Sales than to WooCommerce Total Sales. If you use discounts, confirm your GA4 implementation sends the discounted item price; Google says it does not subtract discount from price automatically.

  • Check where the purchase event is supposed to fire in WooCommerce

    Google’s setup guide shows the purchase event firing on the purchase confirmation page. On classic WooCommerce templates, many implementations still rely on the legacy thank-you flow and the woocommerce_thankyou hook. If your theme overrides woocommerce/checkout/thankyou.php or uses a custom thank-you plugin, verify that the hook or equivalent tracking output still runs. On block themes, the order confirmation surface lives at Appearance → Editor → Templates → WooCommerce → Order Confirmation. WooCommerce documents that inserting the Order Confirmation Block classic placeholder makes the site use the legacy template again, which is useful if your older tracking code only runs there.

  • If the store uses Cart & Checkout Blocks, check the block path separately from the classic path

    WooCommerce says Cart and Checkout Blocks are the default experience for stores started after WooCommerce 8.3, and the order confirmation page is now a dedicated template in the Site Editor. That means a legacy tracking method tied to classic templates can survive checkout but fail on confirmation after a redesign or a block-theme change. This is not a WooCommerce bug by itself; it is a tracking implementation dependency you need to verify.

  • Inspect the data layer on a real test order

    Use GTM Preview / Tag Assistant and GA4 DebugView on a new test order. The page or custom event that signals purchase should expose a data layer payload with transaction_id, numeric value, currency and items, and each item should include item_id or item_name. Google’s data layer documentation says GTM uses the event key to trigger tags, and Google’s ecommerce troubleshooting says the purchase setup must be correct both in the data layer and in the GA4 Event tag.

  • Open the GTM purchase tag and verify the mapping

    In Tag Manager → Workspace → Tags, open the GA4 Event tag used for purchase. Confirm the event name is exactly purchase, the trigger is the intended order confirmation condition or custom event, and the event parameters are mapped from the data layer values rather than hard-coded or partially copied. Google’s Tag Manager help shows the GA4 Event tag path, how to create triggers, how to preview the container and how to publish it. If you use shared event settings variables, make sure they are not overwriting purchase-specific values like currency.

  • Verify the four parameters that usually explain the mismatch

    • transaction_id: unique per order, never blank, and stable on refresh. Google says transaction IDs deduplicate duplicate web purchases and warns not to send an empty string.
    • value: numeric, event-level, and equal to the sum of item revenue. It must exclude shipping and tax.
    • currency: event-level ISO 4217 code. Without it, revenue metrics break.
    • items: present, with valid item identifiers and correctly discounted prices where relevant. Google says price should already reflect the actual price paid per unit after discount allocation.
  • Test the two classic failure modes: duplicates and misses

    Refresh the thank-you page, retry a failed payment, and run at least one external-gateway journey that returns to the store. If the page refresh sends a second hit with a different transaction_id, you will overcount. If the same order keeps reusing a fixed or blank ID, you can undercount through deduplication. If your implementation only fires on the confirmation page and the customer never returns there, that client-side purchase event may never be observed. Google’s own setup places the purchase event on the confirmation page, so this return path matters.

  • Don’t reconcile from the wrong GA4 surface

    Avoid thresholded reports, sampled explorations and heavily modelled interpretations when you are doing a source-of-truth check. Google says thresholding can withhold data, sampling can appear in explorations above event limits, and behavioural modelling estimates behaviour for users who decline consent. For this job, use standard monetisation reporting for a quick check and BigQuery export for order-level truth.

  • Reconcile at order level in BigQuery when the variance is still unexplained

    In GA4 Admin → Product Links → BigQuery Links, enable export if it is not already linked. Google’s export docs show that the dataset is named analytics_<property_id> and that the export contains ecommerce.transaction_id, ecommerce.purchase_revenue, ecommerce.shipping_value, ecommerce.tax_value, repeated items records, user_pseudo_id, and consent fields in privacy_info. Pull the purchase rows, then join them to WooCommerce order data by order number or order key from a Woo export. WooCommerce Analytics tables can be downloaded as CSV from report tables, which is often enough for a first pass.

     SELECT
     event_date,
     ecommerce.transaction_id AS transaction_id,
     ecommerce.purchase_revenue AS purchase_revenue,
     ecommerce.shipping_value AS shipping_value,
     ecommerce.tax_value AS tax_value,
     user_pseudo_id,
     privacy_info.analytics_storage AS analytics_storage
     FROM `your_project.analytics_PROPERTY_ID.events_*`
     WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260630'
     AND event_name = 'purchase';
  • Write up the variance by cause, not as one lump

    Separate the gap into: – definition differences: shipping, tax, discount allocation, refund timing; – capture loss: consent denial, blocked tags, opt-out tools, blocked tag loading; – reporting artefacts: thresholding, sampling, modelling; – implementation defects: missing items, wrong value type, duplicate firing, unpublished GTM changes. This is the step that turns “GA4 is wrong” into a fix list you can act on. Google explicitly documents all four categories somewhere in its GA4 and Tag Manager help.

How To Measure

Key KPIGA4-vs-Woo revenue variance and GA4-vs-Woo order variance, tracked weekly on a fixed comparison basis. Use a formula such as (GA4 comparable revenue - Woo comparable revenue) / Woo comparable revenue and the same for purchase count versus included Woo orders. Success is a small, explained variance that stays stable over time, not perfect parity.

GA4 events / reports to use — Use the purchase event and the Ecommerce purchases or monetisation reporting surfaces for a first pass. Prefer Purchase revenue or purchase-based monetisation views over a broad “Total revenue” lens when you are reconciling store sales, because Google defines total revenue more broadly. For implementation checks, use Realtime and DebugView; Google says purchase data appears in reports after about 24 hours.

WooCommerce segment to read it in — Read WooCommerce from WooCommerce → Analytics → Revenue with the same date range, the same Date Type, and the same included statuses. Then break the variance down by day first, and only then by channel, device or campaign if the site volume supports it. WooCommerce’s report tables can be exported to CSV for the same date window.

What success looks like — Success is a narrow, explainable gap that you can account for from known causes such as shipping/tax definition differences, discount handling, refund timing, consent loss or blocked tags. If the remaining gap is still material after those are accounted for, move to order-level checking in BigQuery.

Guardrail metrics — RPV, conversion rate, checkout completion and AOV should not show unexplained jumps after you change tags or purchase-event logic. On the data-quality side, guard against duplicate purchase IDs, purchases missing currency or items, and any GA4 report showing thresholding or sampling warnings during validation.

Pitfalls

  • Myth: GA4 should match WooCommerce to the penny. That is not how GA4 is documented to work on live traffic once consent loss, blocked tags, thresholding or modelling enter the picture. GA4 is a measurement layer; WooCommerce orders are your commercial ledger.
  • Mistake: comparing GA4 to WooCommerce Total Sales. WooCommerce Total Sales includes taxes and shipping; GA4 value for purchase should exclude both. That comparison will overstate the “gap” before you inspect a single tag.
  • Mistake: assuming Google subtracts discounts for you. Google says it does not automatically subtract discount from price; you must send the actual discounted item price. If a plugin sends pre-discount prices plus a discount value, GA4 revenue can run high.
  • Mistake: validating from the wrong GA4 report. Thresholded reports can withhold data and explorations can sample; neither is the right place to decide whether the implementation is trustworthy.
  • Mistake: forgetting the order confirmation template. In WooCommerce, a redesign from classic templates to block-based order confirmation can leave a legacy thank-you-page tracking method behind.

Examples

FAQs

Sources & Further Reading

Want us to implement this for you?

We run measured CRO consultancy for WooCommerce. If you want help prioritising, testing & implementing these improvements, tell us about your store.

Book Pilot

About This Page

  • Written By: Eliot Webb – Founder & WooCommerce CRO Consultant
  • Last Reviewed: 17 Jun 2026
  • Last Updated: