kAnalyticsRegistry top-level property
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),
});