Your Analytics Dashboard Is Missing Half the Story

42% of your visitors are invisible.

That’s how many people use ad-blockers or privacy-focused browsers. And if you’re using privacy-first analytics like Fathom, these tools still block the official tracking script from cdn.usefathom.com—even though you’re not collecting personally identifiable data.

I ran into this exact problem. My analytics dashboard showed decent traffic, but I knew the real numbers were higher. Ad-blockers were killing Fathom’s script before it could fire. Every blocked request meant lost data about site visits and how people actually use my site.

Here’s how I fixed it using Bunny.net’s CDN as a reverse proxy. The solution bypasses blockers completely, costs about $1/month (even for multiple sites), and takes about 10 minutes to set up.

The Problem: Domain-Based Blocking Kills Analytics

Ad-blockers work by maintaining lists of blocked domains. When your browser tries to load a script from cdn.usefathom.com, the blocker checks its list, finds a match, and blocks the request.

It doesn’t matter that Fathom is privacy-first or GDPR-compliant. The blocker sees “analytics domain” and kills it.

This affects more than just Fathom. Plausible, Umami, and any third-party analytics service face the same issue. Even if you’re doing everything right from a privacy perspective, your scripts get caught in the same net as invasive trackers.

The result? Your analytics dashboard becomes less useful. You can’t make informed decisions about content, UX improvements, or conversion optimization when you’re missing data from 42% of your visitors.

What Didn’t Work: DNS URL Forwarding

My first attempt seemed logical: use URL forwarding at my DNS registrar to point ana.mydomain.com to cdn.usefathom.com.

The idea was simple. If I could serve the script from my own domain, ad-blockers wouldn’t recognize it as a tracking script. First-party requests from your own domain don’t appear on blocklists.

I tried this with my DNS provider at the time (freedns.si). It didn’t work.

Here’s why URL forwarding failed for me:

URL forwarding only worked with root URLs. When I requested ana.mydomain.com/script.js, the path got forwarded—but the slash disappeared. The request ended up going to cdn.usefathom.comscript.js (notice the missing slash between the domain and filename).

There was no way to configure it as cdn.usefathom.com/{path} or anything similar. At least not with freedns.si. I don’t know if this is a limitation across all DNS providers, but it was a dealbreaker for me.

DNS forwarding simply doesn’t handle URL paths properly. I needed something smarter.

The Solution: Reverse Proxy Through Bunny.net CDN

The fix is to use a CDN as a reverse proxy. When someone requests ana.mydomain.com/script.js, the CDN fetches the file from cdn.usefathom.com/script.js and serves it under your domain.

This is proper proxying, not just URL forwarding. The full URL path is preserved correctly, and browsers only see your first-party domain.

I use Bunny.net for this. It’s a CDN provider with simple configuration at low cost.

Here’s what makes this work:

Bunny.net creates a “Pull Zone”—a CDN endpoint that fetches content from an origin server. You point the Pull Zone at cdn.usefathom.com, configure a custom hostname like ana.mydomain.com, and the CDN handles the rest.

When a visitor loads your page:

  1. Their browser requests https://ana.mydomain.com/script.js
  2. Bunny’s CDN receives the request
  3. The CDN fetches the script from https://cdn.usefathom.com/script.js
  4. The CDN serves it to the visitor under your domain
  5. Ad-blockers see a first-party request and allow it

The visitor’s browser never directly contacts cdn.usefathom.com. All communication goes through your domain.

Step-by-Step Setup

Want to skip the manual setup? Jump to Automating the Entire Setup for a programmatic approach.

1. Create a Bunny.net Pull Zone

Sign up for Bunny.net (they have a 14-day free trial). Navigate to the Pull Zones section and create a new zone. Give it a descriptive name like ana-mydomain—this name determines your Bunny CDN hostname (ana-mydomain.b-cdn.net), which you’ll need in step 3.

Key settings:

  • Origin URL: https://cdn.usefathom.com
  • Origin Host Header: cdn.usefathom.com

That second setting is important. Bunny marks it as optional, and technically if you leave it blank, Bunny extracts the hostname from the Origin URL automatically.

Here’s why it matters: When Bunny fetches content from the origin server, it needs to send the right Host header in the HTTP request. If this is wrong or missing, Fathom’s servers might not respond correctly. Setting the Origin Host Header ensures Bunny sends Host: cdn.usefathom.com when fetching the script.

You don’t need special caching rules or edge rules. Default Pull Zone settings work fine.

2. Add a Custom Hostname

In your Pull Zone settings, add a custom hostname. This is the subdomain you’ll use—something like ana.mydomain.com or cdn.mydomain.com.

Choose something that makes sense for your setup. The subdomain name can be anything you want.

3. Configure DNS

Add a CNAME record in your DNS settings:

1
2
3
Type: CNAME
Name: ana
Value: ana-mydomain.b-cdn.net

The value follows the pattern <pull-zone-name>.b-cdn.net, where ana-mydomain is the name you gave your Pull Zone in step 1. You’ll also find this hostname in the Pull Zone settings after adding your custom hostname.

The subdomain name (ana) can be whatever you chose in the previous step—cdn, track, etc.

4. Enable SSL

Bunny automatically provisions a free Let’s Encrypt certificate once you add the custom hostname. This usually takes a few minutes to activate.

Check the SSL status in your Pull Zone settings. Once it shows “Active,” you’re good to go.

I recommend enabling “Force SSL” to redirect all HTTP requests to HTTPS. This is just good practice for any modern website.

5. Update Your Script Tag

Replace your existing Fathom script tag:

1
2
<!-- Old: blocked by ad-blockers -->
<script src="https://cdn.usefathom.com/script.js" data-site="YOUR-SITE-ID"></script>

With your proxied version:

1
2
<!-- New: served from your domain -->
<script src="https://ana.mydomain.com/script.js" data-site="YOUR-SITE-ID"></script>

That’s it. No changes needed in your Fathom dashboard. The data-site attribute still identifies your site. Fathom doesn’t care where the script loads from—the tracking calls use relative paths, so they go through the same proxy automatically.

Why This Works

Ad-blockers maintain blocklists of known tracking domains. These lists include cdn.usefathom.com, along with many other domains associated with analytics, advertising, and tracking.

When you serve the script from ana.mydomain.com, the blocker checks its list and finds nothing. Your domain isn’t on any blocklist. The request goes through.

This isn’t about sneaking past privacy protections. Fathom is still privacy-first analytics that doesn’t collect personal data. You’re just ensuring that your own first-party analytics actually work.

It’s the same principle as self-hosting the script on your own server—but using a CDN gives you better performance and easier updates.

Automating the Entire Setup

Clicking through Bunny.net’s dashboard to set up Pull Zones, DNS records, custom hostnames, and SSL certificates gets old fast when you’re managing multiple sites. I needed a better way.

I ended up building a tool that handles this entire process programmatically: bunny-dns-sync.

It’s an open-source Python tool that lets you define your Bunny.net DNS zones, Pull Zones, custom hostnames, and Edge Rules in a JSON configuration file. Use it from the command line or import it as a library in your own scripts. The tool syncs your desired state to Bunny’s API automatically — creating, updating, or deleting resources as needed.

Here’s what a config file looks like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{
    "domains": {
        "mydomain.com": {
            "dns_records": [
                {"type": "CNAME", "name": "ana", "value": "ana-mydomain.b-cdn.net", "ttl": 3600}
            ],
            "pull_zones": {
                "ana-mydomain": {
                    "origin_url": "https://cdn.usefathom.com",
                    "origin_host_header": "cdn.usefathom.com",
                    "type": "standard",
                    "enabled_regions": ["EU", "US"],
                    "hostnames": ["ana.mydomain.com"],
                    "edge_rules": []
                }
            }
        }
    }
}

Run the sync command, and it creates everything: DNS zones, Pull Zones, custom hostnames, and free SSL certificates. No manual clicking. Everything is version-controlled and reproducible.

This is completely optional — the manual setup works fine if you only have one or two sites. But if you’re managing infrastructure as code or running multiple sites, the tool saves a lot of time and prevents configuration drift.

Check out the https://github.com/mrpesho/bunny-dns-sync for installation instructions and full documentation.

Results and Performance

This approach bypasses all domain-based blockers:

  • uBlock Origin
  • AdGuard
  • Pi-hole
  • NextDNS
  • Any blocker using EasyList or similar lists

Performance should be the same or slightly better than loading directly from Fathom’s CDN. Bunny.net has edge nodes globally, so the script loads from whichever server is closest to your visitor.

For a ~2KB gzipped script, latency differences are negligible. I haven’t noticed any performance degradation, and my analytics data is now complete.

What About Costs?

Bunny.net charges by bandwidth. For an analytics script that’s about 2KB gzipped, the cost is extremely low.

A site with 50,000 page views per month uses roughly 100MB of bandwidth for the script. At Bunny’s pricing, that’s well under $0.01/month for the actual bandwidth.

Bunny does have a minimum charge of $1/month if you use their services. But here’s the thing: this minimum is hard to reach even if you have multiple sites running analytics through Bunny. The bandwidth usage is just too low.

This pairs well with Fathom, which allows up to 50 sites per account. You can proxy analytics for all your sites through Bunny and still barely touch that $1/month minimum.

Could This Work for Other Analytics Tools?

I’ve only tested this setup with Fathom and Bunny.net, so I can confirm it works reliably for this combination.

The principle should work for other privacy-focused analytics tools like Plausible or Umami—they face the same ad-blocker issues and use similar script-based tracking. The setup would be identical: point the Pull Zone at their CDN, configure your custom hostname, update your script tag.

The Key Takeaway

Ad-blockers block by domain, not by functionality. Serving Fathom Analytics script from your own domain bypasses blocklists while preserving visitor privacy.

Using a CDN as a reverse proxy is cleaner than self-hosting (the script automatically updates when Fathom releases new versions) and more reliable than DNS-level URL forwarding (which didn’t handle URL paths correctly with my DNS provider). The proxy routes both the script file and all tracking API calls through your domain, so ad-blockers never see requests to cdn.usefathom.com.

The setup takes about 10 minutes. The cost is about $1/month even with multiple sites. And you get complete analytics data from all your visitors—not just the 58% who don’t use blockers.

If you’re losing analytics data to ad-blockers, try this approach. Your dashboards will thank you.


Disclaimers

Privacy and Ethical Use: This technique is for privacy-respecting, first-party analytics (like Fathom, which is cookieless and doesn’t collect personal data). Users have the right to control their browsing experience—bypassing ad-blockers doesn’t exempt you from privacy laws or consent requirements where applicable. Be transparent: disclose analytics usage in your privacy policy and consider adding a footer notice explaining what data you collect and why.

Affiliate Links: This post contains affiliate links to Fathom Analytics and Bunny.net. If you sign up through these links, I may receive a commission at no additional cost to you.

Legal Disclaimer: I’m not a lawyer, and this article does not constitute legal advice. This describes a technical solution I use on my own sites. Consult your own legal counsel about compliance with privacy regulations (GDPR, CCPA, etc.) applicable in your jurisdiction.