There is a specific kind of expensive mistake that happens when analytics is wrong but plausible. A store shifts budget away from a channel that was actually working, or approves a redesign based on a funnel that was never measured correctly. Broken tracking does not announce itself. It produces numbers that look reasonable, which is far more dangerous than producing none.
This is a checklist for getting the ecommerce side of GA4 into a state you can make decisions from. It assumes you are not an analyst and do not want to become one — the goal is trustworthy basics, not a data warehouse.
The event set that is enough
GA4 recognises a standard ecommerce sequence, and implementing it correctly matters more than adding custom events on top. The minimum useful set is view_item_list, view_item, add_to_cart, begin_checkout and purchase. Each needs an items array carrying item_id, item_name, price and quantity, and purchase additionally needs a transaction_id and a value. Without transaction_id, GA4 cannot deduplicate, and one refresh of the thank-you page becomes two sales in your reports.
- view_item_list, view_item, add_to_cart, begin_checkout, purchase
- items array with item_id, item_name, price, quantity
- purchase requires transaction_id and value
- Currency set explicitly, especially on multi-currency stores
Why GA4 revenue will never match WooCommerce
It will not, and expecting it to is the source of endless wasted hours. The gaps are structural: consent choices block measurement for some visitors, ad and tracking blockers remove others, a shopper who closes the tab before the thank-you page fires never registers a purchase, and refunds and cancellations are recorded in WooCommerce but often never sent to GA4. Manual and phone orders never touch the storefront at all.
A gap of a few per cent is normal and healthy. A gap of thirty per cent means something is broken, and a gap that changes suddenly between months is the signal to investigate — the absolute difference matters far less than its stability. Reconcile monthly, write the number down, and treat the trend as your tracking health metric.
The failure modes, in order of frequency
The most common is a theme or plugin update that removes the dataLayer push on one template — usually the product page, because it is the most customised. Second is duplicate tags: the measurement ID installed both by a plugin and by a tag manager container, doubling every event. Third is a consent banner that blocks tags without anyone realising the default is now "deny", which shows up as a sudden traffic cliff that is not real. Fourth is checkout on a different domain or subdomain without cross-domain configuration, which makes every purchase look like it came from a referral. All four are visible in DebugView within a minute of looking, which is why the check belongs after any theme or plugin update, long before the end of a quarter.
- Missing dataLayer push after a template update
- Duplicate tags: plugin and tag manager both firing
- Consent banner blocking by default without anyone noticing
- Cross-domain checkout not configured — purchases attributed to referrals
Test it in fifteen minutes
Open GA4's DebugView, then walk your own store as a customer: category, product, add to cart, begin checkout, complete a real order with a real card and refund it afterwards. Watch each event arrive with its parameters. This is not sophisticated, and it catches nearly everything on the list above. Do it after every theme update, every plugin change that touches the storefront, and immediately after any migration.
Consent, and the honest version of the trade-off
If you serve visitors in regions that require consent before analytics cookies, blocking measurement until consent is given is not optional. The practical consequence is a measurement gap, and the honest response is to model and accept it. Quietly setting the banner to fire tags regardless is the other option, and it is not one. Consent mode exists to make that gap smaller and legible, where the alternative is pretending it is not there — consent and privacy for stores covers what the banner actually has to do. Expect the gap to be visible, not marginal: EU stores commonly see a double-digit share of sessions unmeasured, and the right response is to compare like with like over time, not to reconcile GA4 against your order table and conclude the tracking is broken.
What to actually look at once it works
Three things, monthly. Conversion rate by device, because the mobile-desktop gap is usually where the money is leaking and it is the gap storefront work moves. The funnel from view_item to purchase, to see which step loses the most people. And landing pages by revenue and not by sessions, because the pages that bring traffic and the pages that bring money are rarely the same list, and knowing the difference changes where you spend. Set data retention to 14 months on day one — GA4 defaults to two, and the default quietly removes your ability to compare this season against last.
Once you have those, the arithmetic in the revenue calculator stops being hypothetical: you know your sessions, your conversion rate and your order value, so you can price any proposed improvement before agreeing to it.
Server-side is not the first answer
Server-side tagging is frequently recommended as the fix for blocked or lost data, and it does recover some measurement. It also adds infrastructure, cost and a new place for things to break, and it does not exempt anyone from consent obligations. Get the browser implementation correct and reconciled first. If you are still losing meaningful data after that, server-side becomes a reasonable next step. Reaching for it first is a way of skipping the boring work. It does not exempt you from consent, and it does not pay for itself below a few thousand sessions a day — at that size you are buying a server to recover data you could recover by fixing one event.
Analytics that is wrong but plausible costs more than no analytics at all, because it produces confident decisions.
