.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. 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/core/shared/src/lib/management/analytics/index.ts — all shared Zod schemas and enums (AnalyticsTimePeriod, PlatformAnalyticsReport, AnalyticsReportRequest, 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-savedanalyticsEnabled plan flag.analyticsEnabled is true on the platform plan.analyticsEnabled is true on the platform plan.Canonical term definitions live in the bounded-context glossaries — see CONTEXT-MAP.md.
LAST_WEEK, LAST_MONTH, LAST_THREE_MONTHS, LAST_SIX_MONTHS, LAST_YEAR).runs × timeSavedPerRun; displayed on the 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 periodmarkAsOutdated(platformId) — flags report for refreshAnalyticsTimePeriod: LAST_WEEK, LAST_MONTH, LAST_THREE_MONTHS, LAST_SIX_MONTHS, LAST_YEAR
Minutes saved = runs count × flow.timeSavedPerRun
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. A "Refresh" button triggers useRefreshAnalytics mutation which calls the backend refresh endpoint and invalidates all analytics query keys.