Analytics events
As of 2026-10-19 (vulture-ios 3176c4cc4, vulture-android 85fd9cc6).
How events are sent
Section titled “How events are sent”| iOS | Android | |
|---|---|---|
| SDK | Mixpanel (vulture-ios/Modules/App/Sources/Services/Analytics/MixpanelAnalyticsReporter.swift) | None yet. Mixpanel is planned (TODO(analytics) in 6 places). Firebase Analytics is not used (decision P8B-D15): only Crashlytics |
| Builds | Release only. The app installs the reporter in Release alone, so Debug builds send nothing (vulture-ios/Packages/Analytics/Sources/Analytics/Analytics.swift) | LoggingSubscriptionAnalytics writes each paywall event to logcat with the tag VultureAnalytics (adb logcat -s VultureAnalytics) |
| Event name | The Analytics.Event raw value (vulture-ios/Packages/Analytics/Sources/Analytics/Event.swift) | The same names (vulture-android/data/billing/src/main/kotlin/be/fousa/vulture/data/billing/SubscriptionAnalytics.kt) |
| Opt-out | Settings › privacy toggle (Analytics.isTrackingEnabled). The site’s privacy page describes it as non-identifiable usage analytics | Local, unsynced setting isAnalyticsEnabled (vulture-android/data/prefs/.../LocalSettings.kt) |
| Property values | All strings | The logging implementation passes isTrial as a Boolean |
When Android adds Mixpanel, it must reuse the iOS names and properties exactly, so that one Mixpanel report covers both apps. Events for Apple-only surfaces (force touch, Siri, Spotlight) have no Android counterpart. Android’s app shortcuts or share actions may reuse the matching names if they are built.
Properties
Section titled “Properties”Analytics.PropertyKey. Only the paywall events carry properties.
| Key | Values | On |
|---|---|---|
trigger | launch, promoted, settings, firstLaunch, or a ProFeature raw value (severalFlights, customAirspace, debrief, thermalAnalysis, taskPlanning, recording, skySight, statistics, uploads, taskOverride, raceRanking, and on Android also syncStorage). See Subscriptions | Every paywall event |
plan | monthly, yearly: the last component of the product id | Purchase events |
isTrial | true, false | paywallPurchased |
outcome | subscribed, dismissed | paywallClosed |
error | The store error code (NSError.code on iOS, the store’s code on Android) | paywallPurchaseFailed, paywallRestoreFailed |
Events
Section titled “Events”93 events are declared in Event.swift. Notes on the columns:
- iOS sent. “Declared, never sent” ³ means the case exists, but nothing in
Modules/orPackages/reports it (checked with a search for each case name). - Android. ¹ Logged only: the event is fired with the same name and properties, but goes to logcat, not to an analytics service. ² Planned: a
TODO(analytics)marks where it will be sent (vulture-android/feature/soaringspot/.../SoaringSpotRoutes.kt,vulture-android/feature/upload/.../DefaultUploadCoordinator.kt). “No” means Android does not send it yet, whether or not the feature exists there.
| Event | Group | When | Properties | iOS sent | Android |
|---|---|---|---|---|---|
forceTouchFlightPanelCell | Force touch | The pilot force-touches the flight panel cell. | none | Yes | n/a (Apple-only) |
forceTouchTurnpointListCell | Force touch | The pilot force-touches the task list cell. | none | Yes | n/a (Apple-only) |
forceTouchLegListCell | Force touch | The pilot force-touches the leg list cell. | none | Yes | n/a (Apple-only) |
presentInFlightActionsPopup | Screens | The pilot opens the actions pop-up from the in-flight screen. | none | Yes | No |
presentPhaseSelectionPopup | Screens | The pilot opens the phase selection pop-up from the phases list pop-up. | none | Yes | No |
presentEditFlightScreen | Screens | The pilot opens the edit flight screen. | none | Declared, never sent ³ | No |
presentInFlightScreen | Screens | The pilot opens the in-flight screen. | none | Yes | No |
presentHomebaseSelectionScreen | Screens | The pilot opens the home base selection. | none | Yes | No |
presentThermalSheet | Screens | The pilot taps a thermal and opens its detail. | none | Yes | No |
presentAirspaceSheet | Screens | The pilot long-presses the map and opens the airspace detail. | none | Yes | No |
presentImportFlightSelectionPopup | Screens | The pilot opens the import selection pop-up. | none | Yes | No |
presentCompareScreen | Screens | The pilot opens the compare screen. | none | Yes | No |
presentStatisticsScreen | Screens | The pilot opens the yearly statistics screen. | none | Yes | No |
presentInFlightSkySight | Screens | The pilot opens the SkySight picker while flying. | none | Yes | No |
toggleSkySightOverlay | Functionality | The pilot toggles the SkySight weather overlay on the task map. | none | Yes | No |
toggleSatelliteOverlay | Functionality | The pilot toggles the satellite overlay on the flight map. | none | Yes | No |
shareMapSnapshot | Functionality | The pilot shares the flight map as an image. | none | Yes | No |
startMeasuring | Functionality | The pilot starts the two-finger measure gesture on a map. | none | Yes | No |
openSoaringSpotCompetition | Functionality | The pilot opens a Soaring Spot competition. | none | Yes | Planned ² |
openCharronCompetitions | Functionality | The pilot opens the Charron.line competition list. | none | Yes | No |
openFlightsFromFiles | Functionality | The pilot opens flights straight off the device, from the sidebar’s Files row. | none | Yes | No |
downloadFlightFromFlarmOverWiFi | Functionality | The pilot downloads a flight from a FLARM over Wi-Fi. | none | Yes | No |
sendTaskToFlarmOverWiFi | Functionality | The pilot sends a task to a FLARM over Wi-Fi. | none | Yes | No |
selectGlidingSport | Functionality | The pilot selects gliding in Settings. | none | Declared, never sent ³ | No |
selectParaglidingSport | Functionality | The pilot selects paragliding in Settings. | none | Declared, never sent ³ | No |
selectHangglidingSport | Functionality | The pilot selects hang gliding in Settings. | none | Declared, never sent ³ | No |
markFlightAsFavorite | Functionality | The pilot marks a flight as a favourite. | none | Yes | No |
markFlightAsContest | Functionality | The pilot marks a flight as a contest flight. | none | Yes | No |
markFlightAsFieldLanding | Functionality | The pilot marks a flight as a field landing. | none | Yes | No |
dropAFlightAndReplace | Functionality | The pilot drops a flight on the map to replace the flights shown. | none | Yes | No |
dropAFlightAndAdd | Functionality | The pilot drops a flight on the map to add it to the flights shown. | none | Yes | No |
dropAFlightFromFlightList | Functionality | The pilot drops a flight from the list on the map. | none | Yes | No |
dropAFlightFromOtherApp | Functionality | The pilot drops a flight from another app on the map. | none | Yes | No |
dropATask | Functionality | The pilot drops a task on the map to override the task of every flight shown there. | none | Yes | No |
dragASelectionOutOfTheList | Functionality | The pilot drags a picked block of flights or tasks out of the list, towards another app. | none | Yes | No |
dropFilesOnTheList | Functionality | The pilot drops flights or tasks from another app onto the list, which imports them into the library. | none | Yes | No |
dropFilesOnTheSidebar | Functionality | The pilot drops flights or tasks from another app onto the sidebar, which imports them into the library. | none | Yes | No |
centerThermal | Functionality | The pilot taps the title in the thermal sheet to centre the thermal. | none | Yes | No |
centerPhase | Functionality | The pilot taps a phase to see it on the map. | none | Yes | No |
centerInfoItem | Functionality | The pilot taps an info item to see it on the map. | none | Yes | No |
centerTurnpoint | Functionality | The pilot taps a turnpoint to see it on the map. | none | Yes | No |
requestReview | Functionality | The app asks for an App Store review. | none | Yes | No |
updateXCSoarFile | Import | A file is updated from XCSoar. | none | Yes | No |
importWaypointFileFromDisk | Import | The pilot picks a waypoint file from disk to import. | none | Yes | No |
importWaypointFileFromXCSoar | Import | The pilot picks an XCSoar waypoint file to import. | none | Yes | No |
importAirspaceFileFromXCSoar | Import | The pilot picks an XCSoar airspace file to import. | none | Yes | No |
importAirspaceFileFromOpenAIP | Import | The pilot picks an openAIP airspace file to import. | none | Declared, never sent ³ | No |
importFlightFromAction | Import from Vulture action | A flight is imported through the Vulture share action. | none | Declared, never sent ³ | No |
importWaypointsFromAction | Import from Vulture action | Waypoints are imported through the Vulture share action. | none | Declared, never sent ³ | No |
importTaskFromAction | Import from Vulture action | A task is imported through the Vulture share action. | none | Declared, never sent ³ | No |
importAirspaceFromAction | Import from Vulture action | Airspace is imported through the Vulture share action. | none | Declared, never sent ³ | No |
shareWaypointsAsSingleFile | Share | The pilot shares waypoint files as one file. | none | Declared, never sent ³ | No |
shareWaypointsAsMultipleFiles | Share | The pilot shares waypoint files as separate files. | none | Declared, never sent ³ | No |
shareAirspaceAsSingleFile | Share | The pilot shares airspace files as one file. | none | Declared, never sent ³ | No |
shareAirspaceAsMultipleFiles | Share | The pilot shares airspace files as separate files. | none | Declared, never sent ³ | No |
backupAllData | Share | The pilot backs up all data from Settings. | none | Yes | No |
uploadFlightFromFlightPanelToSkyLines | Share | A flight is uploaded to SkyLines from the flight panel. | none | Yes | Planned ² |
uploadFlightFromFlightPanelToWeGlide | Share | A flight is uploaded to WeGlide from the flight panel. | none | Yes | Planned ² |
uploadFlightFromFlightPanelToCharron | Share | A flight is uploaded to Charron.line from the flight panel. | none | Yes | Planned ² |
uploadTaskFromTaskListToWeGlide | Share | A task is uploaded to WeGlide from the task list. | none | Declared, never sent ³ | No |
shareTaskFromTaskList | Share | The pilot shares a task from the task list. | none | Yes | No |
shareTaskFromTaskPopup | Share | The pilot shares a task from the task pop-up. | none | Yes | No |
shareTaskFromFlightPopup | Share | The pilot shares a task from the flight pop-up. | none | Yes | No |
saveTaskToVulture | Share | The pilot saves a task to Vulture. | none | Yes | No |
shareTaskToCupFile | Share | The pilot shares a task as a CUP file. | none | Yes | No |
shareTaskToFlarm | Share | The pilot shares a task as a FLARM declaration. | none | Yes | No |
shareTaskToLxNavNano | Share | The pilot shares a task as an LXNAV Nano declaration. | none | Yes | No |
renameWaypoint | Task | The pilot renames a waypoint. | none | Yes | No |
cancelTask | Task | The pilot cancels a task. | none | Yes | No |
cancelTaskDuringNavigation | Task | The pilot navigates away and cancels a task edit. | none | Yes | No |
duplicateTask | Task | The pilot duplicates a task. | none | Yes | No |
reverseWaypoints | Task | The pilot reverses a task’s waypoints. | none | Yes | No |
createTaskFromShortcut | Shortcuts | A task is created from the app icon shortcuts. | none | Yes | No |
openMapFromShortcut | Shortcuts | The map is opened from the app icon shortcuts. | none | Yes | No |
startRecordingFromShortcut | Shortcuts | A recording is started from the app icon shortcuts. | none | Yes | No |
stopRecordingFromShortcut | Shortcuts | A recording is stopped from the app icon shortcuts. | none | Yes | No |
createTaskFromSiri | Siri | A task is created from Siri or Shortcuts. | none | Yes | n/a (Apple-only) |
startRecordingFromSiri | Siri | A recording is started from Siri, Shortcuts or Control Center. | none | Yes | n/a (Apple-only) |
stopRecordingFromSiri | Siri | A recording is stopped from its Live Activity (despite the name). | none | Yes | n/a (Apple-only) |
openFlightFromSpotlight | Spotlight | The pilot opens a flight from Spotlight. | none | Yes | n/a (Apple-only) |
paywallShown | Paywall | The paywall appears. | trigger | Yes | Logged only ¹ |
paywallClosed | Paywall | The paywall goes away. outcome is subscribed or dismissed. | trigger, outcome | Yes | Logged only ¹ |
paywallPurchaseStarted | Paywall | The pilot picks a plan. | trigger, plan | Yes | Logged only ¹ |
paywallPurchaseCancelled | Paywall | The pilot cancels the store’s purchase sheet. | trigger, plan | Yes | Logged only ¹ |
paywallPurchaseFailed | Paywall | A purchase fails. error is the store error code. | trigger, plan, error | Yes | Logged only ¹ |
paywallPurchased | Paywall | A purchase unlocks Pro. isTrial says whether it started a trial. | trigger, plan, isTrial | Yes | Logged only ¹ |
paywallRestoreStarted | Paywall | The pilot taps Restore. | trigger | Yes | Logged only ¹ |
paywallRestored | Paywall | A restore unlocks Pro. | trigger | Yes | Logged only ¹ |
paywallRestoreFoundNothing | Paywall | A restore finds no active subscription. | trigger | Yes | Logged only ¹ |
paywallRestoreFailed | Paywall | A restore fails. error is the store error code. | trigger, error | Yes | Logged only ¹ |
openFlightInVulture | Open in Vulture | An IGC file is opened in Vulture from another app. | none | Yes | No |
openWaypointsInVulture | Open in Vulture | A CUP file is opened in Vulture from another app. | none | Yes | No |
openAirspaceInVulture | Open in Vulture | An airspace file is opened in Vulture from another app. | none | Yes | No |
Unused iOS events
Section titled “Unused iOS events”These 14 are declared but never sent: presentEditFlightScreen, the three select…Sport events, importAirspaceFileFromOpenAIP, the four import…FromAction events, the four share{Waypoints,Airspace}As{Single,Multiple}File(s) events, and uploadTaskFromTaskListToWeGlide. Do not port them to Android as they are. Either wire them up on iOS first, or remove them on both platforms.
Some names do not match what they record. stopRecordingFromSiri fires from the Live Activity, and toggleSkySightOverlay has a doc comment left over from a removed wind-indicator event. Keep the names as they are, because renaming an event splits its history in Mixpanel.
