rytisbalys.com / troubleshooting

GA4 purchases don't match your backend orders. Which number do you trust?

Short answer: your backend's PAID orders are the truth. GA4 is a browser-side observer with known blind spots. The real question is whether your gap is a normal one or a broken one - here's how to tell.

Step 0 - make the comparison honest

Most "GA4 is wrong" panics die here. Compare the same thing: GA4 transactions for a full month vs backend orders that were actually PAID in that month. Backend "all orders" usually includes cancellations, failed payments and abandoned financing applications that no analytics tool should count.

VERIFY - filter backend orders by paid status first. It's common to see an "orders" total shrink by a third or more once unpaid and cancelled ones are stripped out - which makes the raw comparison meaningless.

What a NORMAL gap looks like

GA4 will always see fewer purchases than your backend. Consent rejections (in the EU, everyone who clicks "decline"), ad blockers, Safari's tracking prevention, and users who close the tab before the thank-you page loads. With a strict opt-in consent banner, a 15-30% gap can be fully legitimate - your baseline is roughly your consent rejection rate plus 5-10%.

Corollary: if GA4 shows MORE than your paid backend orders, that's never normal - hunt for duplicate events or test traffic.

01Redirect payments never reach the thank-you page

PayPal, financing, bank redirects: buyers pay off-site and a share never return to the page where the purchase event fires. The loss concentrates in specific payment methods, which is exactly how you catch it.

VERIFY - join GA4 transaction IDs against backend order IDs, segment the missing ones by payment method. If the missing orders cluster on redirect payments, you found the mechanism.

02Server-side container configured but not connected

A surprisingly common one: a server GTM container exists (Stape or self-hosted), but the web container's GA4 tag has no server_container_url - so every event still goes client-side only and inherits every browser blind spot. The server container sits at zero requests and nobody notices.

VERIFY - check the GA4 config tag for a server container URL, and check the server container's request log. Zero incoming requests = it's decorative.

03Duplicate or phantom events inflating GA4

Two GA4 configs on one page, a purchase event firing on page refresh, or a tag on a too-broad trigger. This produces the scarier version: GA4 ABOVE backend.

VERIFY - GA4 DebugView, run one test purchase, count how many purchase events arrive. More than one = trace both sources in GTM Preview.

04Cross-domain journeys breaking attribution and sessions

Separate checkout domain, rebranded domain, or a landing domain that hands off to the store - without cross-domain configuration, GA4 restarts the session mid-journey and purchases detach from their sources (everything collapses into Direct or referral spam).

VERIFY - check the GA4 data stream's configured domains against every domain in the real purchase path, including payment and rebrand domains.

05Consent Mode modeling quietly changing your numbers

With Consent Mode, Google models conversions for visitors who declined. Modeled conversions appear in some reports and not others, so two GA4 screens can legitimately disagree with each other - before you even compare to the backend.

VERIFY - compare the same date range in Reports vs Explorations. If they differ, modeling is in play; document it before blaming the pipeline.

The reconciliation that settles it

1. backend: paid orders only, one full month
2. ga4: transactions, same month
3. join on transaction_id -> list the missing orders
4. segment missing by payment method + device
5. the cluster tells you the mechanism; fix THAT, not "tracking" in general

The named list of missing orders is the deliverable that turns a vague "our numbers are off" into a scoped, fixable engineering task.

Want this done properly? I run exactly this reconciliation as a fixed-scope audit - every number verified against live APIs, every finding with severity, effort and a fix direction. Then I build the server-side pipeline that closes the gap.

work@rytisbalys.com