kAnalyticsRegistry top-level property

Map<String, AnalyticsEventSpec> kAnalyticsRegistry
final

The single-sourced event taxonomy: canonical name → {tier, requiredProperties}. Read by the SDK (warn on unknown), the ingest validator (derive tier), and the schema docs — the validator==SDK triangle.

Forward-compat: unknown names are soft-allowed as Tier 1 (see lookupAnalyticsEvent); they are never rejected here (the abuse budget, not this registry, bounds unknown-name cardinality).

The exposed map is unmodifiable — callers read the taxonomy, they do not mutate it.

Implementation

final Map<String, AnalyticsEventSpec> kAnalyticsRegistry =
    Map<String, AnalyticsEventSpec>.unmodifiable(<String, AnalyticsEventSpec>{
  // --- Tier 1: paywall lifecycle / conversion / errors (existing SDK names) ---
  'paywall_load_started': _tier1,
  'paywall_load_completed': _tier1,
  'paywall_load_failed': _tier1,
  // The funnel terminator (a load that never completed nor failed).
  'paywall_load_aborted': _tier1,
  'paywall_viewed': _tier1,
  'paywall_dismissed': _tier1,
  'paywall_custom_event': _tier1,
  'purchase_initiated': _tier1,
  'purchase_succeeded': _tier1,
  'purchase_pending': _tier1,
  'purchase_cancelled': _tier1,
  'purchase_failed': _tier1,
  'restore_initiated': _tier1,
  'restore_succeeded': _tier1,
  'restore_no_purchases': _tier1,
  'restore_failed': _tier1,
  'page_changed': AnalyticsEventSpec(
    tier: AnalyticsTier.tier1,
    requiredProperties: const <String>{'pageIndex', 'pageCount'},
  ),
  'paywall_survey_responded': AnalyticsEventSpec(
    tier: AnalyticsTier.tier1,
    requiredProperties: const <String>{'questionId', 'questionIndex'},
  ),

  // --- Tier 1: entitlement / subscription lifecycle (server + client) ---
  'entitlement_granted': _tier1,
  'entitlement_revoked': _tier1,
  'subscription_renewed': _tier1,
  'subscription_lapsed': _tier1,

  // --- Tier 1: canonical root presentation (all surface types) ---
  'surface_presented': _tier1,

  // --- Tier 1: delivery infrastructure (all surface types) ---
  // A surface whose description resolved but whose content could not be
  // fetched. The client falls back and the end user sees something reasonable,
  // which is exactly why this has to be reported: the failure is otherwise
  // invisible from the outside. Registered explicitly rather than left to the
  // registry's tolerance of unknown names — a keep-all signal should be
  // declared where sampling is decided, not inferred.
  kSurfaceArtifactFetchFailedEventName: _tier1,

  // --- Tier 1: engagement-flow lifecycle (surface-agnostic) ---
  'flow_started': _tier1,
  'flow_completed': _tier1,
  'flow_unavailable': _tier1,
  'flow_custom_event': _tier1,

  // --- Tier 1: onboarding surface events ---
  'onboarding_step_viewed': AnalyticsEventSpec(
    tier: AnalyticsTier.tier1,
    requiredProperties: const <String>{'screenId', 'stepIndex'},
  ),
  'onboarding_skipped': AnalyticsEventSpec(
    tier: AnalyticsTier.tier1,
    requiredProperties: const <String>{'atScreenId', 'stepIndex'},
  ),
  'onboarding_permission_response': AnalyticsEventSpec(
    tier: AnalyticsTier.tier1,
    requiredProperties: const <String>{'permission', 'granted'},
  ),

  // --- Tier 2: the sole coalesced per-session summary ---
  'paywall_session_summary': AnalyticsEventSpec(tier: AnalyticsTier.tier2),
});