Why do GA4 and PostHog report different visitor numbers?
Last updated: July 24, 2026
From the SoleOS answers series — written about our own product space; grounded in published definitions and documented behavior, never invented numbers.
GA4 and PostHog almost never agree on visitor counts, and that's expected, not a bug in either tool. They define a "user" and a "session" differently, filter bots on different lists, sample and threshold data in different ways, and get blocked by ad blockers and consent banners at different rates. Neither number is more "true" — they're two different measurement methods pointed at the same traffic, so the fix isn't forcing them to match, it's picking one as your source of truth and watching its trend.
This is published by SoleOS, which reads both PostHog and GA4 into one dashboard for solo founders running several products — take the framing with that in mind. If you run a single product and already trust one analytics tool without cross-checking it, you don't need a second tool or a dashboard to reconcile a number you've stopped worrying about.
A different definition of "user" and "session"
GA4 deduplicates a person across devices using a combination of client ID, signed-in user ID, and (if enabled) Google Signals. PostHog identifies a person by a distinct_id that starts as an anonymous device ID and only merges into one person when your code calls identify(). If your app calls identify() late or inconsistently, PostHog will count what GA4 sees as one returning user as two or three separate ones.
Sessions have the same problem. GA4 leans on "engagement": a session generally needs a minimum duration, a conversion event, or several pageviews before it counts as a real, engaged session in most standard reports. PostHog starts a session on the first event and ends it after inactivity, with no engagement bar to clear. A visitor who bounces in three seconds can show up as a session in PostHog and get excluded from GA4's engaged-session count entirely.
Bot filtering doesn't match either
Both tools try to strip non-human traffic, but from different lists and with different aggressiveness. GA4 automatically excludes traffic matching the IAB/ABC international spiders and bots list, which catches well-known crawlers but misses newer scrapers, headless browsers, and AI-agent traffic that doesn't self-identify the old way. PostHog ships its own default bot rules and lets you layer on custom exclusions, but most projects never touch that config. Since the two lists aren't identical, some traffic counts as human in one tool and gets filtered as a bot in the other — and that gap shifts with whatever happens to be crawling your site that week.
GA4 samples and thresholds your data
Beyond bot filtering, GA4 has two behaviors that intentionally shrink or obscure numbers that PostHog doesn't apply: sampling and thresholding. Ad hoc GA4 Explore reports can sample from a subset of events on higher-traffic properties rather than reading every event, and GA4 also thresholds — quietly withholding or aggregating rows when a segment gets too small, as a privacy safeguard, more aggressively if Google Signals is on. PostHog is generally reading every captured event for the queries most solo founders run. That structural difference alone can push GA4's number below PostHog's on identical underlying traffic.
Ad blockers and consent banners hit both — differently
Both tools are client-side JavaScript, and both get blocked — just by different mechanisms and at different rates. google-analytics.com and googletagmanager.com are explicit targets in mature filter lists like EasyPrivacy, so a meaningful share of privacy-conscious visitors — anyone running uBlock Origin, Brave's shields, or an iOS content blocker — never sends GA4 a single hit. PostHog's default script is a less universally recognized target, and many teams route it through a first-party reverse proxy specifically to dodge that blocking, which can let it capture visitors GA4 never sees.
Consent banners add a second filter. If a cookie tool gates analytics behind an accept click, GA4's behavior is usually tied to Google's own consent-mode signals, while PostHog's gating is whatever your CMP integration was actually wired to do. Those rarely match, so the share of visitors lost to "declined or ignored the banner" differs between the two as well.
Cookies vs cookieless identity
GA4 leans on first-party cookies (_ga and friends) plus, optionally, Google Signals for cross-device identity. PostHog defaults to a device-scoped identifier in local storage or a cookie you control, merged into a real person only through your own identify() calls. Cookie lifetimes differ too — Safari's Intelligent Tracking Prevention caps script-set cookies at seven days, eroding long-window identity resolution for both, but not by the same amount. The same real visitor can end up looking like one person in one tool and several in the other, in either direction, depending on your traffic's device mix.
Timezones and session windows
GA4 reports against whatever timezone your property is configured for; PostHog reports against your project's timezone setting, which is easy to leave on UTC by default. A visit at 11:50pm local time can land on different calendar days in each tool, shifting daily and monthly totals near the boundary — a real effect, not a data-quality problem, but easy to mistake for one. Session-window definitions compound this: a session running past midnight can split into two in one tool and stay whole in the other, changing session counts without changing the actual number of visitors.
Processing delays
GA4's standard reports aren't final the moment traffic happens — data keeps settling for a day or two as GA4 finishes processing, deduplicating, and thresholding. PostHog's live event stream shows up close to real time, though your own dashboards may carry their own refresh lag. Compare a PostHog number pulled this morning against a same-day GA4 report pulled at the same moment, and you're comparing a fully matured number against one still finishing.
Neither number is wrong
Every reason above points to the same conclusion: GA4 and PostHog are two different rulers, each with its own starting point, rounding rules, and blind spots. Neither is auditing the other. Expecting them to converge on an identical visitor count is like expecting a pedometer and a GPS watch to report the exact same distance for the same run — both are reasonable, both are internally consistent, and both will be a little off from some true value neither can actually see. A gap in the rough range of 10-30% between two analytics tools measuring the same traffic is common and, on its own, tells you nothing is broken.
The practical rule: pick one source of truth, then watch the trend
Trying to reconcile GA4 and PostHog down to the exact same number is a losing game — you'll spend hours chasing a discrepancy with six legitimate causes and no single fix. The more useful approach: designate one tool as the system of record for a given product, then use it consistently for every trend line, growth claim, and week-over-week comparison. The other tool stays useful as a directional sanity check — did it move roughly the same way — not as a number you reconcile line by line.
This matters more once you're running several products and comparing growth across them, where consistency of measurement beats precision of any single count — covered in more depth in why obsessing over the exact visitor number misleads solo founders. If you're still deciding how to set up tracking, a simple weekly routine for checking your numbers without overthinking them covers the setup side of the same discipline. If you're tracking multiple products and want one place that plots the trend line instead of forcing two tools to agree, that's what SoleOS's metrics view is built around, alongside guides for wiring up each data source the first time.
Frequently asked questions
Which tool should I trust as my source of truth?
Whichever one you set up first, understand best, and check most often. Consistency matters more than which vendor you pick — switching your source of truth back and forth is what corrupts a trend line, not the underlying gap between GA4 and PostHog.
Is a 20-30% gap between GA4 and PostHog a sign something's broken?
Not on its own. Given the differences in bot filtering, sampling, ad-block exposure, and identity resolution covered above, a gap in that range is normal for two independently instrumented tools. Look for a broken setup only if the gap suddenly widens or narrows sharply week over week, or one tool reports a hard zero.
Can I configure GA4 and PostHog to match exactly?
You can close part of the gap — proxying PostHog through your own domain, tightening bot filters, calling identify() earlier and consistently, aligning both tools' timezones — but you can't eliminate GA4's sampling and thresholding, and you can't force every visitor's browser to treat both scripts identically. Treat a smaller gap as a side effect of good instrumentation, not a target.
Does a reverse proxy fix the discrepancy?
It changes it rather than fixes it. Proxying PostHog (or GA4) through your own domain reduces ad-block interception for that tool, which typically pulls its count up relative to the other. That's a legitimate reason the gap moves, not proof the two tools have converged on the "real" number — there is no single real number to converge on.
Should I just drop one of the two tools?
Only if you're not using it. If GA4 gives you search-console-linked acquisition data, or PostHog gives you product events and session replay the other lacks, keep both and use each for what it's good at, while treating one as the headline number you report against.