flowsk.com
Why attribution is broken

Why GA4 says 40 conversions and Stripe says 25

GA4 is session-based, thresholded and models what it could not observe. Four specific mechanics explain almost every GA4-vs-payments discrepancy — and one of them is probably yours.

Jul 31, 2026· 3 min read ·Why attribution is broken
Quick answer

GA4 count = observed events + modelled + duplicates − blocked − thresholded

GA4 disagreements are usually caused by one of four things: duplicate purchase events on page refresh, ad-blocked sessions, modelled conversions from consent mode, or a timezone mismatch between GA4 and your payment processor.

Check duplicates and timezone first. They account for most of the gap and take ten minutes to rule out.

The Meta-vs-Stripe gap has an interesting answer about attribution models. The GA4-vs-Stripe gap usually has a boring answer about implementation, which is good news: boring problems are fixable this afternoon.

Work through these four in order.

1. Duplicate purchase events (GA4 too high)

The single most common cause.

Your purchase event fires on the order confirmation page. Then the customer refreshes. Or navigates back to it. Or bookmarked it last month and opens it again. Each time, the event fires again.

The check: in GA4, look at purchase events per user. Anything above 1.0 in a period where most people bought once is duplication.

The fix: always send transaction_id. GA4 de-duplicates on it within a session. Better still, fire the event from a server-side source that only knows about real orders.

gtag("event", "purchase", {
  transaction_id: "10482",   // ← without this, nothing de-duplicates
  value: 129.00,
  currency: "USD"
})

2. Blocked sessions (GA4 too low)

googletagmanager.com and google-analytics.com are on every tracker blocklist that exists. Sessions with an ad blocker, a privacy browser, tracking protection or a filtering DNS resolver never send the event at all.

This is not random noise. It is systematically worse on paid traffic, on mobile, and on technical audiences — which means it distorts channel comparisons rather than just adding uncertainty.

The check: compare your GA4 conversion count to your payment processor by traffic source. If paid social is worse than organic, blocking is a large part of it.

The fix: send the purchase from your server as well. That event cannot be blocked because it never touches the browser.

3. Modelled conversions and thresholding (GA4 unpredictable)

With consent mode, GA4 estimates conversions for users who declined cookies. Those estimates are reported alongside observed conversions with no separate column in most reports.

Separately, GA4 applies data thresholds — rows with small user counts are suppressed entirely to protect anonymity. Your long-tail campaigns can simply vanish from a report while their conversions remain in the totals.

The check: look for the “data threshold applied” notice on reports, and compare “conversions” against “all conversions” where the distinction is available.

The fix: there is not one within GA4. This is a design decision, not a bug. It is one of the reasons a separate first-party ledger exists.

4. Timezones and day boundaries (GA4 shifted)

GA4 reports in the property’s configured timezone. Stripe reports in UTC or your account timezone. If those differ, conversions move between days.

Daily comparisons will be wrong by however many orders land in the offset window — which for an evening-heavy DTC store can be a substantial share of the day.

The check: compare a full month rather than a day. If the monthly totals agree and the daily ones do not, it is timezone.

The fix: align the timezones, or only ever compare complete months.

The order to check them

Symptom Most likely cause Time to verify
GA4 higher than Stripe Duplicate purchase events 5 minutes
GA4 lower than Stripe Blocked sessions 15 minutes
Daily numbers off, monthly fine Timezone mismatch 2 minutes
Small campaigns missing entirely Thresholding 5 minutes
Gap varies wildly week to week Consent-mode modelling Not resolvable

After you have fixed the fixable

Items 1, 2 and 4 are implementation bugs and you should fix all of them. Item 3 is structural: GA4 will always model and threshold, because that is what it is designed to do.

Once the fixable ones are gone, you are left with a tool that is excellent at behavioural analysis and structurally unable to be your revenue ledger. That is a fine outcome — just keep the two jobs in different tools. The full GA4 comparison covers where each one is the right answer.

Frequently asked questions

Why would GA4 report MORE than Stripe?

Most often duplicate purchase events. If your purchase event fires on the thank-you page, every refresh, back-navigation or bookmark re-fires it. Without a transaction id, GA4 counts each one.

Why would GA4 report FEWER than Stripe?

Ad blockers, consent declines, and users who close the tab before the event sends. All silent, all systematic, all worse on paid traffic than on organic.

Does GA4 deduplicate purchases?

It de-duplicates on transaction_id within a session for ecommerce events. If you are not sending transaction_id — and many implementations are not — nothing de-duplicates.

Is GA4 data sampled?

Standard properties apply thresholds and sampling on large or complex queries, and suppress rows with small user counts for privacy. Fine for trends, unusable for reconciling revenue.

What is the timezone trap?

GA4 reports in the property's configured timezone; Stripe reports in UTC or your account timezone. A day boundary offset shifts conversions between days and makes every daily comparison wrong.

Compare every source at once

Add up what GA4, Meta, Google and email each claim, put your banked orders next to it, and see the total over-report.

Find my ghost conversions

Stop guessing which ad made the sale.

Flowsk Signals stitches the anonymous click to the email to the purchase — first-party, server-side, de-duplicated. One snippet, $29/mo, and every conversion comes with a receipt you can inspect.

Keep reading