Analytics event glossary

July 26, 2026 · View on GitHub

Canonical client analytics contract. Emit only listed event_name values. Companion CSV: docs/analytics/event_glossary.csv. Coverage inventory: docs/analytics/glossary_emission_coverage.csv. Architecture: ARCHITECTURE.md.

SDK-backed vs custom (no double-count)

Glossary nameProduction source of truthApp action
app_openSDK Application OpenedDo not capture("app_open"). Keep captureApplicationLifecycleEvents = true.
app_backgroundSDK Application BackgroundedDo not emit custom background.
Install volume (DNI/WNI/MNI / Weekly Pulse)SDK Application InstalledKeep Weekly Pulse on Application Installed / Application Opened.
install_attributedPerson $set_once install_channelAttribution only — never a second install-count event.
deep_link_openedCustom glossary emitSDK captureDeepLinks = false.

Launch enrichment (subscription bucket, onboarding status) goes on person properties, not a second open event.

Enums

entry_point

home_hero_resume, home_hero_jump_back_in, home_hero_new_episodes, home_hero_spotlight, home_mixtape, home_adaptive_*, home_because_you_like, home_discover_grid, home_recommendations, briefing, explore_for_you, explore_trending, explore_category, explore_search_shows, explore_search_episodes, learn, podcast_detail, episode_detail, queue, downloads, history, liked, notification, deep_link, share, install_referrer, android_auto, android_auto_continue, android_auto_queue, android_auto_new_episodes, android_auto_mixtape, android_auto_downloads, android_auto_liked, android_auto_history, android_auto_discover, android_auto_voice, android_auto_play_all, mini_player, session_restore, player_up_next, smart_queue, onboarding_suggestion, unknown

Aliases (normalized in app; do not add as new enum values): learn_historylearn. Brief audio play tags briefing on playback_* (interactions remain on daily_briefing_action).

surface

home, explore, learn, library_hub, library_subscriptions, library_liked, library_downloads, library_history, podcast_detail, episode_detail, player_full, player_mini, queue_sheet, settings, onboarding, briefing, android_auto, system_notification, share_sheet

content_type

podcast, episode, briefing, mixtape, announcement, unknown

Other

  • playback_mode: stream | offline
  • client_surface: phone | android_auto
  • install_channel: play_store | apk_github | share_referrer | unknown
  • search_mode: show_keyword | episode_semantic
  • pause_reason: user_voluntary | interruption | error | sleep_timer | app_kill | auto_pause
  • subscription_count_bucket: 0 | 1_3 | 4_10 | 10_plus
  • daypart: morning | afternoon | evening | late_night

Events

event_namemeaningrequired_propertiesoptional_propertiespii_risk
app_openDAU volume via SDK Application Opened (glossary alias; not custom-emitted)— (SDK)person props for enrichmentnone
app_backgroundSession end via SDK Application Backgrounded (not custom-emitted)— (SDK)none
install_attributedChannel attribution only ($set_once install_channel); volume is Application Installedinstall_channel on personreferrer_raw; utm_source; share_tokennone
deep_link_openedInbound deep/share link handledlink_scheme:string; is_first_open:bool; cold_start:boollink_host:string; content_type:enum; podcast_id:string; episode_id:stringnone
onboarding_startedUser entered onboardingentry_point:stringis_reentry:boolnone
onboarding_flow_selectedUser chose AI/genre/search/importflow_type:string; entry_point:stringnone
onboarding_step_viewedA discrete onboarding step became visiblestep_name:string; flow_type:stringstep_index:intnone
onboarding_abandonedUser left before completelast_step:string; flow_type:stringtime_spent_seconds:int; subscribed_count:intnone
onboarding_completedUser finished an onboarding pathmethod:string; total_subscribed_count:intscreen:string; subscribed_podcasts_list:list; total_onboarding_time_seconds:float; entry_point:string; favorite_genres:list; did_scroll_suggestions:bool; did_switch_from_ai:bool; import_type:string; searches_performed:intnone
onboarding_ai_turn_submittedUser sent a message in onboarding AI chatturn_number:int; user_input_text:string; has_custom_input:boolselected_options:list; time_spent_seconds:floatlogged_by_policy
onboarding_ai_response_receivedAssistant reply returned in onboarding AIturn_number:int; options_count:intoptions_list:list; duration_seconds:float; detected_intent:string; assistant_message:stringnone
onboarding_ai_search_redirectAI suggested leaving chat for searchturn_number:intsuggested_query:stringlogged_by_policy
onboarding_ai_synthesis_completedAI produced podcast suggestionsrows_count:int; podcasts_count:intduration_seconds:floatnone
onboarding_ai_synthesis_failedAI suggestion generation failederror_message:stringnone
onboarding_search_performedSearch during onboardingsearch_query:string; results_count:intquery_length:intlogged_by_policy
onboarding_search_podcast_subscribedSubscribed from onboarding search resultpodcast_id:string; total_subscribed_count:intpodcast_name:stringnone
onboarding_import_sheet_openedOPML/import sheet shownentry_point:stringnone
onboarding_import_failedOPML/library import failedimport_type:stringerror_message:stringnone
onboarding_manual_step_completedGenre/manual onboarding step finishedstep_name:string; selections_count:intselections_list:list; time_spent_seconds:floatnone
playback_startedAudio playback startedepisode_id:string; podcast_id:string; entry_point:enum; is_resume:bool; playback_mode:enum; client_surface:enum; speed:float; is_subscribed:boolposition_seconds:float; duration_seconds:floatnone
playback_heartbeatPeriodic progress while playingepisode_id:string; podcast_id:string; entry_point:enum; position_seconds:float; playback_mode:enum; client_surface:enumduration_seconds:float; percent_complete:float; milestone:int; speed:float; is_subscribed:boolnone
playback_pausedPlayback pausedepisode_id:string; podcast_id:string; entry_point:enum; position_seconds:float; listened_delta_seconds:float; pause_reason:enum; playback_mode:enum; client_surface:enumduration_seconds:float; percent_complete:float; is_subscribed:boolnone
playback_completedEpisode reached completionepisode_id:string; podcast_id:string; entry_point:enum; listened_delta_seconds:float; playback_mode:enum; client_surface:enumduration_seconds:float; is_subscribed:bool; speed:floatnone
playback_errorPlayback failederror_type:string; entry_point:enumepisode_id:string; podcast_id:string; error_message:string; playback_mode:enum; client_surface:enumnone
playback_bufferingBuffering stall observedentry_point:enumepisode_id:string; podcast_id:string; buffer_duration_ms:int; playback_mode:enum; client_surface:enumnone
playback_seekedUser seeked in episodeepisode_id:string; podcast_id:string; entry_point:enum; from_seconds:float; to_seconds:floatseek_source:string; client_surface:enumnone
session_restore_promptResume previous session prompt shown/actedaction:stringepisode_id:string; podcast_id:string; position_seconds:floatnone
podcast_subscription_toggledUser subscribed or unsubscribedpodcast_id:string; is_subscribed:boolsurface:string; source:stringnone
notification_permission_requestedSystem permission prompt requestedsurface:stringnone
notification_permission_decidedUser granted/denied notificationsgranted:boolnone
notification_tappedUser opened a push/local notificationnotification_type:stringpodcast_id:string; episode_id:string; target_route:stringnone
notification_receivedPush/local notification deliverednotification_type:stringpodcast_id:string; episode_id:stringnone
identity_resetAnalytics identity cleared/resetreason:stringnone
app_check_statusApp Check token attempt resulttoken_obtained:bool; provider:stringnone
first_episode_playedFirst-ever play milestoneepisode_id:string; podcast_id:string; entry_point:enum; hours_since_install:floatnone
home_surface_tappedFirst-class Home component tapsurface_component:stringrail_intent:string; content_id:string; position_index:intnone
home_surface_impressionHome rail/block became visiblesurface_component:stringitems_count:intnone
search_performedUser ran show or episode searchsurface:string; search_mode:enum; search_query:string; results_count:intresult_quality:enum; query_length:intlogged_by_policy
search_result_tappedUser tapped a search resultsurface:string; result_type:enumsearch_mode:enum; podcast_id:string; episode_id:string; position_index:int; search_query:stringlogged_by_policy
learn_card_actionUser acted on a Learn cardaction:string; episode_id:string; podcast_id:stringposition_index:intnone
learn_screen_viewedLearn tab/screen openedcards_available:intnone
explore_screen_viewedExplore openedtab:stringnone
explore_recommendation_tappedFor You/trending card tappedpodcast_id:string; position_index:int; rail:stringnone
queue_modifiedQueue add/remove/reorder/clearaction:stringepisode_id:string; podcast_id:string; queue_size:int; source:stringnone
episode_liked_toggledLike/unlike episodeepisode_id:string; podcast_id:string; is_liked:boolsurface:stringnone
episode_mark_playedUser marked episode played/unplayedepisode_id:string; podcast_id:string; is_played:boolsurface:stringnone
download_requestedUser or Smart Downloads requested downloadepisode_id:string; podcast_id:string; source:stringwifi_only:boolnone
download_completedEpisode finished downloadingepisode_id:string; podcast_id:stringsource:string; bytes:long; duration_ms:longnone
download_failedDownload failederror_type:stringepisode_id:string; podcast_id:string; source:string; error_message:stringnone
smart_download_syncSmart Downloads sync ranrequested_count:int; completed_count:int; failed_count:int; cleaned_count:int; trigger:stringnone
show_notification_toggledPer-show notification preference changedpodcast_id:string; enabled:boolnone
share_contentUser shared podcast/episode/appcontent_type:enumpodcast_id:string; episode_id:string; channel:string; surface:stringnone
backup_restore_resultLibrary backup or restore finishedaction:string; success:boolitem_count:int; format:string; error_message:stringnone
feedback_submittedIn-app feedback/NPS/review handofffeedback_type:stringscore:int; source:stringnone
library_destination_viewedLibrary hub or sub-destination openeddestination:stringitem_count:intnone
podcast_detail_viewedPodcast info screen openedpodcast_id:stringis_subscribed:boolnone
episode_detail_viewedEpisode info screen openedepisode_id:string; podcast_id:stringnone
nav_tab_clickedBottom nav tab selectedtab:stringprevious_tab:stringnone
settings_interactionSettings screen view or controlaction:stringsetting_key:stringnone
feature_announcement_actionIn-app/feature announcement viewed/dismissed/actedaction:stringfeature_id:string; category:stringnone
offline_mode_enteredApp detected offline / offline UIreason:stringnone
player_chrome_interactionMini/full player or control bar actionsurface:string; action:stringnone
daily_briefing_actionBriefing impression or interactionaction:string; region:string; date:stringcontent_id:string; source:string; chapter_index:int; chapter_title:string; method:string; playback_status:string; previous_region:string; episode_id:string; episode_title:string; podcast_id:string; podcast_title:stringnone
home_import_banner_actionImport banner shown/clicked/dismissedaction:stringnone
library_history_tracking_noticeOne-time listening-history tracking reset notice shown/dismissedaction:stringnone
android_auto_connectedAuto session begansession_id:stringnone
android_auto_disconnectedAuto session endedsession_id:string; duration_seconds:intnone
android_auto_browseUser browsed Auto media treenode:stringaction:stringnone
adaptive_ranking_statusRanking engine status/updatestatus:stringdetails:stringnone
learn_caught_upUser reached Learn caught-up statecards_remaining:intnone
catalog_missCatalog/lookup misslookup_type:stringkey:stringnone
rss_refresh_failedRSS feed refresh failedpodcast_id:string; error_type:stringnone
progress_sync_anomalyProgress sync inconsistency detectedanomaly_type:stringepisode_id:stringnone
late_night_safeguard_decisionLate-night listening safeguard fireddecision:stringnone
auto_chapters_lifecycleChapters request/complete/failstage:stringepisode_id:string; error_message:stringnone
auto_transcript_lifecycleTranscript request/complete/failstage:stringepisode_id:string; error_message:stringnone
proxy_fallback_triggeredImage load fell back to proxyreason:stringnone

Person properties

propertyset_whennotes
first_seen_atfirst process$set_once
onboarding_statuspending / completed / skipped_deeplink
onboarding_methodai_chat / manual_genre / search / import / skip / deeplink_skip
install_channelfirst open
notifications_enabledpermission decide
initial_podcasts_subscribedonboarding complete
first_play_atfirst playback_started$set_once
activated_atonboarding complete + play ≤24h$set_once

Logging policy

  • Log user_input_text on AI chat turns and search_query on search events (pii_risk=logged_by_policy).
  • Before emission, scrub those fields: remove email addresses, password-like tokens, and any http(s) audio/enclosure/media URLs. Keep the remaining free-text query/message.
  • Never emit emails, passwords, or audio/enclosure URLs as standalone property values.
  • entry_point is required on all playback_* events.