Skip to content

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

  1. Increase review volume without sacrificing review quality.
  2. Capture negative sentiment privately (Feedback Modal) so issues are fixed before they become public 1‑stars.
  3. 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.tsrequestInAppReview()

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-review
  • npx 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.


← Back to Playbook