Analytics

Every number in the dashboard is computed from persisted ProductEvent rows (and the GuideSession / StepInteraction rows derived from them at ingestion time). Nothing is hard-coded.

Event schema

Each event carries eventId (client idempotency key), name, customName (for custom), occurredAt, anonymousId, userId, accountId, sessionId, guideId, guideVersion, stepId, stepIndex, url, properties and SDK name/version. Duplicate eventIds are ignored (unique (projectId, eventId)).

Lifecycle names: guide_viewed, guide_started, step_viewed, step_completed, guide_completed, guide_skipped, guide_dismissed, guide_abandoned, checklist_task_completed, checklist_completed, checklist_dismissed, survey_displayed, survey_submitted, survey_dismissed, resource_center_opened, article_viewed, messenger_opened, conversation_started, conversation_handed_off, scout_answered, page_view, identify, custom. Autocapture and error tracking add page_leave, click, rage_click and exception; their properties, the page metrics, error grouping, and funnel and retention definitions are in product-analytics.md. Events with a URL also store its pathname in path (not when URL collection is off).

Definitions (denominators)

MetricDefinition
Unique users reacheddistinct anonymousId with ≥1 event in range (identified users keep their anonymous id, so nobody is double counted)
Guide views / starts / completionscount of the respective events in range
Guide sessionsGuideSession rows started in range (one per guide run, keyed by the SDK's guideSessionId)
Completion ratesessions completed ÷ sessions started in range
Abandonmentsessions dismissed + skipped + abandoned ÷ sessions started
Step drop-off(step viewed − step completed) ÷ step viewed, per step
Checklist completion ratechecklists completed in range ÷ checklists with any progress update in range
Survey response ratesurvey_submitted ÷ survey_displayed in range
NPS% promoters (9–10) − % detractors (0–6) over all numeric answers

Comparison periods use the same definitions over the immediately preceding window of equal length.

Performance

  • Overview and per-guide reports use `GROUP BY` aggregates and `COUNT(DISTINCT …)` SQL with the

    indexes listed in docs/data-model.md; the event explorer and exports are paginated (100 rows per page, streamed CSV).

  • The worker maintains `GuideDailyStat` rollups every 15 minutes; switch the timeseries queries to the

    rollup table when a project exceeds a few million events per month.

  • Survey distributions and checklist per-task rates are computed over the most recent 5,000 rows.

Protections

Rate limits per key/IP, batch caps (50 events), property size caps (8 KB), sensitive-key stripping, future timestamp clamping, retention windows, and per-project analyticsEnabled kill switch.