I've been running a side-by-side test of Fathom against my existing analytics setup for the past 30 days. The core data matches up for North American traffic, but EU visitor counts are consistently 20-30% lower in Fathom. This isn't a rounding error.
My setup:
* Primary site is hosted on Cloudflare Pages, with a Fathom script installed in the ``.
* I have a separate Matomo instance (self-hosted, EU server) as a control.
* I'm filtering out known bots and internal IPs in both systems.
The discrepancy is significant enough to skew conversion rate calculations for that region. Before I dig into my own code, I need to rule out a platform or config issue.
Has anyone else validated EU traffic counts and reproduced similar gaps? Specifically:
* Are there known issues with certain EU ad-blockers or privacy browsers (like Brave) not executing the Fathom script?
* Does Fathom's endpoint (`cdn.usefathom.com`) have any geographic latency or blocking problems?
* Is there a recommended way to verify script firing that doesn't rely on their dashboard?
I can provide a sanitized comparison of daily aggregates if it helps, but I need to see if this is a known variable or a new bug.
Show me the query.
The CDN endpoint is a solid lead. Fathom uses Cloudfront for `cdn.usefathom.com`. If your Matomo instance is on an EU server, it will have a lower latency connection to EU visitors, making the script less likely to timeout or fail during slow network conditions. The US-based CDN adds 100-200ms for EU users, which can coincide with page abandonment before the script fires.
I'd set up a simple probe using your browser's dev tools or a synthetic monitoring service from an EU region. Check for HTTP status 204 from the script request. You might also see blocked requests if the endpoint is on certain advertiser blocklists used by European privacy tools.
Regarding validation without the dashboard, you can run a local packet trace or use a Cloudflare Worker to log every script fire, then compare that raw log to Fathom's ingested data. That's how I isolated a similar issue with a different analytics provider last year.
Mike
You've eliminated the big config variables already. Let's talk about the real cost of latency, which is what user494 hinted at.
You're comparing a self-hosted EU endpoint (Matomo) to a US-hosted CDN (Fathom). That extra 100ms+ isn't just a number; it's directly in the critical path before `window.onload`. If you have a bounce or a user closing the tab quickly, that script often doesn't fire. A 20-30% drop in a high-latency region lines up perfectly with that.
Before you go down the rabbit hole of blocklists (which is also valid), run the break-even analysis: what's the actual business cost of that missing 30% of EU data? If it's material, then you need a first-party proxy or a different provider with EU endpoints. Otherwise, you're just chasing a ghost in the logs.
Show me the bill
You've already done the right thing by running a parallel setup with a control. The gap is real, and latency from the US CDN is the prime suspect, but let's tackle your specific questions.
Yes, EU privacy tools and browsers are absolutely a factor. Brave's built-in blocklists are aggressive, and many European users run browser extensions like uBlock Origin with regional filter lists (Easylist, AdGuard) that are more likely to flag third-party analytics scripts originating from US CDNs. The lower latency to your Matomo instance makes it slightly less likely to be caught in a race condition against these blockers.
Verifying script firing without the dashboard is straightforward: deploy a one-line Cloudflare Worker on your own domain that proxies requests to Fathom's endpoint and logs every single call. You'll see the exact difference between what your site attempts to send and what actually reaches them. The 30% gap will likely appear as 204s from your proxy that never get a corresponding success from their CDN.
The "bug" is probably just the inherent flakiness of a third-party script hosted a continent away. The real question is whether you need to chase this down, or just accept that your EU data has a known, consistent error margin.
keep it simple