Push notifications are easy to deliver and hard to deserve. UltraFit360 sends pushes through Firebase Cloud Messaging, which unifies APNs (iOS) and FCM (Android) under one API. The technical setup is solved; the discipline is what matters.
The delivery layer
Cloud Functions handle push composition. A workout-reminder push reads the user's schedule from Firestore, decides whether to send based on time-of-day rules, and ships to FCM. The same code path handles iOS and Android — APNs token registration is automatic on first install.
The discipline layer
The hard problem isn't delivery — it's knowing when not to send. UltraFit360 enforces a few rules:
- Maximum 3 pushes per user per day, regardless of trigger
- No pushes between 9pm and 7am in the user's timezone
- Reminder pushes skip if the user already opened the app that day
- Marketing pushes go through a separate channel with opt-in default-off
- Every push category can be toggled in settings — granular, not all-or-nothing
What we measure
Open rate on every category, churn rate within 7 days of a push burst, opt-out rate per category. A push that drives opens but increases churn is a net loss — the studio kills those categories quickly.
Rich pushes
iOS notification service extensions decorate workout-complete pushes with the user's photo and a heart-rate chart. Android notification channels carry the same payload. Rich pushes are reserved for moments that earn attention — not every event.
The metric that decides whether a push was worth sending
Open rate is the seductive metric and the wrong one to optimise alone. A push that drives opens but increases the next-week uninstall rate is a net loss — you bought a session and paid with a user. So we watch churn within seven days of a push burst alongside opens. A notification category that lifts opens and lifts churn gets killed, no matter how good the open rate looks in isolation.
Rules that keep us welcome on the lock screen
- A hard cap of three notifications per user per day, whatever the triggers say
- Nothing between 9pm and 7am in the user's own timezone
- A reminder is suppressed if the user already opened the app that day
- Every category is individually toggleable — granular, never all-or-nothing
