Skip to content

Latest commit

 

History

History
102 lines (85 loc) · 24.8 KB

File metadata and controls

102 lines (85 loc) · 24.8 KB

Load-bearing PostHog events

This is the maintained dictionary for events that drive a product funnel, reliability or compliance check, or a regression alert. It deliberately does not inventory every analytics wrapper: most of those events are not load-bearing, and a generated list of method names would not identify the product boundary that owns emission.

The authoritative emitter below is the state or user-action boundary that decides whether an event happened. Analytics-manager methods only shape and send its payload.

Maintenance contract

  • Update this file in the same change when a listed event is renamed, moved, starts or stops emitting, changes a listed property/person property, or changes alert coverage.
  • Add an event when a production funnel, reliability/compliance check, or regression alert begins to depend on it. Do not add every analytics method.
  • Keep dimensions bounded and content-free. Normalize unknown values to unknown; never send transcripts, chat text, deletion errors, email, or device names in the properties documented here.
  • macOS and Windows are separate surfaces. Windows has no BLE stack and cannot emit pairing, connection, or pendant-session events. Never report a blended "desktop" hardware funnel.
  • Alert links below point to the checked-in configuration contract. The alerts are not live until their PostHog insight/alert links replace that local link; creating them is a separate production write.

device_vendor is the shared closed dimension: omi, limitless, plaud, bee, apple, fieldlabs, friend, neosapien, above, utami, meta, or unknown.

Every Flutter mobile event is stamped centrally with closed app_platform (ios, android, or unknown), semantic app_version, and store app_build. These canonical fields override conflicting call-site values; PostHog SDK-reserved version fields are not the cross-platform contract.

Connection and purchase funnel

Event Owning surface Emission contract and authoritative emitter Key properties / person properties Alert
Connect Device Page Opened Flutter mobile (iOS/Android) Once when the connect-device page initializes: ConnectDevicePage.initState No event or person properties. Not alerted; funnel denominator for Get Omi Device Clicked.
Get Omi Device Clicked Flutter mobile (iOS/Android) Before launching the external Omi store URL: openOmiStore No event or person properties. Specified: weekly unique people; not yet provisioned.
Permissions Interstitial Shown Flutter mobile (fresh-install permissions flow; repaired for Android) Once per mounted interstitial: _PermissionsInterstitialPageState.initState No event or person properties. Not alerted; must be greater than or equal to Permissions Interstitial Completed by platform.
Permissions Interstitial Completed Flutter mobile (iOS/Android) When the user completes the permission actions and continues: PermissionsInterstitialPage No event or person properties. Not alerted; completion numerator for the shown/completed invariant.
Device Connected Flutter mobile BLE (iOS/Android) Once for each disconnected/different-device → connected transition, regardless of connection path: DeviceProvider.setConnectedDevice Event: closed device_vendor, closed hardware_family, enum-name type; hardware_id only when the device exposes a manufacturer serial, with hardware_id_kind and hardware_id_stable; the BLE transport_device_id is explicitly labeled platform_dependent. Person: device_vendor, hardware_family. Specified: weekly unique people and connected/disconnected ratio; not yet provisioned.
Device Connected macOS desktop BLE Once for each successful DeviceProvider.connect happy path after the session becomes active: DeviceProvider.connect via AnalyticsManager.deviceConnected Event: closed device_vendor, enum device_type. Person: device_vendor. No free-text device names. Same shared weekly alert / connected-disconnected ratio contracts; report macOS separately from mobile.
Device Disconnected Flutter mobile BLE (iOS/Android) On the BLE disconnect callback after state cleanup: DeviceProvider.onDeviceDisconnected No event or person properties. Specified: weekly unique people and connected/disconnected ratio; not yet provisioned.
Device Disconnected macOS desktop BLE Once per ended active session from DeviceSessionCoordinator.onSessionEnded (disconnect or active unpair); unpair of an already-disconnected device emits nothing: DeviceProvider / AnalyticsManager.deviceDisconnected No event or person properties. Same shared weekly alert / connected-disconnected ratio contracts; report macOS separately from mobile.
Device Paired Flutter mobile BLE (iOS/Android) First successful connection to a device.id for the current local uid, deduped in local preferences: DeviceProvider.setConnectedDevice Event: closed device_vendor, closed hardware_family, enum-name type; hardware_id only when the device exposes a manufacturer serial, with hardware_id_kind and hardware_id_stable; the BLE transport_device_id is explicitly labeled platform_dependent. Person: has_paired_device=true, ISO-8601 first_paired_at, device_vendor, hardware_family. Specified: weekly unique people; not yet provisioned.
Device Paired macOS desktop BLE After a successful connection, once per new device ID in local preferences; a previously persisted device is seeded so an upgrade/reconnect is not mislabeled as a new pair: DeviceProvider.recordPairingAnalytics Event: closed device_vendor, enum device_type, normalized model, boolean is_first_pair. Person: has_paired_device=true, paired_device_type, device_vendor, ISO-8601 first_paired_at when known. Same shared weekly alert contract; report macOS separately from mobile.
App Session Started Flutter mobile (iOS/Android) Once at cold launch and once for each background-to-foreground transition; repeated resume callbacks without a background transition are ignored: AppSessionTelemetry Fresh opaque app_session_id; closed start_kind (coldStart or foreground). No person properties. Not alerted; mobile session/retention denominator.
App Launched Windows desktop Once when the authenticated, onboarded main app shell mounts: AppShellInner, through trackEvent $lib=omi-windows, $os=Windows, platform=windows, and authenticated distinct_id. Not alerted; Windows session/retention denominator.
Onboarding How Did You Hear Windows desktop When the Windows onboarding source is selected: Onboarding.handleHowDidYouHear, through trackHowDidYouHear Event: allowlisted source, boolean is_referral; every Windows event also carries $lib=omi-windows, $os=Windows, platform=windows, and distinct_id. Not alerted; this is the Windows transport canary. It is not a hardware-conversion event.
Onboarding Step Completed macOS desktop (Second Brain onboarding) Once on every exit from a live SBOnboardingModel.Step, including skips and already-granted permission jumps: SBOnboardingModel.advance / recordStepExit. Bounded step (enum case name), index, non-negative elapsed_ms, boolean skipped, closed exit_reason (answered / skipped / auto_granted); permission steps also send closed permission and boolean granted. skipped is true for both a user Skip and an auto-granted jump; a skip-rate must filter exit_reason=skipped, not skipped=true. Never names, roles, or page copy. Not alerted; denominator for the admin macOS onboarding funnel (web/admin/lib/onboarding-funnel.ts).
Onboarding Completed macOS desktop (Second Brain onboarding) Once when onboarding hands off to the app, on both finish and skip-the-rest: SBOnboardingModel.finishOnboardingHandoff. No event properties. Not alerted; terminal row of the admin macOS onboarding funnel.
Hardware Purchased External order-fulfilment system (not present in this repository) Not emitted today. Emit only after fulfilment and email/order identity has been authoritatively reconciled to an Omi uid, using the backend's fail-open emit_posthog_event. Checkout intent or a client redirect is not fulfilment. Planned event: order_id, normalized sku, device_vendor=omi, normalized channel, ISO country; distinct_id=uid. No person properties. Not alerted until a real fulfilment emitter exists and has two completed weeks.

Reliability and deletion outcomes

Encoded Audio Duration Measured is emitted by the live listen receiver at session teardown from authoritative decoded mono PCM bytes and negotiated sample rate. It carries recording/conversation identity, codec, decoded bytes, and audio duration; malformed frames are excluded.

Speech Positive Duration Measured is emitted by the live listen receiver at session teardown from the server VAD's cumulative speech clock. It carries recording/conversation identity, seconds, VAD mode, and the closed server_vad measurement source.

Diarization Completed is emitted after the live transcript loop drains speaker work and durably flushes assignments. It carries recording/conversation identity, distinct STT speaker count, and the closed stt_provider source; no labels or transcript content.

Event Owning surface Emission contract and authoritative emitter Key properties / person properties Alert
Recording Started Flutter mobile capture (phone mic and pendant; live and Transcribe Later) Exactly once after the native/BLE capture path confirms it started producing audio: RecordingLifecycleTelemetry, owned by CaptureController Client-minted recording_id UUID and closed `recording_source=phone_mic_live phone_mic_batch
Recording Completed Flutter mobile capture Exactly once when a started phone-mic or pendant capture stops, including controller disposal: RecordingLifecycleTelemetry Start-event fields plus non-negative duration_seconds and closed `reason=user_stopped device_disconnected
Recording Start Failed Flutter mobile capture Exactly once when an ID was prepared but capture could not start; no Recording Started event is emitted for that attempt: RecordingLifecycleTelemetry recording_id, recording_source, and closed `failure_class=permission_denied capture_unavailable
Recording Upload Started Flutter mobile offline-audio queue (iOS/Android) Once after account-cutover and rate-limit admission, immediately before every /v2/sync-local-files request: SyncUploadGate.upload Opaque upload_attempt_id; recording_id when the WAL is already bound to a conversation; file_count, total_bytes, boolean claims_live_capture, and closed upload_source=offline_audio_queue. No filenames or paths. Not alerted; denominator for upload completion/failure rate and latency.
Recording Upload Completed Flutter mobile offline-audio queue (iOS/Android) Exactly once when an admitted upload request returns HTTP 200 (completed) or 202 (accepted): SyncUploadGate.upload Start-event fields plus duration_seconds and closed `result=accepted completed`.
Recording Upload Failed Flutter mobile offline-audio queue (iOS/Android) Exactly once when an admitted upload request throws; admission blocks do not masquerade as network attempts: SyncUploadGate.upload Start-event fields plus duration_seconds and closed `failure_class=rate_limited timeout
Transcript Started Backend /v4/listen provider lane Once, when an Omi-owned live STT attempt receives its first nontrivial audio frame: LiveSTTAttempt recording_id, conversation_id when allocated, closed transcription_source, bounded stt_provider, configured stt_model, transcript_language, and bounded app_platform. uid is only the PostHog distinct_id. No transcript content. Not alerted; live transcription denominator.
Transcript Completed Backend /v4/listen provider lane Exactly once when a nonempty transcript is successfully delivered to the client WebSocket: LiveSTTAttempt.finish Start-event fields plus non-negative duration_seconds and bounded terminal phase. Not alerted; terminal success and first-transcript latency joined by recording_id.
Transcript Failed Backend /v4/listen provider lane Exactly once when an accepted live STT attempt terminates on a provider or pipeline failure before successful delivery: ListenSessionRuntime._finish_live_transcription Start-event fields plus non-negative duration_seconds and bounded failure phase. Raw provider errors are excluded. Not alerted; terminal failure numerator joined by recording_id.
Transcript Cancelled Backend /v4/listen provider lane Exactly once when accepted audio ends normally before any nonempty transcript is delivered: ListenSessionRuntime._finish_live_transcription Start-event fields plus non-negative duration_seconds and phase=teardown. Not alerted; separate from failures so silence/user cancellation does not inflate failure rate.
Speaker Identity Proposed Backend /v4/listen speaker identification Once for each speaker-label suggestion sent to the capture client: ListenSessionRuntime.emit_speaker_suggestion recording_id, conversation_id, numeric session-local speaker_id, booleans matched_existing_person and auto_assign_enabled, and closed proposal_source=live_speaker_identification. Person IDs and names are excluded. Not alerted; proposal denominator joined to the recording.
Speaker Identity Confirmed Backend conversation speaker-assignment mutations After the updated transcript segments are durably written by the single-segment, whole-speaker, or bulk assignment endpoint: conversations.py conversation_id, closed `confirmation=accepted corrected, closed assignment=self
Task Extracted Backend conversation post-processing After transcript-derived action items enter the canonical candidate path or are durably written to the legacy projection: _save_action_items task_count, identical conversation_id and legacy-compatible memory_id, closed task_source=transcript, and closed `persistence_path=canonical_candidate legacy_projection`. No task descriptions.
Task Assignee Corrected Backend canonical action-item update After an action item's owner changes and the updated task is read back successfully: update_action_item action_item_id, conversation_id when present, closed previous_assignee and new_assignee (`user other
Device Session Ended Flutter mobile BLE (iOS/Android) When setConnectedDevice(null) closes a session that has a recorded start: DeviceProvider.setConnectedDevice Native duration_seconds, bounded reason, and raw hci_reason_code when available; local duration/unknown fallback; closed device_vendor, normalized model and firmware_revision, reconnect_attempt_count (currently 0 because native retry starts after emission). No person properties. Not alerted; reliability trend segmented by platform/vendor/model/firmware.
Mobile Background Resource Session Flutter mobile (iOS/Android) Once on foreground resume after at least 60 seconds backgrounded: BackgroundResourceTelemetry, with lifecycle ownership in HomePage Opaque background_session_id; duration; start/end recording state, connected booleans, and enum device type; batch/foreground-task booleans; Dart BLE/WebSocket byte deltas and rates; iOS native offline-writer byte/packet totals for the same background window; bounded BLE disconnect, timeout, fail-to-connect, reconnect, and history-saturation diagnostics. No device ID/name, audio, transcript, or location. Not yet alerted; root-cause dataset for elevated iOS background energy reports.
Delete Account Confirmed Flutter mobile and macOS desktop User confirms deletion, before the backend wipe: DeleteAccountPage and SettingsContentView No event or person properties. Not alerted; intent denominator only. It is not proof that the wipe completed.
Account Deletion Wipe Completed Backend account-deletion worker Only after required derived-data deletion and authoritative Firestore deletion succeed; completion-status persistence is then attempted: background_wipe_user_data duration_seconds, vectors_deleted, recordings_deleted, required/best-effort failure counts, bounded operation names in failed_operations. No uid property beyond PostHog distinct_id. Specified: weekly unique people; not yet provisioned.
Account Deletion Wipe Failed Backend account-deletion worker/reconciler On a wipe exception and when the reconciler claims a stale running wipe: background_wipe_user_data and reconcile_pending_deletion_wipes Bounded operation names in failed_operations, non-negative retry_count, boolean terminal. No raw error and no uid property beyond distinct_id. Not alerted by the weekly volume contract; investigate alongside the completed/confirmed gap.

Other regression-alert events

Event Owning surface Emission contract and authoritative emitter Key properties / person properties Alert
Sign In Completed macOS desktop After a successful Apple or Firebase-provider sign-in: AuthService Bounded auth provider. No event-level email/name. Specified: weekly unique people; not yet provisioned.
Account Created Flutter mobile OAuth Once when Firebase's successful credential result authoritatively reports isNewUser=true: AuthenticationProvider is_first_auth=true, bounded auth provider, and mobile_oauth acquisition source. Identify also sets auth_method, UTC user_created_at, and closed user_role. Not alerted; account acquisition denominator.
Memory Created Flutter mobile and macOS desktop After a server conversation/recording is created and reconciled: CaptureController, AppState+ListenEvents, and TranscriptionStorage Mobile: bounded memory_result, conversation_source, language and shape/count fields plus recording hardware type and firmware revision (not_applicable for phone); macOS: bounded conversation_source plus duration_seconds when known. No transcript text. Specified: weekly unique people; not yet provisioned.
Chat Message Sent Flutter mobile and macOS desktop On the user-send boundary: MessageProvider and the macOS chat surfaces through AnalyticsManager.chatMessageSent Message length/count only, attachment/context booleans and counts, bounded source; no message text. No person properties. Specified: weekly unique people; not yet provisioned.
Upgrade Succeeded Flutter mobile After the subscription purchase/restore result succeeds: PlansSheet No event or person properties. Specified: weekly unique people; not yet provisioned.
Firmware Update Started/Completed/Failed Flutter mobile Omi pendant DFU At the authoritative Nordic DFU or MCU Manager start and terminal callbacks: FirmwareMixin Opaque attempt ID, closed protocol, from/to firmware versions, and bounded failure class. Native error messages and device IDs are excluded. Not alerted; firmware reliability funnel.
Subscription Plan Changed Flutter mobile After a reactivation or checkout returns success: PlansSheet Closed previous/new plan identifiers, billing interval, and mobile_checkout source. Not alerted; subscription transition analysis.

Mobile search-completion events (Search Query Entered, Conversation Detail Search Query Entered, Fact Searched, and Apps Searched) share the content-free fields query_length, query_word_count, results_count, and closed search_surface. Raw query text is never emitted.

Conversation Created is not an Omi PostHog event: both current conversation emitters retain the historical name Memory Created.