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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user