Fas 1a: product analytics schema + GDPR controls

This commit is contained in:
Sven (AAMOS AI)
2026-08-05 19:21:32 +07:00
parent ac5340195a
commit d627014425
26 changed files with 9039 additions and 14 deletions
+132
View File
@@ -0,0 +1,132 @@
/**
* Product analytics taxonomy (spec §8.2).
* Pseudonymous events separated from AAMOS memory and domain events.
* All event names are snake_case and stable.
*/
// ---------------------------------------------------------------------------
// Acquisition & onboarding
// ---------------------------------------------------------------------------
export const ANALYTICS_EVENT_NAMES = [
"app_installed",
"app_first_open",
"onboarding_started",
"onboarding_step_completed",
"onboarding_skipped",
"account_created",
"household_created",
"household_joined",
"allergy_setup_completed",
"camera_permission_result",
"notification_permission_result",
] as const;
// ---------------------------------------------------------------------------
// Inventory
// ---------------------------------------------------------------------------
export const ANALYTICS_INVENTORY_EVENT_NAMES = [
"scan_started",
"scan_uploaded",
"scan_processing_completed",
"scan_processing_failed",
"scan_review_opened",
"scan_item_confirmed",
"scan_item_corrected",
"scan_item_removed",
"scan_completed",
"inventory_item_added",
"inventory_item_consumed",
"inventory_item_discarded",
"inventory_reconciliation_started",
"inventory_reconciliation_completed",
"inventory_conflict_created",
"inventory_conflict_resolved",
] as const;
// ---------------------------------------------------------------------------
// Recipes & cooking
// ---------------------------------------------------------------------------
export const ANALYTICS_COOKING_EVENT_NAMES = [
"recommendations_viewed",
"recommendation_opened",
"recipe_saved",
"cooking_session_started",
"cooking_session_completed",
"cooking_session_cancelled",
"leftovers_created",
"substitution_confirmed",
] as const;
// ---------------------------------------------------------------------------
// Shopping
// ---------------------------------------------------------------------------
export const ANALYTICS_SHOPPING_EVENT_NAMES = [
"shopping_item_added",
"shopping_item_checked",
"shopping_list_shared",
"receipt_scanned",
"purchase_imported",
] as const;
// ---------------------------------------------------------------------------
// Household
// ---------------------------------------------------------------------------
export const ANALYTICS_HOUSEHOLD_EVENT_NAMES = [
"household_invite_sent",
"household_invite_accepted",
"second_member_first_action",
] as const;
// ---------------------------------------------------------------------------
// Subscription
// ---------------------------------------------------------------------------
export const ANALYTICS_SUBSCRIPTION_EVENT_NAMES = [
"paywall_viewed",
"trial_started",
"trial_cancelled",
"subscription_started",
"subscription_renewed",
"subscription_grace_period",
"subscription_cancelled",
"subscription_expired",
"entitlement_restored",
] as const;
// ---------------------------------------------------------------------------
// Feedback
// ---------------------------------------------------------------------------
export const ANALYTICS_FEEDBACK_EVENT_NAMES = [
"feedback_submitted",
"incorrect_inventory_reported",
"bad_recommendation_reported",
"support_contact_started",
] as const;
export const PRODUCT_ANALYTICS_EVENT_NAMES = [
...ANALYTICS_EVENT_NAMES,
...ANALYTICS_INVENTORY_EVENT_NAMES,
...ANALYTICS_COOKING_EVENT_NAMES,
...ANALYTICS_SHOPPING_EVENT_NAMES,
...ANALYTICS_HOUSEHOLD_EVENT_NAMES,
...ANALYTICS_SUBSCRIPTION_EVENT_NAMES,
...ANALYTICS_FEEDBACK_EVENT_NAMES,
] as const;
export type ProductAnalyticsEventName = (typeof PRODUCT_ANALYTICS_EVENT_NAMES)[number];
/**
* Built-in funnels. Each funnel is an ordered list of event names.
*/
export const FUNNELS = {
install_to_account: ["app_installed", "app_first_open", "account_created"],
account_to_first_scan: ["account_created", "scan_started", "scan_completed"],
scan_to_inventory: ["scan_completed", "inventory_item_added"],
inventory_to_recipe: ["inventory_item_added", "recommendations_viewed"],
recipe_to_cooking: ["recommendation_opened", "cooking_session_started"],
cooking_to_updated_inventory: ["cooking_session_started", "cooking_session_completed"],
activated_to_trial: ["cooking_session_completed", "trial_started"],
trial_to_paid: ["trial_started", "subscription_started"],
single_to_two_members: ["household_invite_sent", "household_invite_accepted", "second_member_first_action"],
} as const;
export type FunnelName = keyof typeof FUNNELS;
+2
View File
@@ -485,6 +485,8 @@ export const CONSENT_KINDS = [
"health_integration",
"location_weather",
"push_notifications",
/** Product analytics legitimate interest with opt-out (spec §8, §33). */
"product_analytics",
] as const;
export type ConsentKind = (typeof CONSENT_KINDS)[number];
+1
View File
@@ -6,3 +6,4 @@ export * from "./brand.js";
export * from "./locale.js";
export * from "./money.js";
export * from "./measurement.js";
export * from "./analytics.js";