virling Pricing Self-host Demo Changelog Agencies GitHub Start free trial
blog / 2026-11-01

Why GA4 revenue doesn't match Stripe or Shopify

By Devendra Variya, co-founder of Virling. Published 2026-11-01.

TL;DR: GA4 counts purchase events that a browser sends. Stripe and Shopify count money that actually moved. Anything that stops the event from being sent, or changes the amount after it was sent, opens a gap. Trust your payment provider for revenue, and use analytics only to say where each payment came from.

The eight causes, and how to check each

CauseHow to checkFix
The purchase event never firesCount GA4 purchase events and successful payments for the same day. Hosted checkouts such as checkout.stripe.com return to your site only if the buyer waits for the redirectSend the purchase from your server when the payment webhook arrives, not from the thank-you page
Ad blockers and declined consentCompare purchases in GA4 with orders in the same hour; the gap stays even on days with no other issueServer-side events reduce it. Some gap is normal
Subscription renewalsIn Stripe, invoices with billing reason subscription_cycle. No visit happens, so the browser sends nothingSend renewals from the server, or use a tool that reads payments
Refunds and disputesYour provider subtracts refunds; GA4 keeps the purchase unless you send a refund eventSend a refund event with the same transaction_id
CurrencyPurchase events without a currency parameter do not count toward revenue. GA4 also converts to your property currency at its own rateAlways send currency with value
Tax, shipping and discountsCompare one order's value in GA4 with its total in Shopify or StripeDecide what value means and send the same thing every time
Time zonesYour GA4 property and your Stripe or Shopify account can use different time zones, so orders near midnight land on different daysCompare whole weeks or months, or set both to the same zone
Duplicate purchase eventsGA4 higher than Stripe usually means the thank-you page fired twice, for example on reloadSend a unique transaction_id so GA4 can drop the duplicate

When the total matches but the channel is wrong

A second problem hides inside the first. When a buyer leaves for checkout.stripe.com or a PayPal page and comes back, GA4 can start a new session with the payment page as the referrer. The sale then belongs to Stripe or PayPal instead of the ad or post that brought the buyer. Add those domains to GA4's list of unwanted referrals in the data stream's tag settings.

Long buying cycles cause the same drift: a buyer who first came from a post and paid two weeks later from a bookmark shows as Direct under a last-click view. See first-touch or last-touch attribution.

How to send Stripe purchases to GA4

  1. When you create the Checkout Session, put the visitor's GA4 client ID in client_reference_id or metadata.
  2. Listen for the checkout.session.completed webhook on your server.
  3. Send a purchase event to GA4 with the Measurement Protocol, using that client ID, the session ID as transaction_id, the amount as value and the currency.
  4. Send a refund event with the same transaction_id when Stripe reports a refund.
  5. Add checkout.stripe.com to GA4's unwanted referrals so the return visit keeps its source.

That fixes the missing and duplicate purchases. It does not bring in renewals unless you also send them from invoice.paid.

Which number to trust

Use your payment provider for revenue, refunds and renewals, because it is the ledger. Use analytics for the question it can answer: which visit came before each payment. The reliable way to join the two is to pass a visitor ID into checkout and match each payment to that visitor's visits, as in tracking Stripe revenue by traffic source.

Virling does this join for you. It reads payments from Stripe, Shopify and seven other providers with a read-only key, so its revenue matches your provider, and credits each payment to the visit before it. Renewals keep the channel of the first payment.

Frequently asked questions

Why is GA4 revenue lower than Stripe?

Usually because purchase events never fire: buyers who close the tab after paying, blocked or declined tracking, and subscription renewals that happen without a visit. Missing currency parameters also drop revenue.

Why is GA4 revenue higher than Stripe or Shopify?

Duplicate purchase events, often from a reloaded thank-you page, and refunds that GA4 never hears about. Send a unique transaction_id and a refund event.

Does GA4 track Stripe subscription renewals?

Not on its own. A renewal is charged with no visit, so no browser event is sent. You have to send it from your server or use a tool that reads payments from Stripe.

How do I stop checkout.stripe.com showing as a referrer in GA4?

Add checkout.stripe.com, and any other payment domain you use, to the list of unwanted referrals in your GA4 data stream's tag settings.

How do I connect Stripe to GA4?

Pass the GA4 client ID into the Checkout Session, listen for the checkout.session.completed webhook, and send a purchase event with the Measurement Protocol. Add checkout.stripe.com to GA4's unwanted referrals.

Get revenue that matches your payment provider, split by channel: start a 14-day free trial at app.virling.com.