Ratings & Feedback Loops (iOS-first)
This page documents how DreamStream collects App Store ratings and user feedback in a way that:
- happens at the right time (after value),
- respects iOS system limits, and
- avoids “review gating” patterns.
Goals
- Increase review volume without sacrificing review quality.
- Capture negative sentiment privately (Feedback Modal) so issues are fixed before they become public 1‑stars.
- Make prompts rare and respectful so they don’t harm retention.
1) In‑app review prompt (iOS system sheet)
What users see
Users may occasionally see the iOS system rating/review prompt (the native Apple UI). DreamStream can request it, but iOS decides whether to show it.
When we request it
DreamStream requests a review only after early “delight” milestones:
- After 2 dreams logged
- After a share or download (high‑delight action)
- After a streak milestone (3+ days)
We do not request reviews during onboarding.
Frequency limits (iOS behavior)
iOS rate‑limits the system prompt (Apple documents a limit of 3 requests per 365 days per app), and the OS may ignore a request entirely. Plan review volume accordingly.
Implementation map
- Gating + cooldowns:
src/services/ratingPromptService.ts - Trigger points:
App.tsx(after dream logging, streak close, share/download) - Native call:
src/services/nativeService.ts→requestInAppReview()
Plugin requirement
The code calls the Capacitor in‑app review plugin via runtime lookup. To enable the native prompt, install and sync:
npm i @capacitor-community/in-app-reviewnpx cap sync ios
2) Feedback pulse (separate from ratings)
Why this exists
Ratings are rate‑limited and public. We also need a private check‑in loop that:
- surfaces product issues,
- captures feature requests,
- and gives users a “vent” path that doesn’t go to public reviews.
What users see
An occasional “Quick check‑in” modal with a single CTA:
- Send Feedback → opens the existing
FeedbackModal
When it can show (rare)
The pulse is intentionally infrequent and only shows after meaningful usage, e.g.:
- After 5 dreams logged, or
- After a 7‑day streak milestone
It has a long cooldown (45 days) and a small lifetime cap.
Implementation map
- Gating + cooldowns:
src/services/feedbackPulseService.ts - UI modal:
components/FeedbackPulseModal.tsx - Trigger points:
App.tsx(after dream logging + streak close)
Analytics
We track when we attempt a review request and when we show/click the feedback pulse (without sending dream content).
See analytics-tracking.md for the event list.