Why do daily numbers differ across analytics tools?
Last updated: August 5, 2026
From the SoleOS answers series — written about our own product space; grounded in published definitions and documented behavior, never invented numbers.
Daily numbers differ across analytics tools because each one uses a different timezone as its "day boundary," a different definition of the event it's counting (a session isn't a visit isn't a user), and a different moment for when data finally settles. None of this means one tool is "wrong" — it means you're comparing three different measurement systems and expecting them to produce identical output. The fix isn't finding the "correct" tool; it's understanding each tool's definitions well enough to know which one to trust for which question.
This is the single most common support question in indie analytics, and it comes up constantly with two pairings in particular: Stripe vs. RevenueCat for revenue, and GA4 vs. PostHog for traffic. Below is what's actually happening under the hood.
The timezone problem is bigger than you think
Most founders assume "yesterday" means the same 24 hours everywhere. It doesn't.
- Stripe reports in the timezone set on your Stripe account (often UTC unless you changed it).
- GA4 reports in the timezone you configured in the property settings — which may or may not match your Stripe account.
- RevenueCat aggregates on UTC days for most metrics, regardless of what timezone your app displays to users.
- App Store Connect and Google Play sales reports are famously tied to their own internal reporting day, which for Apple can differ from calendar UTC by design.
If you're in California and your Stripe account is set to UTC, "today's revenue" on your Stripe dashboard already spans two different calendar days from your perspective. Multiply that by four or five tools with four or five different timezone settings, and a single sale near midnight can show up on different "days" in different dashboards. This is annoying for a single product. Across a portfolio of five or ten apps, each with its own Stripe account or RevenueCat project, the timezone drift compounds — one app's "day" starts eight hours before another's.
Definitions of "day," "user," and "revenue" don't match
Even inside the same timezone, tools count different things when they say "revenue" or "user."
Revenue: Stripe's dashboard revenue is typically gross charge volume net of Stripe's own adjustments, recorded at the moment a charge succeeds. RevenueCat's MRR estimate is a subscription-state calculation — it looks at active subscriptions and projects what they're worth, which is a different animal from "money that moved today." A single failed card retry, a delayed webhook, or a subscription renewal that Apple processes a few hours late will make these numbers disagree on any given day, even though they should converge over a longer window.
Users: GA4 counts users based on a device/cookie identifier and session logic that resets after 30 minutes of inactivity by default. PostHog, if self-hosted or configured differently, may use a different session timeout, different bot filtering, or different identity-merging rules (anonymous ID vs. logged-in ID). Two people could visit your site the exact same number of times and get counted as 3 "users" in one tool and 5 in another purely because of how sessions get stitched together.
Installs vs. sales: App Store Connect reports "units" which include reinstalls, family sharing redemptions, and promo codes depending on the report type you pull. Play Console's install reports have their own quirks and — as covered in why Google Play install reports lag by days — a reporting delay that has nothing to do with definitions and everything to do with processing lag.
Processing lag vs. definition mismatch
It helps to separate two distinct causes of "the numbers don't match":
- Definition mismatch — the tools are correctly reporting different things. This gap is permanent; it won't close if you wait longer.
- Processing lag — the tools are trying to report the same thing, but one of them hasn't finished settling yet (webhook backlog, app store batch processing, ad network attribution windows). This gap closes on its own, usually within 24-72 hours.
The mistake most founders make is treating lag as if it were a definition problem — reconciling by adjusting formulas, when the real fix is just waiting a day and re-checking. Conversely, treating a genuine definition mismatch as lag means you'll keep expecting numbers to "catch up" that never will, because they're not measuring the same thing.
A practical rule: if two tools disagree on a metric they both claim to calculate the same way (e.g., two revenue tools disagree on gross Stripe charges), suspect lag first. If two tools disagree on a metric that's fundamentally defined differently (Stripe gross revenue vs. RevenueCat subscriber-state MRR), stop trying to make them match daily — match them monthly instead, where noise averages out.
What to actually reconcile, and what to leave alone
Not every discrepancy is worth chasing. Here's a rough triage:
- Leave alone: Sub-5% daily variance between GA4 and PostHog session counts. This is baseline noise from session logic and bot filtering.
- Leave alone: Stripe vs. RevenueCat MRR differing by a percent or two on any single day. Check the monthly trend instead.
- Investigate: A sudden multi-day divergence that wasn't there last week — that's usually a broken webhook, an expired API key, or a connector that silently stopped syncing.
- Investigate: App store sales reports that are off by an order of magnitude, not a rounding amount — that's almost always a currency conversion or report-type mismatch (units vs. proceeds), not measurement noise.
If you run more than two or three products, doing this triage manually across every tool, every day, becomes the actual time sink — which is the gap SoleOS tries to close: it pulls Stripe, RevenueCat, GA4, Search Console, App Store Connect, Play Console, PostHog, Firebase, and Supabase into one place on a normalized daily cadence, so at least the "which timezone is this even in" question stops being manual detective work every morning. (Disclosure: this is the SoleOS blog writing about its own space — take the comparison with that in mind.)
You don't need SoleOS, or any paid tool, if you run one product and check numbers inside the native dashboards a couple times a week — the definitions above are the same whether you pay for aggregation or not, and a well-labeled spreadsheet can hold the same reconciliation notes for free. Where it starts to matter is when you're doing this across five, ten, fifteen projects and the timezone/definition triage above needs repeating for each one, every day.
How to build a reconciliation habit
A few practices make this less painful regardless of what tools you use:
- Standardize your timezones where you can. Set Stripe, GA4, and any dashboard settings to the same timezone, even if it's not your local one. Consistency beats "correctness."
- Pick one source of truth per metric type. Stripe for cash that actually moved. RevenueCat (or your store's own reporting) for subscription state. GA4 or PostHog for behavioral traffic — not both, unless you're actively debugging a discrepancy between them.
- Reconcile monthly, not daily, for anything estimate-based. MRR, projected revenue, and session-based user counts are all better trusted at a monthly grain.
- Know exactly what each connector reads. Understanding scopes and refresh cadence removes a lot of "is this stale or just different" confusion — see what SoleOS connects to for an example of the level of detail worth having for any tool you connect. The metrics dictionary approach — writing down the exact formula behind every number you track — pays for itself the first time you're debugging a mismatch at 11pm.
None of this eliminates discrepancies. It just makes them boring and predictable instead of a monthly panic.
Frequently asked questions
Which tool should I trust when Stripe and RevenueCat disagree?
Trust Stripe for cash that has actually moved (charges, refunds, payouts). Trust RevenueCat for subscription state — active subscribers, trial conversions, and MRR as a projection of recurring value. They're answering different questions, so "trusting" one over the other is the wrong frame; use each for what it's built for and expect them to diverge on any single day.
Why do GA4 and PostHog show different visitor counts for the same day?
They use different session timeout windows, different bot/crawler filtering, and different rules for merging anonymous and identified users. A 10-20% gap is common and not necessarily a sign either tool is broken — it's a sign they define "a visit" slightly differently.
Should I change my timezone settings to make numbers match?
Setting all your tools to the same timezone (UTC is a common choice) removes one entire category of mismatch and is worth doing once, early. It won't fix definition-based gaps like Stripe revenue vs. RevenueCat MRR, but it removes the noisiest, most confusing source of daily disagreement.
How long should I wait before treating a gap as a real problem?
Give processing lag 24-72 hours to resolve before investigating. If a gap persists past that window, or widens instead of narrowing, check for a broken webhook, expired API key, or connector that stopped syncing — that's a real problem, not measurement noise.
Does running more products make reconciliation harder?
Yes, linearly at least. Each additional app can have its own Stripe account, its own GA4 property timezone, and its own RevenueCat project, so the number of timezone/definition combinations you're mentally tracking multiplies. This is exactly the kind of grind that the case for the portfolio approach has to survive on real numbers to be worth it — reconciliation overhead is one of the real costs of running more than one thing at a time.