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

@@ -134,6 +134,10 @@ struct BootstrappedContentView: View {
.onChange(of: scenePhase) { _, newPhase in
switch newPhase {
case .active:
// Refresh super properties (subscription status may have changed)
AnalyticsManager.shared.updateSuperProperties()
// Track subscription state with rich properties for funnel analysis
StoreManager.shared.trackSubscriptionAnalytics(source: "app_foreground")
// Sync when app comes to foreground (but not on initial launch)
if hasCompletedInitialSync {
Task {
@@ -141,6 +145,8 @@ struct BootstrappedContentView: View {
}
}
case .background:
// Flush pending analytics events
AnalyticsManager.shared.flush()
// Schedule background tasks when app goes to background
BackgroundSyncManager.shared.scheduleAllTasks()
default:
@@ -190,15 +196,19 @@ struct BootstrappedContentView: View {
}
NetworkMonitor.shared.startMonitoring()
// 7. App is now usable
print("🚀 [BOOT] Step 7: Bootstrap complete - app ready")
// 7. Configure analytics
print("🚀 [BOOT] Step 7: Configuring analytics...")
AnalyticsManager.shared.configure()
// 8. App is now usable
print("🚀 [BOOT] Step 8: Bootstrap complete - app ready")
isBootstrapping = false
// 8. Schedule background tasks for future syncs
// 9. Schedule background tasks for future syncs
BackgroundSyncManager.shared.scheduleAllTasks()
// 9. Background: Try to refresh from CloudKit (non-blocking)
print("🚀 [BOOT] Step 9: Starting background CloudKit sync...")
// 10. Background: Try to refresh from CloudKit (non-blocking)
print("🚀 [BOOT] Step 10: Starting background CloudKit sync...")
Task.detached(priority: .background) {
await self.performBackgroundSync(context: context)
await MainActor.run {