PostHog Analytics Custom Events in SwiftUI
A thousand undifferentiated events answers nothing. The work is choosing the handful that map to real product questions.
TL;DR
Custom-event analytics records the specific actions that answer product questions, not just screen views, and the trap most apps fall into is instrumenting everything and drowning in noise. Good analytics is a deliberate taxonomy: a small set of well-named events (object_action, one tense) with structured properties, designed backward from the questions you want answered, where one feature_used event with a property beats fifty near-duplicate events. Wire PostHog's iOS SDK behind a thin analytics layer so views call your abstraction not PostHog, gate everything on consent and ATT, never put PII in properties, and identify users with a stable ID that stitches the journey. A free VP0 design supplies the screens; analytics is the instrumentation underneath.
What is custom-event analytics, and why do most apps get it wrong?
Recording the specific actions that matter in your app, button tapped, paywall viewed, onboarding finished, rather than just screen views, so you can answer real product questions. PostHog (an open-source product-analytics platform with over 34,000 GitHub stars) has an iOS/Swift SDK, and “custom events” means you define and send your own named events with properties. The trap most apps fall into is the opposite of too little: they instrument everything, drown in noise, and still cannot answer the one question they care about, because a thousand undifferentiated events is as useless as none.
The honest framing first: good analytics is a deliberate event taxonomy, not a firehose. The work is not wiring the SDK (that is an afternoon), it is deciding which handful of events actually answer your product questions and naming them consistently, so that six months from now the data means something. An app that thinks analytics is “add tracking everywhere” has built a haystack; an app that thinks in events tied to questions has built an answer.
What does a good event taxonomy look like?
A small set of well-named events with structured properties, designed backward from the questions you want answered:
| Question | The event | Key properties |
|---|---|---|
| Where do users drop in onboarding? | onboarding_step_completed | step number, variant |
| Does the paywall convert? | paywall_viewed, subscription_started | source, plan, price |
| What features get used? | feature_used | feature name, context |
| Why do users churn? | session_started, key actions | the sequence before they leave |
Two disciplines make this work. Consistent naming: object_action in one tense (paywall_viewed, not a mix of viewPaywall and PaywallShown), because inconsistent names fragment the data and make funnels impossible to build. And properties over event proliferation: one feature_used event with a feature property beats fifty separate events, because properties let you slice one clean event a hundred ways while fifty events just clutter. This is the same name-things-deliberately discipline as a good Cursor rules file, applied to data instead of code.
How does the SwiftUI integration actually run?
Through the SDK, with a thin wrapper so tracking does not litter your views. Initialize PostHog once at launch, then capture events at the points that matter, but the pattern that keeps it clean is not calling the SDK directly from every SwiftUI view; instead a small analytics layer (a protocol with one track(_ event:) method) means views call your abstraction, not PostHog, which keeps the SDK swappable and the call sites readable. Screen views can auto-capture, but the custom events, the ones that answer questions, are deliberate calls at the moment the action happens.
The honesty that matters here is privacy and consent, because analytics is user data. Three rules: respect App Tracking Transparency and consent (do not send events the user declined), never put personally identifiable information in event properties (an event is “subscription_started”, not the user’s email), and minimize, collecting the events you will actually use rather than hoovering everything. The same data-minimization posture as any GDPR-aware build applies: analytics that quietly over-collects is both an ethics and a compliance problem, and PostHog supports the consent-gating to do it right.
What completes a real analytics setup?
The parts that turn events into decisions. Identify users carefully (a stable anonymous ID, upgraded to a real ID on login, so a user’s journey stitches across sessions without leaking identity), define a few funnels that match your real questions (onboarding completion, paywall conversion), and instrument feature flags / experiments through the same SDK if you run them, since PostHog does both. And resist the urge to add events reactively: every event should trace back to a question someone will actually ask, or it is noise you will pay to store and have to ignore.
The screens are unaffected by analytics, that is the point of the thin wrapper, but the product decisions analytics enables are why it matters. A free VP0 design gives the agent the screens; the analytics layer is the instrumentation underneath, and the discipline is keeping it a deliberate taxonomy rather than tracking sprinkled across every tap. The A/B-testing half of this, measuring the right outcome, is covered in onboarding A/B testing.
Key takeaways: PostHog custom events in SwiftUI
- Analytics is a deliberate taxonomy, not a firehose: a thousand undifferentiated events answers nothing; design events backward from questions.
- Consistent naming and properties over proliferation:
object_actionone tense, onefeature_usedwith a property beats fifty events. - Wrap the SDK behind a thin analytics layer: views call your abstraction, not PostHog, keeping call sites clean and the SDK swappable.
- Privacy is non-negotiable: respect consent and ATT, never put PII in properties, and minimize to what you will use.
- Identify carefully and build a few real funnels: stitch the journey with a stable ID, and tie every event to a question someone will ask.
Frequently asked questions
How do I add PostHog custom events to a SwiftUI app? Initialize the PostHog SDK at launch, then capture deliberately-named events (object_action, one tense) at the moments that matter, called through a thin analytics layer rather than directly from views. Design the event set backward from your product questions, and gate it on user consent. A free VP0 design supplies the screens the instrumentation sits beneath.
How many analytics events should an app track? A small, deliberate set, not everything: a thousand undifferentiated events answers no question and just costs storage. Design events backward from the questions you want answered (onboarding drop-off, paywall conversion, feature use), and prefer one event with structured properties over many near-duplicate events.
Should I call the analytics SDK directly from SwiftUI views? No: wrap it behind a thin analytics layer, a protocol with a track method, so views depend on your abstraction rather than PostHog directly. That keeps call sites readable, the SDK swappable, and lets you gate consent and strip PII in one place rather than scattered across every view.
How do I name analytics events consistently? Use one convention, object_action in a single tense (paywall_viewed, subscription_started), applied everywhere, because mixing styles like viewPaywall and PaywallShown fragments the data and makes funnels impossible. Consistent naming is what lets you build reliable funnels and slice events months later.
What are the privacy rules for app analytics? Respect App Tracking Transparency and user consent so you do not send events the user declined, never put personally identifiable information in event properties, and minimize collection to the events you will actually use. Analytics that over-collects or carries PII is both an ethics problem and a GDPR/ATT compliance risk.
More questions from VP0 vibe coders
How do I add PostHog custom events to a SwiftUI app?
Initialize the PostHog SDK at launch, then capture deliberately-named events (object_action, one tense) at the moments that matter, called through a thin analytics layer rather than directly from views. Design the event set backward from your product questions, and gate it on user consent. A free VP0 design supplies the screens the instrumentation sits beneath.
How many analytics events should an app track?
A small, deliberate set, not everything: a thousand undifferentiated events answers no question and just costs storage. Design events backward from the questions you want answered (onboarding drop-off, paywall conversion, feature use), and prefer one event with structured properties over many near-duplicate events.
Should I call the analytics SDK directly from SwiftUI views?
No: wrap it behind a thin analytics layer, a protocol with a track method, so views depend on your abstraction rather than PostHog directly. That keeps call sites readable, the SDK swappable, and lets you gate consent and strip PII in one place rather than scattered across every view.
How do I name analytics events consistently?
Use one convention, object_action in a single tense (paywall_viewed, subscription_started), applied everywhere, because mixing styles like viewPaywall and PaywallShown fragments the data and makes funnels impossible. Consistent naming is what lets you build reliable funnels and slice events months later.
What are the privacy rules for app analytics?
Respect App Tracking Transparency and user consent so you do not send events the user declined, never put personally identifiable information in event properties, and minimize collection to the events you will actually use. Analytics that over-collects or carries PII is both an ethics problem and a GDPR/ATT compliance risk.
Part of the Native Apple & SwiftUI: The iOS Ecosystem hub. Browse all VP0 topics →
Keep reading
School Parent Portal App in SwiftUI: A Design Guide
How to build a school parent portal in SwiftUI: the child switcher, a today-first home, absence reporting, actionable notifications, and student privacy.
Build a Mental Health Journal App in SwiftUI
A free SwiftUI pattern for a private mental health journal: mood check-ins, on-device storage, Face ID lock, and HealthKit State of Mind, all non-medical.
Build a Stock Market Heat Map Grid UI in SwiftUI
A market heat map colors and sizes tiles by gain and market cap. Here is how to build the stock market heat map grid in SwiftUI, with an accessible color scale.
Build a Booking.com-Style Availability Calendar in SwiftUI
A Booking.com-style availability picker is more than a date picker. Here is how to build the availability calendar in SwiftUI, with real open and booked dates.
Build a Sideloading iOS App Install Animation in SwiftUI
In the EU, an alt-marketplace install is a real, system-gated flow. Here is how to build the sideloading install animation in SwiftUI, honestly.
Build a Smooth, Scrolling Social Media Feed in SwiftUI
A social media feed in SwiftUI is a scrolling list of post cards. Here is how to build it so it stays smooth with images, likes, and infinite scroll.