Know where your visitors come from. Keep the data.
visit-keeper is web analytics you run yourself: pageviews, visitors, bounce rate, sources, UTM campaigns, countries, devices, live visitors and goals with revenue credited to the source that brought the customer. No cookies, no IP stored, a script under 1 KB, one Node process, no database. Free and MIT.
Get your snippet
Set SITES=yoursite.com on the server; beacons for any other hostname are refused. Single-page apps are counted on every route change.
How much disk will it use?
Visitor scratch data is deleted after a day or two; what stays is daily counters. Two years of history for a busy site is still a small file.
Why someone would use this
| Today | Catch | visit-keeper |
|---|---|---|
| Google Analytics | Cookies, consent banners, a heavy script, and your visitors' data lives with an ad company | No cookies, under 1 KB, data stays on your server |
| Plausible, Fathom, Simple Analytics | Good products, billed monthly and by pageviews | No per-pageview fee; you run it and fix it |
| Umami, Matomo | Powerful, but a database to run and keep patched | One process, one JSON file, about 700 lines to audit |
| Server logs and GoatCounter | No campaign or goal attribution by source | UTM, referrers and goals by source in one table |
Run it yourself
git clone https://github.com/Duncan-Haywood/fp-monorepo && cd fp-monorepo/ventures/visit-keeper ADMIN_KEY=$(openssl rand -hex 16) SITES=example.com node server.mjs # dashboard: http://localhost:8080/ (any user, ADMIN_KEY as the password)
One-click Render, Fly.io and Docker paths are in the README. Put it behind HTTPS and set TRUST_PROXY=1 when a proxy forwards the visitor's address.
Questions
Is it really cookie-free? Do I need a consent banner?
It sets no cookies and uses no localStorage on your visitors' browsers. A visitor is a one-way hash of a secret, the UTC date, your site, the IP address and the browser string; the IP and browser string are never written to disk and the hash changes every day, so a person cannot be followed from one day to the next. Whether you still need a notice depends on your country and your lawyer; this is not legal advice.
What does it not do?
No session replay, heatmaps, funnels, cross-day unique visitors or cross-device identity, on purpose. A visitor who returns on another day counts again. Time on site is measured between pages of a visit, so a one-page visit has no duration.
How do I see which source brings paying customers?
Call visitKeeper('signup') or visitKeeper('purchase', 29) when something worth counting happens. The Goals table credits each conversion to the source the visitor arrived with (utm_source or referrer) and shows conversions per visit for that source.
Will ad blockers hide my visitors?
Some block third-party analytics by hostname. Serve the script from a subdomain of your own site (for example stats.yoursite.com) and most do not. Visits from people who block it are simply not counted.
Where does my data live?
In one JSON file on the disk of the server you deploy in your own account. The author runs nothing in between and never sees your traffic.
How is it different from Plausible, Fathom or Umami?
Same idea, a much smaller footprint: one Node process, no database, no dependencies, about 600 lines to read. In exchange you get fewer features and you run it yourself. If you want a managed service, those are good choices.