About this project
OpenAnalytics is an open-source web analytics product shipped as a pnpm monorepo, released under AGPL-3.0 and built to be self-hosted on your own hardware. Its stated design is privacy-first, cookieless measurement with aggregate-only reads: no cookies, no fingerprinting, no cross-site identifiers, and raw IP addresses are never stored. Visitor identity is a salted hash that rotates every night, so a visitor trail is as long as a visit and never as long as a person. Do Not Track and Global Privacy Control are honored at the collector before anything is written, and city-level geolocation is opt-in per site, resolved against a database on the host so no lookup leaves the machine. A hosted instance operated by the authors runs the same code at getopen.so.
The monorepo splits the product into separate applications: a small browser tracker snippet whose byte budget is enforced by CI; a collector that validates, sanitizes, rate-limits and enqueues; a worker that drains the queue into ClickHouse and handles sessions, rollups, exports, mail and deletions; an api control plane covering auth, sites, keys, sharing, event definitions, funnels, widgets, revenue, an AI assistant and an MCP server; a query gateway that is the only process permitted to read ClickHouse and that verifies Ed25519-signed query envelopes; a realtime app providing the SSE stream behind the live dashboard; a Next.js dashboard; and an `oa` CLI for site setup, stats and device-flow login. Shared packages cover domain logic, Postgres and ClickHouse schemas with migrations, Redis/Valkey, auth, OpenAPI contracts, observability and integrations.
Storage is split three ways: Postgres for the control plane, ClickHouse for events and rollups, and two Valkey instances — one durable event queue and one disposable realtime cache. Reported functionality includes page views, custom and attribute-driven events, sessions, web vitals, funnels, per-site retention, embeddable widgets, public share links, revenue analytics from your own Stripe account, CSV/JSON import and export, an MCP server and the CLI. The dashboard also shows a realtime visitor list taken from a presence cache, per-visitor journey trails, and an optional live globe of city-level locations.
Several architectural rules are enforced by CI rather than convention: the web app may import only the shared contracts package, with the OpenAPI document as the single seam between frontend and backend; ClickHouse is reachable only through the query gateway; a change that exceeds the tracker size budget fails the build; and a CI job asserts against a real database that the Postgres schema contains no billing tables.
Self-hosting is documented in SELF-HOSTING.md, using a generator script and a single `docker compose up -d` with automatic TLS. It calls for a Linux host with Docker, four DNS records (app, api, c and rt subdomains), roughly 4 GB of RAM and 25 GB of free disk. Releases publish ten images to ghcr.io, so installation is a pull rather than a build; arm64 hosts or branch builds compile the images locally instead. `upgrade.sh` moves between releases and takes the snapshot `rollback.sh` needs, since migrations are not reversible and the documented way back is a restore. Running from source requires builds before the compiled migration runners. Only the AI assistant and object storage are optional; unset, those surfaces disable themselves. A CI-style test and verification suite runs without infrastructure.
Geolocation data is not bundled (the README notes it is a 60 MB download that goes stale within a month); a helper script fetches a DB-IP database, used under CC BY 4.0. Contributing happens through pull requests merged directly into this repository, with a one-time CLA that leaves copyright with the contributor. The code is AGPL-3.0, which the README notes obliges anyone running a modified version as a network service to offer the modified source to its users; the project name and the hosted service's domain are not part of the license grant.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.