First, check what WooCommerce is counting
On WooCommerce, the two sets of numbers can differ before any tracking goes wrong, because of how reports treat order statuses and dates. These settings live under Analytics, Settings. All of this was checked in WooCommerce's documentation in November 2026.
- Excluded statuses: by default WooCommerce Analytics leaves out Pending payment, Cancelled and Failed. On hold stays in, even though WooCommerce describes it as awaiting payment confirmation. A bank transfer that hasn't arrived can be in your report already.
- Custom statuses: statuses added by a shipping or fulfilment plugin are included in reports by default. If a tracking plugin only fires on Processing or Completed, orders that jump straight to a custom status can be missed.
- Date type: the default is Date Paid. A browser tag fires when the buyer sees the order-received page, which can be days before a bank transfer is paid. Compare a full week rather than one day.
- Time zone: GA4 uses the property's reporting time zone, WooCommerce uses the one in your WordPress settings. If they differ, late-evening orders land on another day.
- Processing delay: GA4's standard reports can run a day or two behind. Leave the last two days out of your comparison.
Why GA4 shows fewer purchases than WooCommerce
This is the usual direction. A browser tag reports a purchase only if the buyer reaches the order-received page, the page is fresh, and the script is allowed to run. WooCommerce stores have a few extra ways to break that chain.
- Your own test orders. Google Analytics for WooCommerce says in its FAQ that it purposely doesn't track admin visits, and other plugins have similar settings. Test in a private window, logged out, or you'll think tracking is broken when it isn't.
- Redirect payments. With PayPal, Klarna, iDEAL and similar methods the buyer pays on another page. Whoever closes that tab never comes back to your order-received page.
- Caching. A cached or partly cached order-received page can miss the order details the tag needs. Exclude that page from your cache.
- Script delay and minify settings. Performance plugins can hold scripts back until the visitor scrolls, clicks or types. A buyer who sees the confirmation and leaves never triggers them.
- Custom thank-you pages. A page builder or funnel plugin can replace the standard page, and the hook your tracking plugin listens to may not run there.
- Consent banners. If a buyer declines, or your banner isn't connected to your tag, the tag runs in a limited mode or not at all.
- Ad blockers and privacy browsers, which stop Google's scripts before they load.
- Orders without a website visit. Orders you enter by hand and subscription renewals exist in WooCommerce, but no buyer's browser saw them.
Why GA4 can show more than WooCommerce
More purchases in GA4 than paid orders in WooCommerce usually means two sources report the same sale. On WordPress that's easy to get: a GA4 plugin, a tag manager container and a theme setting can all send a purchase. Check each one, and check that they all point to the same GA4 property.
GA4 drops repeat purchases with the same transaction id, according to Google, but only on web streams and only when the id really matches. WooCommerce makes this easier to miss: a sequential order numbers plugin gives each order a number that differs from its internal id. If one tag sends the number and another sends the id, GA4 sees two sales.
Failed and cancelled orders are the other cause. Google Analytics for WooCommerce only stopped sending the purchase event for those orders in version 2.4.4, released in October 2026. If you run an older version, update before you compare. Other plugins can behave differently, so look up one failed order in GA4 to see what yours does.
Why revenue differs when the orders match
If the purchase counts line up but revenue doesn't, look at what's inside the value.
- Shipping and tax: one setup reports the full order total, another only the products. Check your plugin's setting and compare it with the report you're reading.
- Currency: a currency switcher can send the buyer's currency to GA4 while your report shows the shop currency.
- Refunds: WooCommerce reports reflect them. GA4 keeps the original purchase unless a separate refund event is sent, so GA4 runs higher on stores with many returns.
- Orders that change later: an order cancelled after payment stays in GA4 as a sale.
- Profit-based values: if a tool sends profit as the purchase value, GA4 always shows less. Settl has this as an optional setting.
Compare one week, order by order
This replaces the guessing. It tells you which orders are missing, and that usually shows the pattern.
- In WooCommerce, open Analytics, Orders, pick one full week that ended at least two days ago, and download the list.
- In GA4, open Explore and make a free-form report with Transaction ID as the dimension and Ecommerce purchases and Purchase revenue as metrics, for the same dates.
- Put both lists in a spreadsheet and look up each order number in the GA4 list.
- Sort the missing orders by status, payment method, country and device. Most of them on hold points to reports rather than tracking, most from PayPal or Klarna points to redirects, and most from Europe points to consent.
- Look for one order under two ids, or rows with a count above 1. Both mean a double setup.
- Look for GA4 transaction ids that aren't in your paid list. Those are usually failed, cancelled or test orders.
When purchases land under Unassigned or Direct
Sometimes the count is right but the channels are wrong. After a redirect payment, a buyer who does come back can start a new session, so the sale gets credited to the payment page instead of your ad. Add your payment providers to GA4's list of unwanted referrals to reduce that.
Server integrations have their own version of the problem. GA4 links a purchase to a visit through the client id and session id. Without them the purchase can land under Unassigned or Direct, and Google Ads can't import it for that click. Before you trust a server-side setup, check that it passes both from the _ga cookies.
What server-side tracking fixes, and what it doesn't
Sending the purchase from a server removes the dependence on that one page load. Closed PayPal tabs, cached pages, delayed scripts and ad blockers no longer decide whether GA4 hears about the sale. The Settl plugin reports the order when WooCommerce marks it as paid, and Settl sends it through Google's Measurement Protocol with the WooCommerce order number as transaction id, plus value, currency, products, hashed email and consent signals. Bank transfers go out when they're paid, not when the order is placed. On-hold, pending, failed and cancelled orders aren't sent. The plugin saves the GA4 client id and session id from the visitor's cookies, so the purchase can join the session it came from. Every hour Settl also checks the past week's paid orders and sends anything that didn't arrive.
It won't make the two reports identical. Settl doesn't send refunds to GA4. A bank transfer lands in GA4 around the day it's paid, so it won't line up with a report by order date. Orders entered by hand and renewals have no visit to connect to. A buyer who blocked all cookies has no client id, so the sale counts but won't sit in the right session. And it doesn't replace consent: you stay responsible for your cookie banner and privacy policy.
One thing to check after you connect it. If a GA4 plugin keeps sending purchases to the same property with a different id, each sale shows up twice. Run the comparison above after a few days, and if you see two formats, switch off the purchase event in one of the two.