Blog

Ad blockers hide part of your analytics. How to measure it and serve analytics first-party

If your audience is developers, designers or anyone tech-savvy, a noticeable share of them run an ad blocker. Most blockers don't only hide ads: they also stop analytics scripts from loading. Those visitors don't show up in your dashboard at all, so you under-count traffic and the gap differs by channel.

Why analytics gets blocked

Blockers such as uBlock Origin, AdGuard and the built-in shields in Brave use filter lists. Lists like EasyPrivacy contain the domains and paths of common analytics tools. When the page asks for a script from a listed domain, the request is simply cancelled.

The lists match on the request URL, not on what the script does. That's why the same script, served from your own domain under a neutral path, usually loads fine.

How much are you missing?

It depends heavily on the audience. Mainstream consumer sites lose a small share; developer tools and tech blogs often lose much more. Rather than trusting someone else's average, measure your own:

  1. Compare with server logs. Count page requests from real browsers in your web server or CDN logs for one day and compare with the pageviews in analytics. Logs include bots, so filter obvious crawlers first. This gives a rough upper bound.
  2. Run both for a week. Keep the normal script and add a proxied copy on the same pages (with a separate site, so the numbers don't mix). The difference between the two is your blocked share.
  3. Look by channel. Visits from Hacker News, GitHub or Reddit are typically blocked far more often than visits from Google Search. If your analytics says "developers don't come from Hacker News", check this first.

The fix: serve the script first-party

A first-party proxy makes your own domain forward a path such as /pl/* to the analytics provider. The browser only talks to your site, so domain-based lists don't apply. The setup is one rule in most stacks.

Next.js

// next.config.js
module.exports = {
  async rewrites() {
    return [{ source: '/pl/:path*', destination: 'https://app.pagelens.io/:path*' }];
  },
};

Nginx

location /pl/ {
    proxy_pass https://app.pagelens.io/;
    proxy_set_header Host app.pagelens.io;
    proxy_ssl_server_name on;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Cookie "";
}

Then load the script through the proxy:

<script defer src="/pl/script.js" data-site-id="YOUR_SITE_ID"></script>

Two details matter:

Recipes for Cloudflare Workers, Vercel, Netlify and Caddy are in the proxy guide.

Is this OK to do?

A proxy changes where a request goes, not what the law requires. If your analytics sets cookies or builds profiles of people, you still need consent, proxy or not, and hiding a tracker from someone who chose to block it doesn't get you that consent.

The argument for proxying is strongest when the tool itself respects privacy: no cookies, no cross-site tracking, no personal data stored, and no data used for ads. Then you're measuring visits to your own site, which is what most people who install a blocker are fine with. Mention the tool in your privacy policy either way.

Summary

Try PageLens on your site

Create a free PageLens account: 7-day trial, no card, no cookie banner needed.

Start free trial

Keep reading