Skip to content
All posts

The Android In-App Review API: asking for a rating without being annoying

A practical guide to Google's In-App Review API — how it actually works, where to trigger it, and why the usual 'rate us' popup is quietly hurting your Play Store rating.

MFKAPPS 4 min read

Most “rate us” prompts on Android are a custom dialog with two buttons: one that opens the Play Store listing, one that dismisses. They show up on app launch, or after some arbitrary number of sessions, and they interrupt whatever the user was actually trying to do. The person who taps “rate” leaves your app, lands in the Play Store, and now has to write a review from scratch — friction that kills most of the intent you just captured. The person who taps “not now” has told you nothing, and you’ll probably ask again next week anyway.

Google’s In-App Review API fixes the mechanical half of this problem: a native rating sheet that appears over your app, lets the user pick stars (and optionally write a few words) without leaving, and returns them exactly where they were. It doesn’t fix the UX half — when you trigger it still matters more than how — but it removes the excuse for getting the “how” wrong.

How it actually works

The API is part of Play Core (com.google.android.play:review-ktx). You request a ReviewInfo object ahead of time, then launch the flow when you’re ready to show it:

val manager = ReviewManagerFactory.create(context)

manager.requestReviewFlow().addOnCompleteListener { request ->
    if (request.isSuccessful) {
        val reviewInfo = request.result
        manager.launchReviewFlow(activity, reviewInfo)
            .addOnCompleteListener {
                // The flow is finished — you don't get a signal on
                // whether the user actually rated. Treat this as "done,"
                // not "succeeded."
            }
    }
}

Two details catch people out. First, requestReviewFlow() can fail silently or return without ever showing a dialog — Google throttles how often the same user sees the sheet (roughly once a year per app, undocumented precisely and out of your control), so most calls in testing will complete without displaying anything. Second, the completion callback fires whether the user rated, skipped, or the quota blocked the dialog entirely. There is no onRatingSubmitted — by design, so apps can’t gate features or nag based on the result.

The part that actually matters: timing

The API being frictionless doesn’t help if you trigger it at a bad moment. The failure mode I see most often is calling requestReviewFlow() right after onCreate(), on the theory that more impressions means more reviews. It means the opposite — you’re asking before the user has any opinion, and you’re doing it while they’re mid-task on whatever brought them into the app that day.

The moment that works is right after the app has demonstrably done its job. Building Mintly, that’s the beat right after a focus session completes and the user sees their streak tick up — not the first session, but one where the app has already earned a little trust. A few concrete rules that hold across app categories:

  • Trigger on a completed positive outcome, not a fixed session count. A budgeting app after the user reconciles a month cleanly, a habit tracker after a streak milestone, a reminder app after a genuinely useful save — not “session #5.”
  • Never trigger on an error path. If something just failed or the user backed out of a flow, that’s the worst possible time to ask.
  • Rate-limit yourself even though the API rate-limits you. Google’s quota means most requests are silently no-ops, but your own trigger logic should still avoid firing on every qualifying event — once the flow has completed for a user, don’t call it again for months, even if your own tracking can’t confirm whether it displayed.
  • Never combine it with your own pre-prompt. A custom “enjoying the app?” dialog that gates the real one just reintroduces the two-tap friction the API exists to remove, and it lets you filter who sees the real prompt — which is exactly the gaming Google’s review guidelines prohibit.

What it can’t do, and what people try anyway

You cannot detect whether the user actually left a rating, read the star value, or redirect unhappy users away from the flow and happy users toward it. That last one is a common ask and it’s explicitly against Play’s developer policy — the whole point of the API is that everyone who triggers it gets the same unfiltered sheet. If you want a “having a rough time?” support channel, build it as a separate, honest feedback link — not a fork in front of the review prompt.

The other limitation worth knowing: it’s Play-only. There’s no equivalent guarantee on other Android app stores, and on those you’re back to a manual “rate us” link or the store’s own mechanism.

Testing it without burning your quota

Because real quota is opaque, test through the Play Core testing tooling rather than your production build — the com.google.android.play:review-ktx testing artifact and internal app-sharing tracks let you trigger the flow repeatedly without waiting out Google’s real-world throttle. Wire the trigger into a debug menu during development so you can fire it on demand, then remove that shortcut before release. In production, treat every call as fire-and-forget: request, launch, move on, and let Google’s own logic decide who actually sees the sheet.