add-analytics

SkillDatabases & data

Design or add Sesori product analytics. Use when adding a user-facing feature, deciding whether an event is valuable, changing analytics identity/privacy, instrumenting an outcome, or adding BigQuery/Looker metrics. Covers authoritative hook points, layered delivery, bounded event design, GoRouter screen reporting, voice/login exceptions, and warehouse verification.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the add-analytics skill

What this skill tells your AI

The instructions your AI receives, as published by sesori-ai/sesori_apps_monorepo in .opencode/skills/add-analytics/SKILL.md and read by ahel’s review.

Design analytics that answer a product question without creating misleading or sensitive data.

Before adding an event

An event is worthwhile only when all of these are concrete:

  1. Decision: What product decision or investor metric changes if this moves?
  2. Meaning: Is it an intent, confirmed outcome, state transition, or view?
  3. Authority: Which business success/failure seam proves it happened?
  4. Population: Is the unit an account, installation, or action? Never mix those denominators under one label.
  5. Privacy: Can every parameter be a bounded enum/boolean or explicitly approved scalar without code, content, paths, identity, or entity IDs?
  6. Reporting: Which curated model/view consumes it, and how are coverage, maturity, freshness, and deduplication handled?

If the answer is only “this button was tapped,” skip it unless that tap is the only honest signal for a defined funnel step.

Current and planned seams

The source of truth is the closed models under client/module_core/lib/src/foundation/models/product_analytics/, with repository delivery/preference records under repositories/models/ and service state under services/models/:

  • Consumers call ProductAnalyticsService for authenticated account-linked events.
  • Five approved account-less authentication events call InstallationAnalyticsService: the started/completed/failed attempt funnel plus Firebase's recommended sign_up and login outcomes. They are preference-exempt by explicit product decision.
  • Singular attribution is a separate, preference-exempt scope by owner decision: standard authentication conversions through InstallationAnalyticsService, one-shot bridge_paired through AttributionService, and one-shot first_session_run from the canonical message outcomes inside ProductAnalyticsService. All reach the SDK through AttributionRepository; add no other attribution event without a privacy decision.
  • Delivery flows Client (Foundation) -> API -> Repository -> Service -> Consumer. Cubits/widgets/listeners never hold AnalyticsClient or AnalyticsApi directly.
  • Mobile implements AnalyticsClient with Firebase; desktop uses a no-op adapter until desktop analytics has its own approved scope.

Choose the authoritative hook

Event meaningCorrect seamExample
Confirmed outcomeSuccess branch after repository/service responseMessage accepted, session created
Failure diagnosticExplicit typed failure branchSession creation failed
Reactive stateDedicated listener or bounded transition guardBridge/screen state
ScreenGoRouterRouteSource -> exhaustive AnalyticsScreen mappingproduct_screen_viewed
Flutter-only capabilityUI call site after capability succeeds, calling Layer-3 serviceVoice transcription completed
Account-less authenticationLoginCubit terminal state through InstallationAnalyticsServiceAttempt failure or server-confirmed signup/login

Never use a widget tap as a proxy when a confirmed outcome exists. Never emit a success event when an operation is queued, merely attempted, or later requeued. Capture product-event occurrence time at that authoritative seam before any preference deferral; a later Firebase emission timestamp must not move funnel or retention timing.

Screen reporting

  • GoRouterRouteSource.currentRouteStream is the sole screen source.
  • Map every AppRouteDef exhaustively to a pinned AnalyticsScreen; never send concrete paths, project/session IDs, or Dart enum names as implicit wire values.
  • Disable Firebase automatic screen reporting on Android and Firebase-enabled Apple targets.
  • Emit canonical account-linked product_screen_viewed, then let the Firebase adapter best-effort mirror the same pinned name through logScreenView.
  • Curated account metrics use only product_screen_viewed; standard screen_view is diagnostic. Test one custom + one native event per changed GoRouter route and no automatic duplicate.

Parameters and naming

  • Event/parameter names: pinned snake_case, max 40 characters.
  • Use enums for closed values and explicit converters/mappings for existing sealed types. Do not assume a domain type is an enum.
  • Max 25 parameters per GA4 event; fewer is better.
  • Do not rename a released wire value. Add a schema version when semantics must change.
  • input_mode=voice_assisted means a successful transcript contributed to the submitted composer value; it never means the final text was unedited. Preserve that bounded origin with any restored composer draft.

Identity and privacy

Never report:

  • prompt, response, transcript, code, reasoning, or tool content;
  • file/repository/project/session/branch/worktree names or paths;
  • raw or hashed project/session/bridge/device/notification IDs;
  • OAuth identity, username, email, provider user ID, IP/geography, or raw error text;
  • coding provider/model/agent/tool/command names unless a later approved plan changes the privacy contract.

Account-linked events use only the pseudonymous custom user_key produced in the repository. Never set Firebase global user_id for the new design. Installation authentication events carry no user_key or attempt ID. Funnel events use only approved provider/failure enums; recommended sign_up/login events use only the same pinned provider enum as method. Any broader parameters require a new decision.

Implementation checklist

  1. Add a closed event variant and pinned parameter enums to the active source of truth.
  2. Identify the authoritative success/failure/transition seam.
  3. Route through the correct Layer-3 service; update every mobile/desktop constructor consumer in lockstep.
  4. Keep product behavior independent: analytics is best-effort, failure-isolated, and never changes product success.
  5. Generate source outputs; never hand-edit generated files.
  6. Test exact wire names/parameters, success-only emission, failure/no-op paths, deduplication, and absence of sensitive values.
  7. Add/update versioned BigQuery transforms and fixture ASSERTs. Account metrics use user_key plus the eligible auth snapshot; installation events aggregate without persisting user_pseudo_id.
  8. Show complete periods, denominators, cohort maturity, coverage, and freshness.
  9. Run analyze/tests for every touched module and affected downstream shell.

Do not create raw-export dashboards

Investor and product dashboards read authorized aggregate reporting views, not ad-hoc views over raw events_*. Raw GA4 timestamps are integer microseconds; users/installations/accounts differ; rolling WAU needs a real seven-day range; and retention requires matured, fixed windows. Encode those contracts in curated SQL with fixture assertions rather than dashboard formulas.

Signals

GitHub stars
119
Forks
8
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
add-analytics-sesori-ai
Source
github.com/sesori-ai/sesori_apps_monorepo