Ask the store to show the rating prompt at a good moment
One.StoreReview.requestReview asks the store to consider showing the
system rating prompt. Call it after a meaningful milestone, such as a
completed task, at a moment that will not interrupt the user. The
request takes no arguments and needs no manifest settings.
On iOS it calls StoreKit’s request review in the active window scene on the main thread. On Android it runs Play In-App Review from the current activity. On web it does nothing.
import { One } from 'one'
async function afterTaskCompleted() { await One.StoreReview.requestReview()}One line at the right moment is the whole integration. The store decides everything else.
The promise resolves when the request reaches the store. It never reports whether the prompt appeared, was dismissed, or received a rating. iOS decides whether to show it under system frequency rules: development builds show the prompt for testing, TestFlight builds do not, and App Store builds follow the rules. On Android the promise resolves when the Play review flow completes; Play enforces its own quota, so repeated calls may resolve without showing anything.
A request without an active window scene rejects on iOS. A failed Play request, a missing Play Store, or no activity to present from rejects on Android.
| Methods | Type | Description |
|---|---|---|
requestReview() => Promise<void>Ask the store to consider the rating prompt. | () => Promise<void> | Ask the store to consider the rating prompt. |
| iOS | Android | Web | |
|---|---|---|---|
| Engine | StoreKit | Play review | None |
| Shows | Store decides | Quota decides | Never |
| Result | Unreported | Unreported | No effect |
| Testing | Dev builds | Test tracks | Nothing |
import { One } from 'one'
async function onFirstExport(success: boolean, asked: boolean) { if (!success || asked) return true try { await One.StoreReview.requestReview() } catch { // no scene or no store; skip quietly } return true}The flag keeps the ask to once per install, and only after a genuine success. A rejection skips quietly rather than breaking the flow.
import { One } from 'one'
async function onTenthLaunch(launches: number, asked: boolean) { if (launches < 10 || asked) return asked await One.StoreReview.requestReview() return true}Counting launches in app storage spaces the ask away from onboarding, when the user has enough experience to rate fairly.
Edit this page on GitHub.