I built vigie — cookieless web analytics where the primary consumer is an AI agent, not a human staring at charts.
The premise
Every privacy-first analytics tool (Plausible, Fathom, Rybbit) assumes a human logs into a dashboard. My team is agents: they write the code, send the email, file the issues. They need analytics they can query and act on — JSON on stdout, semantic exit codes, a machine-readable API.
vigie stats overview --site example.com --since 7d
# {"ok":true,"data":{"pageviews":1234,"visitors":410,"bounce_rate_pct":38,...}}
vigie stats cities --site example.com # geo down to city + coordinates
vigie stats journeys --site example.com # the sankey, as JSON
vigie stats vitals --site example.com # LCP/FCP/CLS/INP/TTFB p50/75/90
When a human needs to see it
The dashboard is an artifact: vigie snapshot --publish renders every metric (22 sections — journeys, channels, heatmap, vitals, errors, geo to city…) into one self-contained HTML page and publishes it to an artifact host. Regenerated on a timer, never stale, no frontend server to run. Fully-populated demo report here (synthetic data, labeled).
And one indulgence: your traffic as a living 3D globe — hand-rolled canvas math, city-level dots, repaints itself from the live feed. Zero JS frameworks.
The interesting constraints
-
Cookieless by construction: visitor =
sha256(secret + day + site + ip + ua), daily salt rotation, raw IP never stored. Nothing to consent to. -
Agents are users too:
vigie track --name deploy --actor cirecords server-side events — your cron job is a first-class analytics stream. - One ~300 KB binary (HTTP ingest + SQLite + stats engine + globe renderer + CLI), written in MFL, no Node/ClickHouse/Docker.
- Geo without a SaaS: a MaxMind-DB (.mmdb) reader written from scratch in MFL, reading DB-IP City Lite (CC BY). ~300 lines for the binary tree walk + data-section decoder.
An agent built the whole thing in a day, and found three compiler bugs in the process — including string literals silently corrupted by C trigraph processing (?? became ^ in the globe JavaScript, surfacing as a browser SyntaxError three layers away).
Full story: https://blog.intrane.fr/analytics-with-no-dashboard
Repo (MIT): https://github.com/javimosch/vigie
Top comments (0)