feat: add PostHog analytics with full event tracking across app

Integrate self-hosted PostHog (SPM) with AnalyticsManager singleton wrapping
all SDK calls. Adds ~40 type-safe events covering trip planning, schedule,
progress, IAP, settings, polls, export, and share flows. Includes session
replay, autocapture, network telemetry, privacy opt-out toggle in Settings,
and super properties (app version, device, pro status, selected sports).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-02-10 15:12:16 -06:00
parent 5389fe3759
commit 2917ae22b1
20 changed files with 989 additions and 23 deletions

View File

@@ -165,6 +165,8 @@ struct TripWizardView: View {
// MARK: - Planning
private func planTrip() async {
let mode = viewModel.planningMode?.rawValue ?? "unknown"
AnalyticsManager.shared.track(.tripWizardStarted(mode: mode))
viewModel.isPlanning = true
defer { viewModel.isPlanning = false }
@@ -242,18 +244,29 @@ struct TripWizardView: View {
if options.isEmpty {
planningError = "No valid trip options found for your criteria. Try expanding your date range or regions."
showError = true
AnalyticsManager.shared.track(.tripPlanFailed(mode: mode, error: "no_options_found"))
} else {
tripOptions = options
gamesForDisplay = richGamesDict
showTripOptions = true
if let first = options.first {
AnalyticsManager.shared.track(.tripPlanned(
sportCount: viewModel.selectedSports.count,
stopCount: first.stops.count,
dayCount: first.stops.count,
mode: mode
))
}
}
case .failure(let failure):
planningError = failure.message
showError = true
AnalyticsManager.shared.track(.tripPlanFailed(mode: mode, error: failure.message))
}
} catch {
planningError = error.localizedDescription
showError = true
AnalyticsManager.shared.track(.tripPlanFailed(mode: mode, error: error.localizedDescription))
}
}