//Analytics Layer

Analytics Layer

Status as of March 28, 2026.

Goal

ButtrBase should expose a control-plane analytics layer, not just a pile of legacy counters.

The first shipped slice focuses on:

  • app analytics overview
  • organization analytics overview
  • custom event ingestion
  • shared analytics views in both the React and Solid admin consoles
  • Live Backend Surface

    GET /api/analytics/apps/:app_uuid/overview

    Returns the app-level analytics overview.

    Current summary coverage includes:

  • organizations
  • members
  • teams
  • active users over the last 7 days
  • new users over the last 30 days
  • audit events over the last 30 days
  • custom analytics events over the last 30 days
  • trailing revenue totals from stored pricing rows
  • Current chart coverage includes:

  • user activity over the last 14 days
  • event volume over the last 14 days
  • trailing 6-month revenue trend
  • Optional panel coverage (when instrumentation is present) includes:

  • pricing funnel conversion
  • auth and SSO adoption mix
  • entitlement deny-rate signals
  • session and governance operational signals
  • GET /api/analytics/organizations/:org_uuid/overview

    Returns the same analytics contract at organization scope.

    Optional panels Contract

    Both overview endpoints may include an optional top-level panels object.

    If panels is missing, consumers should keep rendering the base summary/series/breakdown/status contract.

    Current optional panel keys:

  • pricing_funnel
  • auth_adoption
  • entitlements
  • governance
  • Current panel fields:

  • pricing_funnel
  • preview_count_30d
  • quote_count_30d
  • checkout_started_30d
  • checkout_completed_30d
  • preview_to_quote_rate
  • quote_to_checkout_rate
  • checkout_completion_rate
  • auth_adoption
  • auth_login_30d
  • oidc_login_30d
  • otp_verified_30d
  • sso_share_pct
  • otp_share_pct
  • password_share_pct
  • entitlements
  • checks_30d
  • denied_30d
  • deny_rate_pct
  • top_denied_features (same shape as breakdown rows: key, label, value)
  • governance
  • audit_exports_30d
  • team_created_30d
  • team_member_added_30d
  • team_member_removed_30d
  • governance_events_30d
  • POST /api/analytics/events

    Stores a first-class analytics event.

    Current fields:

  • event_name
  • event_category
  • source
  • app_uuid
  • org_uuid
  • team_uuid
  • status
  • amount_cents
  • currency
  • metadata
  • occurred_at
  • At least one of app_uuid or org_uuid should be present.

    Current Data Sources

    The first analytics layer intentionally reuses existing operational data before moving to a dedicated warehouse:

  • users for sign-in and creation recency
  • orguser and teams for membership and team counts
  • app_pricing for stored billing totals
  • audit_events for structured admin actions
  • analytics_events for custom event ingestion
  • Current Frontend Surface

    React:

  • /dashboard/:appName/:appId/analytics
  • /dashboard/:appName/:appId/org/:orgName/:orgId/analytics
  • Solid:

  • /dashboard/:appName/:appId/analytics
  • /dashboard/:appName/:appId/org/:orgName/:orgId/analytics
  • Both consoles now use the same backend analytics contract and render optional decision panels when panels data is present.

    Important Limits In Phase 1

  • Revenue is aggregated from stored billing rows without FX normalization.
  • If the analytics_events migration has not been applied, overview routes still work, but custom-event storage is reported as not ready.
  • The first slice is overview-driven, not yet a full warehouse, segmentation, or export platform.
  • Recommended Event Taxonomy

    The next events worth standardizing are:

  • auth_*
  • sso_*
  • mfa_*
  • session_*
  • team_*
  • role_*
  • entitlement_*
  • pricing_*
  • governance_*
  • agent_*
  • audit_*

Next Build Steps

1. Automatically instrument pricing preview, quote, checkout, entitlement, and auth flows into analytics_events 2. Add export and warehouse sync paths once volume justifies it 3. Move the same analytics contract into the Rust migration plan after the current control-plane slices stabilize