Adjet

Three blind spots in your stats, and what is hiding in the gap

Google Analytics shows you the people who clicked accept. Everyone else is missing, without a trace. On top of that come two groups that did not exist in 2020: AI crawlers reading your text, and people arriving from ChatGPT or Perplexity. As of today our ad plugin counts both.

There is one number nearly every site owner knows and almost nobody questions: users over the last seven days. It sits in the report, gets passed along, ends up in proposals and media kits. And it does not describe your website's visitors, it describes a subset of them.

Blind spot 1: everyone who declined

The mechanism is simple. Analytics only loads after consent, so it only counts those who consented. Anyone declining, dismissing the banner or running a blocker leaves no trace.

On large publishers Google compensates for part of this statistically, which it calls modelling. That does not apply to small sites: below roughly a thousand events per day nothing is modelled. The gap does not become an estimate, it becomes nothing at all.

Nobody can tell you how big that gap is in general, because acceptance rates depend on audience, banner design and subject. Which is why the only sensible answer is to measure it on your own site rather than quote a study.

Blind spot 2: the machines reading along

For two years now a new group has been reading your text, and it appears in no analytics report: OpenAI's GPTBot, Anthropic's ClaudeBot, PerplexityBot, plus crawlers from Google, Microsoft, Meta, Apple, ByteDance, Amazon, Common Crawl and Mistral. They execute no JavaScript, so as far as an analytics script is concerned they do not exist.

This is more than a curiosity. If you want your content to appear in answers, the first question is whether it gets read at all, and the second is which pages. Both are answerable server-side, because these crawlers identify themselves.

Blind spot 3: visitors an AI sent you

The counterpart: people arriving from ChatGPT, Perplexity, Claude, Copilot or Gemini. Analytics does count them, but it drops them into the same bucket as a forum link, somewhere between Pinterest and an email signature.

For the question of whether content pays off with answer engines, that is precisely the interesting channel. It deserves its own line, per day and per landing page.

What Sonar does with that

Since version 2.6.0 our ad plugin carries a tab of its own closing these three gaps, plus a check that logically belongs beside them. Everything stays in your database and nothing calls out.

The counting

A script under two kilobytes runs once the page has finished loading. Because it executes in the browser, it counts pages served from a cache too, which server-side counters routinely miss.

Unique visitors come from a hash of address and browser signature, salted with a random value discarded at midnight. After that the attribution cannot be reconstructed, not by us and not retroactively. The address itself is never written down.

The crawlers

44 identifiers, detected server-side, grouped by vendor and by the pages actually fetched. A visitor who is not a crawler causes no database work at all.

The referrals

Visits from eleven AI assistants are tracked as their own channel, per day and landing page. No other referrer is stored, so no general referrer database accumulates as a side effect.

The consent check

For first-time visitors who have not decided yet, Sonar looks at whether a full analytics or pixel request went out, and names the host. Red means a full hit, yellow a cookieless Consent Mode ping, green nothing sent. Why this is such a widespread problem, and the four causes behind it, is covered in our piece on tracking before consent.

The dark figure

You enter the last seven days' user count from Google Analytics by hand, Sonar puts its own count beside it and works out the factor, along with your banner's acceptance rate. Without your input nothing is estimated. That is deliberate: a guessed dark figure would be exactly the mistake this whole tab exists to avoid.

What Sonar cannot do

Three limits, stated in the plugin next to every number and therefore stated here:

  • Visitors with script blockers are missing. They are not estimated and not extrapolated. They are absent, and the tab says so at the number.
  • Behind a page cache the server only sees the crawler requests that miss it. Crawler figures are a lower bound, not a complete census.
  • The consent check is a check, not a watch. In the free version you see the finding in the admin. There is no permanent guard that emails you.

Also not built, however obvious it may sound: an automatic Google Analytics connection, an import from server log files, a per-page reading map. They are planned, but they do not exist, and while they do not exist they will not be described here.

Why this sits in an ad plugin

Fair question. The answer has to do with how it started: Sonar came out of a measurement in which we checked 40 websites for whether they send data before consent. Going through the results, it became clear that the actual question never gets asked, namely who was there in the first place and who is missing from the report.

Anyone serving ads needs that number anyway. An ad is shown to every visitor, including the one who declined the banner. If your reach figure comes from Analytics while the ad reaches everyone, report and reality diverge, and not in your favour.

Trying it

Sonar is part of Hafenstudios Ads from version 2.6.0, free in the WordPress directory. After activation it takes a day or two before the numbers mean anything, because counting starts when you switch it on and nothing is reconstructed retroactively.

The most honest first step is a different one, though, and it costs two minutes: check whether your site sends anything before your visitors have decided. How to do that is here.

Back to blog A post by hafenstudios