# Observability and Analytics Plan The demo currently proves the full gameplay loop: collect items, answer trivia, submit predictions, unlock badges, complete challenges, and move on the leaderboard. This plan defines the events and health signals that should be added before a larger public pilot. ## Goals 1. Confirm fans can complete the daily loop without friction. 2. Measure which features drive repeat visits. 3. Detect broken API routes, stalled gamification updates, and leaderboard anomalies quickly. 4. Preserve privacy by avoiding unnecessary personal data collection. ## Product analytics events All events should include: | Field | Type | Notes | | --- | --- | --- | | `event_name` | string | One of the event names below. | | `event_id` | string | Random unique id for deduplication. | | `session_id` | string | Anonymous session id. | | `user_id` | string | Demo/user id if available; avoid email addresses. | | `occurred_at` | ISO timestamp | Client time plus server receive time when available. | | `app_surface` | string | `web`, `api`, `demo-script`, or future client. | | `app_version` | string | Release tag or commit SHA. | Recommended events: | Event | Trigger | Important properties | | --- | --- | --- | | `demo_session_started` | App first loads and passport is fetched | `source`, `viewport`, `api_base_url_mode` | | `passport_loaded` | Passport state is returned | `collections_count`, `badges_count`, `completed_challenges_count`, `points` | | `collection_item_collected` | Fan collects a team, stadium, match, or sticker | `item_id`, `item_type`, `rarity`, `points_awarded` | | `trivia_answer_submitted` | Fan answers a trivia question | `question_id`, `answer_correct`, `points_awarded`, `streak_after` | | `prediction_submitted` | Fan submits a prediction | `match_id`, `prediction_type`, `selected_team_id`, `confidence` | | `badge_unlocked` | Gamification engine awards a badge | `badge_id`, `badge_category`, `trigger_event` | | `challenge_completed` | Fan completes a challenge | `challenge_id`, `challenge_category`, `points_awarded` | | `leaderboard_viewed` | Fan opens or refreshes leaderboard | `rank`, `points`, `entries_returned` | | `api_error_seen` | Client receives a handled API error | `route`, `status`, `error_code` | | `empty_state_seen` | Empty collection/leaderboard state is shown | `surface`, `reason` | ## Example event payload ```json { "event_name": "badge_unlocked", "event_id": "evt_9d2a8c21", "session_id": "sess_demo_001", "user_id": "demo-fan", "occurred_at": "2026-06-14T18:30:00.000Z", "app_surface": "web", "app_version": "demo-release-1", "properties": { "badge_id": "first-trivia-win", "badge_category": "trivia", "trigger_event": "trivia_answer_submitted" } } ``` ## Funnel definitions ### Daily fan loop 1. `demo_session_started` 2. `passport_loaded` 3. At least one of: - `collection_item_collected` - `trivia_answer_submitted` - `prediction_submitted` 4. At least one gamification event: - `badge_unlocked` - `challenge_completed` 5. `leaderboard_viewed` Healthy demo target: at least 80% of guided demo sessions reach step 5. ### Trivia loop 1. `passport_loaded` 2. `trivia_answer_submitted` 3. `badge_unlocked` or `challenge_completed` 4. `leaderboard_viewed` Track correct/incorrect answer split to ensure wrong answers are handled clearly and do not trap the user. ### Collection loop 1. `passport_loaded` 2. `collection_item_collected` 3. Collection count increases in passport response 4. Challenge or badge state updates 5. Leaderboard points increase Track duplicate collection attempts separately; they are expected edge cases and should return friendly messaging. ## Operational health signals | Signal | Source | Target | | --- | --- | --- | | API health check success | `/health` or `/api/health` | 99% during demo windows | | API p95 latency | Server timing middleware or hosting metrics | Under 300 ms for demo in-memory flows | | API 5xx rate | Hosting logs | 0 during scheduled demos | | Client unhandled errors | Browser error reporting | 0 during scheduled demos | | E2E demo pass rate | CI and release runbook | 100% before public update | | Leaderboard rank anomalies | API assertions or analytics | No negative ranks, no duplicate rank for same user snapshot | | Gamification award duplication | API assertions | Badge and challenge awards are idempotent | ## Logging recommendations API logs should include: - Request method and route pattern - Response status - Duration - Demo user id when available - Error code for handled failures - Correlation id Do not log: - Raw personal identifiers - Future authentication tokens - Full free-text support messages - Browser fingerprinting fields Suggested structured log shape: ```json { "level": "info", "message": "request_completed", "correlation_id": "req_3f4bcf", "method": "POST", "route": "/api/passport/:userId/trivia/:questionId", "status": 200, "duration_ms": 42, "user_id": "demo-fan" } ``` ## Alerting thresholds for a public demo | Alert | Threshold | Response | | --- | --- | --- | | API down | 2 consecutive failed health checks | Switch to local Docker demo or restart service. | | E2E demo failure on main | Any failure | Block release until triaged. | | 5xx burst | More than 3 errors in 5 minutes | Review logs, restart demo, capture failing input. | | Leaderboard empty after gameplay | Any occurrence in guided demo | Verify store reset, seed data, and scoring engine. | | Badge duplication | Same badge awarded twice to one user in one response | Review gamification idempotency. | ## Privacy posture For the current demo, keep analytics anonymous or use demo-only user ids. Future public releases should add: - Consent copy for analytics - Data retention policy - User deletion/export path - Region-aware hosting decisions - Review of FIFA and club/team trademark usage in content and marketing