Disciplines · Decisions (ADRs)

ADR-0012: Analytics Taxonomy and Event Naming

OSHUN needs one analytics language across:

Accepted · 2026-02-16
10sections6 minread

On this page

Status: Accepted Date: 2026-02-16 Authors: OSHUN Platform Engineering, OSHUN Data/Analytics Engineering Reviewers: Domain Leads (Tara, Veritas, Nyx, Arete), OSHUN Product Supersedes: N/A Superseded by: N/A

Context and Problem Statement#

OSHUN needs one analytics language across:

  • mobile shell (iOS/Android)
  • website/PWA shell
  • domain adapters (Tara, Veritas, Nyx, Arete)

Current repo patterns are inconsistent:

  • OSHUN metrics draft defines shell KPI events as oshun.* names.
  • Veritas web behavior tracking uses snake_case event names (article_view, article_complete, search_query, etc.).
  • Shared monitoring infra accepts generic eventType: string with no enforced naming taxonomy.
  • Domain contracts in libs/contracts/src/events/* already use dot-delimited <domain>.<entity>.<action> naming.

Without a single taxonomy, we get fragmented dashboards, weak KPI comparability across surfaces, and expensive data normalization work.

Decision Drivers#

  • Comparability of product metrics across iOS, Android, web, and PWA.
  • Cross-domain consistency for Tara, Veritas, Nyx, and Arete reporting.
  • Governance with versioned event contracts and validation.
  • Implementation pragmatism by reusing existing event styles where possible.
  • Privacy/compliance through explicit consent and PII controls.
  • Observability with low-cardinality, query-friendly event names.

Considered Options#

Option 1: Keep Domain-Specific Naming, Normalize in Warehouse#

Description: each domain keeps current names; BI layer remaps later.

Pros:

  • ✅ Minimal short-term engineering work in apps
  • ✅ High domain autonomy

Cons:

  • ❌ Expensive and brittle downstream mapping
  • ❌ Slower KPI iteration and conflicting metric definitions
  • ❌ Harder enforcement of quality and consent rules

Option 2: One Flat Global Event List#

Description: enforce one long list of event names with no namespace layering.

Pros:

  • ✅ Simple initial schema
  • ✅ Easy to start tracking quickly

Cons:

  • ❌ Name collisions over time
  • ❌ Poor ownership boundaries by shell/domain
  • ❌ Hard to evolve and reason about event families

Option 3: Canonical Dot-Delimited Taxonomy with Namespaces (Chosen)#

Description: enforce <namespace>.<entity>.<action> canonical naming and a standard envelope; allow adapter-level mapping from legacy names.

Pros:

  • ✅ Aligns with existing domain contract style (veritas.article.published)
  • ✅ Clear ownership boundaries (oshun, tara, veritas, nyx, arete)
  • ✅ Query-friendly and scalable naming model
  • ✅ Supports gradual migration from existing snake_case trackers

Cons:

  • ❌ Requires migration/adaptation for existing behavior trackers
  • ❌ Requires governance and linting discipline

Decision Outcome#

Chosen option: Option 3 - canonical dot-delimited taxonomy.

Canonical Event Name Contract (Normative)#

Event names MUST use:

  • format: <namespace>.<entity>.<action>
  • lowercase ascii only
  • dot-delimited segments
  • snake_case words within each segment if needed
  • past-tense or completed-action verb in action where applicable

Examples:

  • oshun.app.opened
  • oshun.domain.opened
  • oshun.search.executed
  • veritas.article.viewed
  • tara.session.completed
  • arete.checkin.completed

Disallowed examples:

  • AppOpened (camelCase)
  • article_view (missing namespace/entity separation)
  • oshun.article (no action)
  • oshun..opened (empty segment)

Namespace Ownership#

  • oshun.*: shell-level and cross-domain normalized KPI events.
  • tara.*, veritas.*, nyx.*, arete.*: domain-native product events.
  • system.*: optional non-product telemetry (ingestion, pipeline, SDK health).

Required Event Envelope (Normative)#

Every analytics event MUST include:

  • event_id (globally unique id)
  • event_name (canonical name)
  • event_version (integer, starts at 1)
  • occurred_at (ISO-8601 UTC timestamp)
  • platform (ios, android, web, pwa)
  • surface (mobile_shell, web_shell, domain_app, bff)
  • session_id
  • domain_context (oshun_shell, tara, veritas, nyx, arete)
  • consent_analytics (boolean gate)

User identity fields:

  • user_id when authenticated
  • anonymous_id when unauthenticated
  • at least one of user_id or anonymous_id is required

Property Standards#

  • Use snake_case property names.
  • Stable enum properties MUST be documented in contract schemas.
  • High-cardinality free text should be minimized and explicitly justified.
  • PII (email, phone, full name, raw IP) MUST NOT be sent in event properties.

Event Versioning Rules#

  • Additive, backward-compatible property additions: keep same event_name, increment optional schema metadata as needed.
  • Breaking changes (rename/remove semantic meaning): increment event_version.
  • Name changes require dual-write period and mapping documentation.

Taxonomy Families (Normative)#

OSHUN analytics events MUST be categorized into these families:

  • lifecycle: app/session open, close, resume
  • auth: signin, signup, logout, refresh, revocation outcomes
  • navigation: route transitions, deep-link opens, domain launches
  • engagement: views, reads, saves, shares, follows
  • value_action: normalized high-value outcomes for KPI computation
  • search: query, filter, result open, zero-result
  • notification: received, opened, dismissed, actioned
  • performance: web vitals, startup, hydration, launch latency
  • error: user-visible failures and recoveries
  • commerce (if enabled): paywall views, conversion steps, purchase outcomes

Canonical OSHUN KPI Events#

The following normalized events are mandatory for OSHUN KPI computation:

  • oshun.app.opened
  • oshun.auth.completed
  • oshun.profile.initialized
  • oshun.domain.opened
  • oshun.value_action.completed
  • oshun.item.saved
  • oshun.item.resumed
  • oshun.search.executed
  • oshun.notification.opened

oshun.value_action.completed MUST include:

  • domain_context
  • value_action_type
  • completion_quality (partial, full)
  • entity_id (or equivalent domain entity reference)

Legacy-to-Canonical Mapping Requirements#

Adapter layers MUST map legacy names to canonical names before ingestion into OSHUN KPI datasets.

Initial mapping requirements include:

Legacy Event Canonical Event
oshun.app_opened oshun.app.opened
oshun.auth_completed oshun.auth.completed
oshun.profile_initialized oshun.profile.initialized
oshun.domain_card_opened oshun.domain.opened
oshun.value_action_completed oshun.value_action.completed
oshun.item_saved oshun.item.saved
oshun.item_resumed oshun.item.resumed
oshun.search_executed oshun.search.executed
oshun.notification_opened oshun.notification.opened
article_view (Veritas behavior tracker) veritas.article.viewed
article_complete (Veritas behavior tracker) veritas.article.completed
search_query (Veritas behavior tracker) veritas.search.executed
  • Events with consent_analytics=false MUST be excluded from analytics KPI views.
  • Consent state transitions must be audited as separate oshun.privacy.* events where policy permits.
  • Anonymous pre-consent events may be used only for strictly necessary operational telemetry, not product analytics KPIs.

Implementation Guidance#

SDK and Contracts#

  • Implement shared types/contracts in libs/oshun/analytics (planned).
  • Validate names and required envelope fields at SDK boundary.
  • Provide helper APIs to reduce ad hoc string event usage.

Shell and Domain Adapters#

  • Shell emits oshun.* normalized events.
  • Domain adapters emit domain-native events and optional normalized mirror events for KPI-critical actions.
  • BFF enforces envelope validation and rejects malformed events.

Warehouse and BI#

  • Keep event_name canonical and immutable in curated tables.
  • Preserve raw event payload in bronze/raw storage for forensics.
  • Maintain version-aware transforms for event_version changes.

Implementation Plan#

Phase 1: Contract Finalization#

  • Define canonical event-name regex and lint checks.
  • Define envelope schema and required enums.
  • Publish initial event dictionary with owners.

Phase 2: Adapter Migration#

  • Add mapping layer for existing Veritas behavior events.
  • Add canonical shell event emitter for mobile/web/PWA.
  • Introduce dual-write where migrations are needed.

Phase 3: Enforcement#

  • Add CI checks for disallowed event names.
  • Add ingestion-side validation with reject/error metrics.
  • Add dashboard for unknown/unmapped event names.

Phase 4: Hardening#

  • Remove deprecated aliases after migration window.
  • Run periodic taxonomy review and cardinality audits.
  • Add playbooks for emergency event rollback/deprecation.

Success Metrics#

  • 100% of OSHUN KPI dashboards use canonical event_name values.
  • Unknown/unmapped event rate < 0.5% of daily event volume.
  • Consent violation rate for KPI datasets = 0.
  • Event schema validation pass rate >= 99.5%.
  • Cross-platform metric parity (mobile vs web/PWA definitions) maintained.

Consequences#

Positive Consequences#

  • ✅ Clear, scalable analytics naming model across shell and domains.
  • ✅ Faster metric development with less downstream remapping.
  • ✅ Better governance, auditability, and privacy control.

Negative Consequences#

  • ❌ Upfront migration work in tracking adapters and dashboards.
  • ❌ Ongoing taxonomy governance overhead.

Risks and Mitigations#

Risk Probability Impact Mitigation
Legacy tracker drift continues Medium High CI lint + ingestion validation + owner escalation
High-cardinality property explosion Medium Medium event review checklist + cardinality monitoring
Dashboard breakage during rename Medium High dual-write period + mapping tables + cutover plan
Consent metadata missing in clients Low High SDK-required fields + ingestion reject policy

Monitoring and Observability#

Track:

  • event ingestion acceptance/rejection counts by reason
  • unknown event-name frequency
  • event-version distribution per event_name
  • consented vs non-consented event ratios
  • mapping-layer fallback usage during migration
  • docs/adr/ADR-0013-oshun-shell-architecture-and-domain-adapters.md
  • docs/adr/ADR-0014-oshun-web-and-pwa-strategy.md
  • docs/adr/ADR-0016-shared-identity-and-cross-domain-session-model.md
  • docs/adr/ADR-0017-offline-caching-and-sync-strategy.md
  • docs/adr/ADR-0010-eventing-strategy.md

References#

  • docs/releases/v1/reports/metrics.md
  • apps/veritas/web/src/lib/behavior-tracking/types.ts
  • apps/veritas/web/src/lib/behavior-tracking/tracker.ts
  • apps/veritas/mobile/src/services/notifications.ts
  • libs/contracts/src/events/veritas.ts
  • libs/shared/infrastructure/src/types.ts
  • libs/shared/infrastructure/src/monitoring/monitoring-manager.ts