Feature SDKs
How to ask for app ratings at the right time in Flutter
Free Reference for rating_review_sdk: every variable, option and package it generates. Command: archipelago generate rating_review_sdk
Generate the Rating & Review SDK, set the five prompt gates at runtime, record sessions and key events, and read why prompts were skipped.
What you'll learn
- Generating the Rating & Review SDK
- Configuring the five-gate prompt evaluation system at runtime
- Recording sessions and key events to drive the rating prompt
- Using the analytics-friendly decision API to track why prompts were skipped
- Understanding platform availability constraints on iOS and Android
Prerequisites
- An existing Archipelago monorepo (see Monorepo Scaffolding)
Step 1: Generate the Rating & Review SDK
archipelago generate rating_review_sdkThe brick has no generation variables. All configuration happens at runtime through RatingPromptConfig in your DI module.
The brick generates storage_sdk and package_info_provider for you if they are missing. It saves counters through StorageProvider under the rating_review namespace. A logout does not clear them.
Step 2: Understand the Generated Structure
The Rating & Review SDK uses the API/Impl split pattern:
features/
└── rating_review/
├── rating_review_api/ # RatingReviewSDK contract + RatingPromptConfig + decision types
└── rating_review_impl/ # Gate evaluation, persistence, and platform review request
└── lib/src/
├── rating_review_sdk_impl.dart
├── data/ # Local storage for session/event counts
├── di/ # RatingReviewImplPackageModule
└── domain/ # Gate evaluation logicFeatures that trigger the rating prompt depend only on rating_review_api.
The post-generation hook registers RatingReviewImplPackageModule in lib/di/injector.dart. The SDK is a lazy singleton. Nothing runs at boot.
Step 3: Configure the Prompt Gates
Provide RatingPromptConfig in your app DI module before RatingReviewImplPackageModule runs:
// apps/<appName>/lib/di/app_di_module.dart
@module
abstract class AppDIModule {
@lazySingleton
RatingPromptConfig get ratingPromptConfig => const RatingPromptConfig(
minSessions: 3, // Minimum app launches before showing the prompt
minKeyEvents: 2, // Minimum positive moments before showing the prompt
cooldownDays: 30, // Days to wait before asking again after a dismissal
askOncePerVersion: true, // Reset gates when the app version changes
iosAppStoreId: 'YOUR_APP_STORE_ID', // Required for openStoreListing() on iOS
);
}The five gates are evaluated in order on each shouldRequestReview() call:
- Platform availability:
in_app_reviewis supported on this device/OS version - Session threshold: recorded sessions ≥
minSessions - Key event threshold: recorded key events ≥
minKeyEvents - Cooldown: enough days have passed since the last prompt
- Per-version gate: not yet shown in this app version (when
askOncePerVersionis true)
All five must pass for the prompt to show.
Step 4: Record Sessions and Key Events
Call recordSession() once per app launch, early in your post-launch phase:
// In a post-launch initializer
await ratingSDK.recordSession();Call recordKeyEvent() after a meaningful positive moment, such as a finished checkout or a successful upload:
// In your order confirmation screen or usecase
await getIt<RatingReviewSDK>().recordKeyEvent('checkout_completed');
await getIt<RatingReviewSDK>().recordKeyEvent('photo_shared');Key event names are free-form strings. Use them to tell event types apart in your analytics.
Step 5: Show the Rating Prompt
Check the gates and show the prompt after a positive moment:
final ratingSDK = getIt<RatingReviewSDK>();
await ratingSDK.recordKeyEvent('subscription_activated');
if (await ratingSDK.shouldRequestReview()) {
await ratingSDK.requestReview();
}requestReview() delegates to the platform's native in-app review UI. On iOS this is SKStoreReviewController. On Android it is the Google Play In-App Review API. The OS decides whether the dialog appears. Calling requestReview() is a request, not a guarantee.
Step 6: Use the Decision API for Analytics
evaluatePromptDecision() returns a typed decision instead of a boolean, which lets you track skip reasons without duplicating the gate logic:
final ratingSDK = getIt<RatingReviewSDK>();
final decision = await ratingSDK.evaluatePromptDecision();
switch (decision) {
case RatingPromptDecisionShow():
await ratingSDK.requestReview();
analytics.track('rating_prompt_shown');
case RatingPromptDecisionSkip(:final reason):
analytics.track('rating_prompt_skipped', {'reason': reason.name});
// reason.name is one of: 'platformUnavailable', 'sessionThreshold',
// 'keyEventThreshold', 'cooldown', 'perVersionGate'
}Use this to measure how often each gate suppresses the prompt.
Step 7: Link to the Store Listing
After a positive review or to let users rate manually from a settings screen:
// Opens App Store (iOS) or Play Store (Android) listing
await getIt<RatingReviewSDK>().openStoreListing();On iOS, iosAppStoreId must be set in RatingPromptConfig for this to work. On Android, the Play Store app page is derived from the app's package name automatically.
Platform Notes
| Platform | Availability |
|---|---|
| iOS | Available when iosAppStoreId is set and the app is on the App Store |
| Android | Requires the app to be published (internal testing track is sufficient) |
| Debug builds | isAvailable() returns false on Android. The Play Store API needs a production or testing track build |
| iOS simulator | Review requests are silently ignored by the OS |
If isAvailable() returns false, shouldRequestReview() will also return false via the platform availability gate, so your feature code needs no special handling.
Common Customizations
| Goal | What to do |
|---|---|
| Lower threshold for testing | Set minSessions: 1, minKeyEvents: 1 in a debug DI override |
| Disable per-version gating | Set askOncePerVersion: false |
| Show prompt after a specific screen only | Call shouldRequestReview() in that screen's initState or onResume |
| Reset all counters | Call ratingSDK.reset() (useful for QA) |
| Surface the prompt after onboarding | Record a 'onboarding_completed' key event at the end of onboarding |
Next Steps
- Set up monitoring to capture exceptions if
requestReview()fails on older OS versions - Configure analytics to track
rating_prompt_skippedevents by gate reason