Skip to content

feat(drive): first-party usage analytics for admins - #29

Closed
vlidholt wants to merge 1 commit into
mainfrom
feat/usage-analytics
Closed

vlidholt wants to merge 1 commit into
mainfrom
feat/usage-analytics

Conversation

@vlidholt

Copy link
Copy Markdown
Contributor

Summary

An admin-only Analytics page in Wonky Drive (/drive/analytics), built on first-party data in our own Postgres (spec: specs/19-usage-analytics.md).

  • What admins see:
    • accounts and new accounts, active today, weekly and monthly active users, stickiness (average daily ÷ monthly)
    • active users over time (daily, with a Created or edited line, plus weekly and monthly), and active users by app (Drive, Write, Sheets, Slides, MCP clients)
    • sign-ups, content now (items by kind, storage) and sign-in methods
    • content created by kind; collaboration (items shared, co-edited, commenters, comments and shares over time)
    • AI requests and tokens by feature and model, and MCP tool calls
    • weekly sign-up cohort retention
  • Page controls: a 7/30/90/365-day period and an Include admins switch (off by default), both through drive.analytics.show. Every chart has a table view, and the page shows aggregates only.
  • Access: the board's admin rule (board.adminEmailDomains / adminEmails), checked on the server. The left-menu entry only shows for admins (HomeNavItem(adminOnly: true)).
  • Recording: one user_activity_day row per person, UTC day and app; no content.
    • Sources: the apps' ping at start and resume, item opens, creations and edits (via the activity log), and MCP tool calls.
    • Welcome content, scripts and the system don't count.
    • Kept 400 days (daily job analytics.purgeActivity). Tracking never fails the request that triggers it.
  • Database load:
    • Finished days are rolled up once into usage_day_stats, since a past UTC day never changes. The rolling count(DISTINCT) windows therefore run only for today.
    • New indexes: activity_event(type, at), comment(createdAt), drive_item_permission(grantedAt), ai_usage(at) (also serves the purge) and user_profile(createdAt).
    • The overview is cached for 1 minute.
  • Charts: drawn in wonky_drive with the app's tokens, not wonky_charts_flutter. That engine would pull flutter_scene and its assets into Drive's bundle. Colors were checked for color vision deficiency in light and dark.
  • Privacy policy: a new Usage data entry and an aggregate-statistics purpose; the effective date is now 20 October 2026. Please review the wording.

Two migrations: usage-analytics (tables) and analytics-indexes (rollup and indexes).

Testing

  • wonky_server: dart test -x slow -j 2: 2,382 passed, 1 skipped. The analytics tests run in far-future date windows that they clear first, so they're isolated in the shared test database and pass on repeated runs.
  • wonky_drive: flutter test: all non-golden tests pass, including 25 analytics widget and unit tests (admin and non-admin, period and switch, hover tooltip, table view, dark, 360 px, pseudo-locale). The goldens weren't compared locally (spec 15 §7: Linux CI only).
  • wonky_app: flutter test -x golden,slow,e2e: all pass. The mobile left-menu test now skips admin-only entries.
  • dart analyze is clean in the server, Drive and the shell; the dependency rules check is OK.
  • Not done: no browser check of a release build yet.

🤖 Generated with Claude Code

Admins get an Analytics page in Wonky Drive (/drive/analytics, admin-only
left-menu entry and `drive.analytics.show`): accounts, active today,
weekly and monthly active users, stickiness, active users by app, sign-ups,
content now and created, collaboration, AI and MCP use, and weekly sign-up
cohorts. Aggregates only; admins are left out unless *Include admins* is on.

Recording is first-party and minimal (specs/19): one `user_activity_day`
row per person, UTC day and app, from the apps' ping at start/resume, item
opens, creations and edits (the activity log) and MCP tool calls. Welcome
content, scripts and the system don't count. Rows are kept 400 days.

Finished days are rolled up once into `usage_day_stats` (a past day never
changes), so the rolling DAU/WAU/MAU windows stay off the request path; new
indexes cover the date-range scans (activity_event type+at, comment,
permission grantedAt, ai_usage at, user_profile createdAt). The charts are
drawn in Drive with the app's tokens, colors checked for color vision
deficiency, each with a table view. The privacy policy names usage data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vlidholt

Copy link
Copy Markdown
Contributor Author

Superseded by #30 (same change, opened from the fork vlidholt/wonky).

@vlidholt vlidholt closed this Oct 20, 2026
@vlidholt
vlidholt deleted the feat/usage-analytics branch October 20, 2026 14:52
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant