Skip to content

feat(docs): cookieless first-party docs-site analytics (no 3rd party) - #40

Open
ProjectBay wants to merge 1 commit into
mainfrom
feat/docs-analytics
Open

feat(docs): cookieless first-party docs-site analytics (no 3rd party)#40
ProjectBay wants to merge 1 commit into
mainfrom
feat/docs-analytics

Conversation

@ProjectBay

Copy link
Copy Markdown
Owner

What

Adds cookieless, first-party traffic analytics for the docs site — no
third-party services
. The Docusaurus site sends an anonymous beacon on each
pageview to a tiny collector you run on your VPS; it stores aggregate counts
in SQLite and serves a small stats dashboard.

Two pieces:

  • apps/docs-analytics/ — a small standalone Node/TypeScript service (one
    dependency: better-sqlite3). Endpoints: POST /collect, GET /stats (HTML
    dashboard), GET /stats.json, GET /health. Ships with a Dockerfile +
    docker-compose.yml + README for a one-command VPS deploy.
  • apps/docs — a cookieless clientModule beacon + config wiring. It's a
    complete no-op unless the docs are built with DOCS_ANALYTICS_URL set, so
    local dev and PR/preview builds never phone home. deploy-docs.yml passes it
    from a DOCS_ANALYTICS_URL repo variable (unset ⇒ nothing changes).

Privacy

No cookies, no localStorage, no fingerprinting, no PII at rest, honors
navigator.doNotTrack. The client IP + User-Agent are combined with a per-day
rotating salt
and SHA-256 hashed into a visitor id used only for daily
de-duplication — the raw IP is never stored, and the daily salt rotation means
a visitor can't be correlated across days. GDPR-friendly with no cookie banner.
Footprint: one small Node process + a SQLite file (no Postgres/ClickHouse).

Verified locally

  • Collector: npm install + tsc build clean (0 vulns). Ran it and exercised
    every path — /collect204, real beacons aggregate correctly
    (views=3, uniques=2), query strings stripped from paths, referrer hosts
    extracted, bot UA dropped from stats, oversized body → 413, /stats
    without token → 401, with token → HTML + JSON.
  • Docs: npm run build succeeds with the beacon wired in; the runtime global
    is injected into the built HTML only when DOCS_ANALYTICS_URL is set.

To turn it on

  1. Deploy the collector on the VPS (apps/docs-analytics/README.md), behind your
    TLS reverse proxy, with a STATS_TOKEN.
  2. Set the DOCS_ANALYTICS_URL repository variable to the collector's
    /collect URL. The next docs deploy activates the beacon.
  3. View traffic at https://<collector-host>/stats?token=<STATS_TOKEN>.

Until step 2, this changes nothing user-facing — the beacon stays dormant.

🤖 Generated with Claude Code

Add a self-hosted, cookieless pageview analytics stack for the docs site:

- apps/docs-analytics/: a small standalone Node/TS collector (better-sqlite3),
  with POST /collect, GET /stats (HTML dashboard) + /stats.json + /health, and a
  Dockerfile/compose/README for a one-command VPS deploy. Privacy-first — client
  IP+UA hashed with a per-day rotating salt (raw IP never stored), no cookies, no
  PII, DNT-respecting, bounded retention.
- apps/docs: a cookieless clientModule beacon + config wiring; a complete no-op
  unless built with DOCS_ANALYTICS_URL, so dev/PR builds never phone home.
- deploy-docs.yml: pass DOCS_ANALYTICS_URL from a repo variable (unset ⇒ no-op).

Verified locally: collector build clean + every endpoint exercised (ingest,
aggregation, bot-filter, size limit, auth); docs build succeeds with the global
injected only when DOCS_ANALYTICS_URL is set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant