.agents/features/analytics.md
The Analytics module provides platform-level reporting on automation usage: daily run counts, active flow counts, active user counts, and time-saved estimates. It powers an "Impact" dashboard for project-level drill-down and a "Leaderboard" view that ranks projects and users by automation output. Reports are cached with a 5-minute TTL and refreshed via a distributed-lock background job; a separate daily cron tracks per-piece usage across all flows.
packages/server/api/src/app/analytics/ — backend module (controller, two services, entity)packages/shared/src/lib/management/analytics/index.ts — all shared Zod schemas and enums (AnalyticsTimePeriod, PlatformAnalyticsReport, ProjectLeaderboardItem, UserLeaderboardItem, etc.)packages/web/src/features/platform-admin/api/analytics-api.ts — frontend API clientpackages/web/src/features/platform-admin/hooks/analytics-hooks.ts — TanStack Query hooks (platformAnalyticsHooks)packages/web/src/app/routes/impact/index.tsx — Impact page rootpackages/web/src/app/routes/impact/summary/index.tsx — summary metrics (active flows, users, runs, time saved)packages/web/src/app/routes/impact/trends/index.tsx — time-series area chartspackages/web/src/app/routes/impact/details/index.tsx — per-flow drill-down with editable time-savedpackages/web/src/app/routes/leaderboard/index.tsx — leaderboard page rootpackages/web/src/app/routes/leaderboard/projects-leaderboard.tsx — projects leaderboard tablepackages/web/src/app/routes/leaderboard/users-leaderboard.tsx — users leaderboard tableanalyticsEnabled plan flag.analyticsEnabled is true on the platform plan.analyticsEnabled is true on the platform plan.LAST_WEEK, LAST_MONTH, LAST_THREE_MONTHS, LAST_SIX_MONTHS, LAST_YEAR).runs × timeSavedPerRun; displayed on leaderboards and impact summary.pieceMetadata.usage.PlatformAnalyticsReport: id, platformId, cachedAt, outdated (boolean), runs (AnalyticsRunsUsageItem[]), flows (AnalyticsFlowReportItem[]), users (UserWithMetaInformation[]).
AnalyticsRunsUsageItem: { flowId, day: Date, runs: number } — daily aggregationAnalyticsFlowReportItem: { flowId, flowName, projectId, projectName, ownerId } — enabled flowspieces-analytics.service.ts)Scheduled: Daily cron at 12:00 UTC
Tracks which pieces are actively used:
pieceMetadata.usage = projectCountplatform-analytics-report.service.ts)Key methods:
refreshReport(platformId) — distributed lock (400s), queries users + enabled flows + daily run counts (PRODUCTION only), merges incrementally. Stored as entity.getOrGenerateReport(platformId, timePeriod?) — returns cached report (5-min TTL), filters by time periodgetProjectLeaderboard(platformId, timePeriod) — groups flows by project, calculates minutes savedgetUserLeaderboard(platformId, timePeriod) — groups flows by owner, calculates minutes savedmarkAsOutdated(platformId) — flags report for refreshAnalyticsTimePeriod: LAST_WEEK, LAST_MONTH, LAST_THREE_MONTHS, LAST_SIX_MONTHS, LAST_YEAR
Minutes saved = runs count × flow.timeSavedPerRun
Users: rank, userName, email, flowCount, minutesSaved, badges[] Projects: rank, projectName, flowCount, minutesSaved
Displayed at /leaderboard in frontend with time period selector + search + time-saved range filter.
analyticsEnabled plan flag. Module uses platformMustHaveFeatureEnabled((p) => p.plan.analyticsEnabled).
All analytics queries in platformAnalyticsHooks include enabled: platform.plan.analyticsEnabled to prevent firing when the feature is off. The Impact page (/impact) is split into Summary, Trends, and Details sub-routes. The Leaderboard page (/leaderboard) shows separate tabs for projects and users, each with a time period picker. A "Refresh" button triggers useRefreshAnalytics mutation which calls the backend refresh endpoint and invalidates all analytics query keys.