Skip to main content

App Review — Methods

Two methods, two return types. Signatures verbatim from src/definitions.ts.

import { NativeUpdate } from 'native-update';
import type { ReviewResult, CanRequestReviewResult } from 'native-update';

canRequestReview()

canRequestReview(): Promise<CanRequestReviewResult>

Cheap pre-flight check. Returns whether all plugin-side throttles (config) currently allow a review prompt. Does not call the platform — it cannot know about Apple's silent 3-per-365 cap.

Returns CanRequestReviewResult.

const { canRequest, reason } = await NativeUpdate.canRequestReview();

if (!canRequest) {
console.log('[review] gate not met:', reason);
return;
}
await NativeUpdate.requestReview();

When canRequest is false, the reason field tells you which gate failed:

  • 'minimumDaysSinceInstall' — too soon since first install
  • 'minimumDaysSinceLastPrompt' — too soon since the last prompt
  • 'minimumLaunchCount' — too few app launches
  • 'customTriggerNotMet' — your custom trigger has not fired
  • 'platformNotSupported' — the platform cannot show a native prompt (e.g. desktop web)

requestReview()

requestReview(): Promise<ReviewResult>

Triggers the native review sheet. Calls SKStoreReviewController.requestReview on iOS and ReviewManager.launchReviewFlow on Android. The platform decides whether the user actually sees a sheet — neither API exposes that signal.

Returns ReviewResult. The displayed field is best-effort: it is true when the platform call returned without error, not a confirmation that the sheet was visible.

Throws REVIEW_NOT_SUPPORTED (Play Services missing on Android, jailbroken iOS without StoreKit), CONDITIONS_NOT_MET (plugin-side throttle blocked the call — same reasons canRequestReview() returns false).

try {
const result = await NativeUpdate.requestReview();
if (result.displayed) {
console.log('[review] prompt fired (display not guaranteed)');
} else {
console.log('[review] declined to show:', result.reason);
}
} catch (e) {
// Falls through to the web fallback URL (config.webReviewUrl)
console.error('[review] failed', e);
}

After a positive user signal — payment success, onboarding complete, sharing the app, an NPS-9 answer:

async function maybeAskForReview() {
const { canRequest } = await NativeUpdate.canRequestReview();
if (!canRequest) return;
await NativeUpdate.requestReview();
}

// Inside your "checkout success" handler:
await trackPurchase(...);
await maybeAskForReview(); // best-effort; never blocks the success UI

Never await a review call inline with critical user flows — wrap it in a fire-and-forget that catches all errors. A failed review attempt should never break a purchase confirmation.


Return types

ReviewResult

FieldTypeRequiredDescription
displayedbooleanyesBest-effort. true when the platform call returned without error. Not a confirmation that the user saw the sheet — neither Apple nor Google exposes that signal.
errorstringnoHuman-readable error if the platform call failed.
reasonstringnoIf displayed: false, why. Same set of values as CanRequestReviewResult.reason.

CanRequestReviewResult

FieldTypeRequiredDescription
canRequestbooleanyestrue if all plugin-side throttles currently allow requestReview().
reasonstringnoWhen canRequest: false, identifies which gate failed.

Common errors

CodeWhenWhat to do
REVIEW_NOT_SUPPORTEDPlay Services missing (Huawei, F-Droid, no-GMS Android), iOS without StoreKit, web without webReviewUrlFall back to opening webReviewUrl in a browser.
CONDITIONS_NOT_METPlugin-side throttle blocked the callSkip silently; respect the throttle.
QUOTA_EXCEEDEDSome platforms surface this when their internal cap is exhaustedSkip silently; quota resets eventually.

The full code list ships with the security reference in Batch 4.


Method reference verified against src/definitions.ts in the plugin repo as of 2026-05-10. Documented by Ahsan Mahmood.