How Nora Lab tests analytics tools
Nora Lab is the research team at Nora Analytics. Every comparison on this site carries numbers we measured ourselves; this page says how, what the tests cannot see, and who we are.
The four visitors the lab sends to every tool, each on its own test page.
Who writes these pages
Nora Lab is the research team at Nora Analytics, and we make Nora Analytics, one of the tools we compare. That is a reason to read us with care, so we work to three rules. Every number we measured comes from the lab below, run the same way for every tool. Every fact about another tool links to that tool's own page. And every comparison says when the other tool is the better choice.
Each page also says, at its foot under "How we tested this", exactly what ran for that page: the tools, the browser and its version, the visitors, the blocklist version, the dates, and what we did not test. No maker paid to be included, and our links to other tools are not affiliate links.
If we got something wrong, write to hello@noraanalytics.io and we will correct the page and say what changed.
The tracker lab
Each tool is installed alone on its own test page, with its maker's install code and a made-up site ID. The one exception is Microsoft Clarity, which loads nothing for a made-up project, so the lab uses Clarity's public demo project. Each page is then opened in Chrome 155.0.8059.79 on a Mac by four kinds of visitor.
The lab answers every request a script makes, other than downloading the script itself, with an empty reply, and writes it down. When a browser first asks permission to send to another site (a CORS preflight), the lab grants it, so the real request follows. Apart from the script itself, nothing passes between the page and the tool's maker. That keeps test traffic out of anyone's dashboard, and it means the lab sees what happens in the browser and not what a maker's servers do afterwards.
For each tool and each visitor, the lab records:
- the scripts the page downloaded;
- every request sent while the page was open and as it was left, and which of them carried the page view;
- the cookies, localStorage and sessionStorage left in the browser.
Script weight is each script fetched once and compressed with gzip at level 6, the usual server setting, so every tool is weighed the same way. Where a tool loads a small loader that then fetches its main script, both count. A real site's script can differ a little: Brotli compression is a few percent smaller, and some tools build the script from the site's settings.
The last run was on 13 October 2026. The raw results are here as JSON.
The four kinds of visitor
| Visitor | What it is | What it stands for |
|---|---|---|
| A person | Chrome, driven by our script like the others, with a normal user agent and a 1440×900 laptop screen; the mouse moves across the page and it scrolls | Someone reading |
| Automated Chrome, as shipped | Headless Chrome driven by a script, saying so: "HeadlessChrome" in its user agent and navigator.webdriver set | Scrapers, test runners and monitoring that make no effort to hide |
| Automated Chrome, disguised | The same browser with its tells removed: a normal user agent, client hints and screen size, webdriver off; it never touches the page | Scrapers and fake traffic that pass as Chrome |
| Disguised, clicking without moving | The disguised browser clicks a point on the page with no pointer movement before the click | How AI agents such as ChatGPT agent, Atlas and Comet click: straight onto the target |
What the lab cannot see
- What happens on the maker's servers. A page view a script sends can still be dropped later, by a user-agent list or a list of data-centre addresses. The lab says "sent", never "counted". It ran from a home internet connection, so lists of data-centre addresses would not have caught any of the four visitors.
- Real AI agents. The fourth visitor copies the way agents click; it is not ChatGPT agent itself. Agents change month to month.
- Crawlers that do not run JavaScript. GPTBot, ClaudeBot and most search crawlers fetch the page without running its scripts, so no script-based tool sees them, Nora included. Seeing them needs server or CDN logs.
- Scale. One run, one browser, one machine. It shows what each script does, not how often.
Facts about other tools
Prices, features, hosting and limits come from each maker's own pricing pages, documentation, changelogs and public code, read on 13 October 2026. Each comparison lists its sources at the foot of the page. Prices are in US dollars, billed monthly, at about 10,000, 100,000 and 1 million page views a month; where a tool counts something else, such as events, the page says so.
What users say comes from public reviews and discussions: ratings on review sites with their number of reviews and the date we read them, and the praise and complaints that recur across several sources. We summarise in our own words and link to where it was said.
We recheck every comparison each quarter, and sooner when a maker changes something.
How Nora labels a page view
Nora gives every page view four tests: a signature check (signed requests, as Web Bot Auth defines them), the name the browser gives, how it behaves on the page, and signs of a machine such as a headless browser or a browser whose parts disagree. Each page view is then a person, an AI agent or a bot, and the dashboard shows which test caught each agent and bot. Nothing is dropped: a page view Nora is unsure of is counted, and its label can be checked.
The lab ran Nora's script like every other tool's and applied Nora's rules to what it caught. Nora counted the disguised browser that never touched the page as a person. No test in the browser can tell that one from a reader who does not move, and we say so wherever it matters.
Changes
13 October 2026. First run of the lab: 11 tools, four kinds of visitor.
13 October 2026, later. The first run showed that EasyPrivacy blocked Nora's own page views: its
script sent them with sendBeacon, which browsers mark as a "ping", and the list blocks every ping sent to
another site. Nora's script 1.5 sends them with fetch instead. We ran the lab again; every other tool's
result was unchanged.