Analytics
Every screen fires through one AnalyticsTracker protocol via @Environment(\.analytics) — available to any view, not just DeliciousKit's own onboarding/paywall/settings views. DeliciousKit ships ConsoleAnalytics (prints to the console), NoopAnalytics (drops everything), and CompositeAnalytics (fans out to several trackers at once — e.g. PostHog + console in debug).
Event vocabulary
AnalyticsEvent is the base vocabulary every app inherits for free — onboarding funnel, paywall, purchases, sign-in/account lifecycle, permission prompts, and settings actions. Use .custom(name:params:) for app-specific events: keep names short, snake_case, and params flat with low cardinality (no raw IDs or free text) so events stay aggregable.
PostHog
import DeliciousKitPostHog:
.environment(\.analytics, PostHogAnalyticsTracker(apiKey: "phc_xxx"))
Every AnalyticsEvent case maps to a flat snake_case event name (e.g. .onboardingCompleted → "onboarding_completed", .purchaseFailed(reason:) → "purchase_failed" with a reason property). .custom(name:params:) passes through as-is.
Mixpanel
import DeliciousKitMixpanel — same event-name mapping as PostHog, so switching backends (or running both via CompositeAnalytics) doesn't change what shows up in either dashboard:
.environment(\.analytics, MixpanelAnalyticsTracker(token: "your-mixpanel-token"))
Firebase Analytics & Crashlytics
import DeliciousKitFirebaseAnalytics ships two separate trackers — combine them with CompositeAnalytics if you want both:
.environment(\.analytics, CompositeAnalytics([
FirebaseAnalyticsTracker(),
FirebaseCrashlyticsTracker(),
]))
FirebaseCrashlyticsTracker doesn't send events to a dashboard — it logs each AnalyticsEvent as a Crashlytics breadcrumb, so your event trail is visible on the timeline of any crash report.
Running more than one backend
.environment(\.analytics, CompositeAnalytics([
PostHogAnalyticsTracker(apiKey: "phc_xxx"),
ConsoleAnalytics(), // handy while developing
]))