Vincent Bernat dropped Google Analytics from his blog in 2016 and read his server logs with GoAccess instead. A couple of years ago the numbers stopped making sense, because AI scrapers were pushing his visitor count to around 2,000 a day. He moved to GoatCounter and rebuilt the filter around the one thing scrapers do not do, which is behave like a person.
Only count a real interaction
GoatCounter is open source and self-hostable: one binary, SQLite or PostgreSQL for storage, about 3.5K added to the page, no cookies, and unique visits derived from a non-identifiable hash rather than a stored address.
The bundled client sends a hit when the script loads. Bernat replaced it with a smaller one that only sends a hit after the reader moves a pointer, presses a key or touches the screen. A scraper fetching the page never triggers any of those events, and a crawler running a real browser does not interact with the page either. Readers with JavaScript disabled are counted through a CSS image loaded on hover, which he says covers about 2% of them.
Five servers, one database
The blog is served from five machines and GoatCounter runs on one of them, so each server runs a small local proxy. It buffers hits in memory for days and forwards them in batches to the authenticated count endpoint, so an outage of the analytics instance does not lose traffic. The counting endpoint sits on the blog’s own domain, which gets it past ad blockers. He offered the proxy upstream as pull request #909 and the maintainer declined to carry it, on the grounds that a one-off contribution becomes a long-term commitment. Bernat says he takes the same position with his own projects.
The comparison is the point. Where GoAccess reported around 2,000 visitors a day, GoatCounter counts fewer than 200 humans.
My read
Most of what a log analyser counts was never a person, and requiring an interaction is the cheapest way to find out how much. It is also the only analytics change worth making on a static site, because a hit that needs a human cannot be inflated by anything that reads pages for a living.
Source: Bot-free self-hosted analytics with GoatCounter on NixOS and the GoatCounter repository