Skip to content

Repository files navigation

Skopia

Open-source, cookieless web analytics you deploy to your own Cloudflare account — the privacy-first Google Analytics alternative with nothing to run.

Skopia — from the Greek skopeín, "to observe."

License Live demo

Skopia's overview dashboard — pageviews, visitors, top pages, sources, and devices for a live site, rendered with real traffic, not mock data

  • Cookieless visitor counting, no cookie banner — a daily-salted HMAC identity, not a persistent ID. How it works →
  • A 554 B gzipped tracking script (≤ 2 KB budget) — src/script/skopia.ts, verified by scripts/check-script-size.mjs, run via pnpm run ci.
  • Public, read-only share links — full dashboard views anyone can open logged-out, cached at the edge. Mint one →
  • Custom events with low-cardinality props, capped at 512 bytes. Docs →
  • Multi-site in one deploy — each site gets its own live count, origin allowlist, and share link. Docs →
  • Everything lives in your Cloudflare account — Workers, D1, KV, Durable Objects, Workers Analytics Engine. Nothing calls home to the Skopia project, enforced by scripts/check-no-external.mjs, run via pnpm run ci.

Deploy

Deploy to Cloudflare

One click provisions D1, KV, the SiteLive Durable Object, and a Workers Analytics Engine dataset into your own Cloudflare account, then prompts for four secrets. The full walkthrough — secret generation, the CLI alternative, local dev — lives in the install guide.

Custom domain (optional)

By default your deploy is reachable at https://skopia.<your-subdomain>.workers.dev. To serve it on your own domain, add a Custom Domain to the Worker — Cloudflare provisions the DNS record and TLS certificate automatically. The domain must be in the same Cloudflare account.

  • Dashboard: Workers & Pages → your skopia Worker → Settings → Domains & Routes → Add → Custom Domain, then enter your domain (apex or subdomain).

  • Config: or add a route to your own wrangler.jsonc and redeploy:

    "routes": [{ "pattern": "analytics.example.com", "custom_domain": true }]

Keep your own domain out of the upstream wrangler.jsonc if you plan to send PRs — the committed config stays domain-agnostic so the one-click deploy works for everyone.

Limitations

Skopia trades some things for running cookieless and entirely on Cloudflare. These are owned tradeoffs, not oversights:

  • WAE sampling. Workers Analytics Engine — the raw event store — adaptively samples queries at high per-site volume. Skopia's daily numbers avoid this: a per-site Durable Object writes exact, unsampled aggregates to D1 on every event (ADR-0011); only an ad-hoc query against raw WAE data is still subject to WAE's own sampling.
  • 90-day raw retention. Cloudflare caps raw Workers Analytics Engine data points at 90 days — a platform limit, not a Skopia setting. The daily D1 rollups aren't subject to that cap and become your durable long-range history once the raw window rolls off (privacy.md §4).
  • What daily-salt identity can't tell you. The cookieless visitor hash rotates every UTC day, so Skopia can report same-day, same-site uniques but never true monthly unique-visitor counts or cross-day conversion attribution (e.g. "visited Monday, converted Thursday") — see privacy.md §3.
  • The Cloudflare dependency. Skopia is self-deployed on your own Cloudflare account, not vendor-neutral software — Workers, D1, KV, Durable Objects, and Workers Analytics Engine are all Cloudflare primitives. If you need a different cloud, this isn't that.

Install

Add the tracking snippet, verify it, track multiple sites, and send custom events — see the install guide.

Documentation

  • Install guide — add the tracking snippet, verify it, track multiple sites, send custom events, public share links.
  • Privacy & data collection — exactly what is and isn't collected, and what the daily-salt identity mechanism cannot tell the site owner.
  • Contributing — dev setup, conventions, the tracking-script budget.
  • Security policy — how to report a vulnerability; the security model.
  • Architecture decisions — the ADRs behind the design.

Tech stack

  • Cloudflare Workers — a single Worker serves the collector, the dashboard, and the public share surface.
  • D1 (SQLite) — sites, users, and daily rollups (migrations/).
  • Workers KV — the response cache and the daily identity salt.
  • Durable Objects (SiteLive) — event-driven live counts and the unsampled rollup_daily writer (ADR-0011).
  • Workers Analytics Engine — the raw, 90-day event store.
  • Hono — routing, in the same Worker as everything else.
  • TypeScript, strict mode. Tests: Vitest with @cloudflare/vitest-pool-workers. Lint/format: Biome.

Repository layout

.claude/agents/   PM + tech-lead agent definitions
design/           Frontend design system (Claude Design source — visual/behavioral spec)
docs/assets/      README/marketing screenshots
docs/research/    Deep-dive research (competitive analysis, Cloudflare architecture)
docs/specs/       Approved design specs
docs/decisions/   Architecture Decision Records (ADRs)
public/           Static assets shipped with the Worker (fonts + vendored jsVectorMap)
src/              Worker source (TypeScript strict)
CLAUDE.md         Operating contract for agents/humans in this repo

Contributing

See CONTRIBUTING.md for dev setup, conventions, and the tracking-script budget rules.

License

AGPL-3.0. Chosen to keep every feature open and unlocked while preventing a closed-source SaaS fork — see docs/specs/2026-06-21-product-spec.md §6.

About

Privacy-first, Cloudflare-native web analytics you self-host on your own Cloudflare account. No cookies, exact rollups from a Durable Object, 554-byte tracker. AGPL-3.0.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages