Statistics for admins: views, visitors, moderation, accounts (no cookies) #99

Merged
anas merged 1 commits from feature/stats into main 2026-10-09 22:54:20 +00:00
Owner

Closes #86. Owner request: privacy-friendly stats on the admin dashboard (moderation, views, visits).

Admin › اعداد و شمار (/admin/stats, admins only), for 7 days, 30 days, 90 days or a year:

  • Readers: page views and visitors per day (bar chart), the most-read pages (with their titles), and the sites readers came from.
  • Moderation: drafts waiting for review and for publishing, steps taken (created, submitted, approved, published…), the most active moderators.
  • Accounts and library: accounts by role, new accounts, who signed in, saved items by kind, e-books, tags, published versions.

Privacy (no consent banner needed):

  • No cookies, and no addresses are stored.
  • The site reports each reading page to the API without waiting for an answer.
  • The API keeps three kinds of numbers: views per page per day; visitors per day, as a hash of address and browser made with a salt that changes daily and is kept only in memory (it cannot be reversed or followed from one day to the next); and the referring site's domain name only.
  • Not counted: bots and link previews, errors, and private pages (accounts, library, moderation, admin, sign-in, files).
  • Only the site can report views (x-site-key, as for rate limits).
  • The privacy page (رازداری) now says this.

Schema: three new tables (stat_views, stat_visitors, stat_referrers), created by the deploy's schema step.

Tested:

  • New stats.test.ts: hits are accepted only from the site, the counts are right, no addresses are stored, and the dashboard is for admins only. All API tests pass.
  • Checked locally end to end: a browser visit from Google was counted with google.com as the referrer; Googlebot and /account were not counted; the dashboard renders.

Known limit: the salt lives in the API process, so a restart in the middle of a day can count a returning reader twice that day.

🤖 Generated with Claude Code

Closes #86. Owner request: privacy-friendly stats on the admin dashboard (moderation, views, visits). **Admin › اعداد و شمار** (`/admin/stats`, admins only), for 7 days, 30 days, 90 days or a year: - **Readers:** page views and visitors per day (bar chart), the most-read pages (with their titles), and the sites readers came from. - **Moderation:** drafts waiting for review and for publishing, steps taken (created, submitted, approved, published…), the most active moderators. - **Accounts and library:** accounts by role, new accounts, who signed in, saved items by kind, e-books, tags, published versions. **Privacy** (no consent banner needed): - No cookies, and no addresses are stored. - The site reports each reading page to the API without waiting for an answer. - The API keeps three kinds of numbers: views per page per day; visitors per day, as a hash of address and browser made with a salt that changes daily and is kept only in memory (it cannot be reversed or followed from one day to the next); and the referring site's domain name only. - Not counted: bots and link previews, errors, and private pages (accounts, library, moderation, admin, sign-in, files). - Only the site can report views (`x-site-key`, as for rate limits). - The privacy page (رازداری) now says this. **Schema:** three new tables (`stat_views`, `stat_visitors`, `stat_referrers`), created by the deploy's schema step. **Tested:** - New `stats.test.ts`: hits are accepted only from the site, the counts are right, no addresses are stored, and the dashboard is for admins only. All API tests pass. - Checked locally end to end: a browser visit from Google was counted with google.com as the referrer; Googlebot and `/account` were not counted; the dashboard renders. Known limit: the salt lives in the API process, so a restart in the middle of a day can count a returning reader twice that day. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
anas added 1 commit 2026-10-09 22:45:10 +00:00
anas merged commit 4fc4e644d6 into main 2026-10-09 22:54:20 +00:00
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: anas/divan#99
No description provided.