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

@@ -91,6 +91,13 @@ struct HomeView: View {
.tag(4)
}
.tint(Theme.warmOrange)
.onChange(of: selectedTab) { oldTab, newTab in
let tabNames = ["Home", "Schedule", "My Trips", "Progress", "Settings"]
let newName = newTab < tabNames.count ? tabNames[newTab] : "Unknown"
let oldName = oldTab < tabNames.count ? tabNames[oldTab] : nil
AnalyticsManager.shared.track(.tabSwitched(tab: newName, previousTab: oldName))
AnalyticsManager.shared.trackScreen(newName)
}
.sheet(isPresented: $showNewTrip) {
TripWizardView()
.environment(\.isDemoMode, ProcessInfo.isDemoMode)
@@ -106,6 +113,9 @@ struct HomeView: View {
}
}
.onAppear {
let tabNames = ["Home", "Schedule", "My Trips", "Progress", "Settings"]
let activeTabName = selectedTab < tabNames.count ? tabNames[selectedTab] : "Unknown"
AnalyticsManager.shared.trackScreen(activeTabName)
if displayedTips.isEmpty {
displayedTips = PlanningTips.random(3)
}
@@ -116,7 +126,7 @@ struct HomeView: View {
}
}
.sheet(isPresented: $showProPaywall) {
PaywallView()
PaywallView(source: "home_progress_gate")
}
}
@@ -209,6 +219,10 @@ struct HomeView: View {
HStack(spacing: Theme.Spacing.md) {
ForEach(regionGroup.trips) { suggestedTrip in
Button {
AnalyticsManager.shared.track(.suggestedTripTapped(
region: regionGroup.region.shortName,
stopCount: suggestedTrip.trip.stops.count
))
selectedSuggestedTrip = suggestedTrip
} label: {
SuggestedTripCard(suggestedTrip: suggestedTrip)