Subscribe to Jacob’s Tech Tavern for free to get ludicrously in-depth articles on iOS, Swift, tech, & indie projects in your inbox every two weeks.
Paid subscribers unlock Quick Hacks, my advanced tips series, and enjoy exclusive early access to my long-form articles.
I’m proud of my app review track record.
It’s really simple to consistently get rated ~4.8* on the App Store.
Not easy as such. Simple.
Don’t believe me? I’ll demonstrate it at the end. Mathematically.
There are just 2 concepts to understand. One technical, one design:
You don’t get what you don’t ask for.
Identifying your wow moments.
Look, it’s table stakes to have an app without any bugs, crashes, or accessibility-related snafus.
Every time you frustrate your user from doing what they want, you risk a one-star rating that hobbles your average. I’m not here to discuss that.
You don’t get what you don’t ask for
Users aren’t often compelled to go to all the bother of opening the App Store, searching your app, and leaving a grumpy 1* review.
This rigmarole is reserved for especially crappy experiences.
Therefore, the majority of your app reviews should come when you ask for review. This is really easy via the StoreKit APIs in iOS.
SwiftUI
Asking for a review is trivial in a SwiftUI app. You simply invoke the requestReview
environment value.
import StoreKit
@Environment(\.requestReview) var requestReview
@AppStorage("hasRequestedAppReview")
var hasRequestedAppReview: Bool = false
// ...
func requestReview() {
if !hasRequestedAppReview {
requestReview()
hasRequestedAppReview = true
}
}
Here, requestReview()
is the one-liner which does it all for you.
The environment property calls the
RequestReviewAction
instance directly, because internally it defines acallAsFunction()
method.
I’m also adding user defaults here via @AppStorage
— this prevents us asking multiple times in this context, so we don’t spam (and annoy) our users.
UIKit
The traditional approach to requesting app review is a little more verbose, but gives you more control (read: allows you to store your logic outside of a View
, thank you very much).
Create a manager which finds a scene from your UIApplication
singleton, then requests a review on that scene.
import StoreKit
public enum AppStoreReviewManager {
public static func requestReview() {
SKStoreReviewController.requestReviewInCurrentScene()
}
}
private extension SKStoreReviewController {
static func requestReviewInCurrentScene() {
if let scene = UIApplication.shared.connectedScenes
.first(where: {
$0.activationState == .foregroundActive
}) as? UIWindowScene {
requestReview(in: scene)
}
}
}
For each app, Apple imposes a hard limit of 3 review requests per year, which should compel you to avoid wasting requests.
In practice, this means:
Avoid asking in the same context more than once.
‘Debounce’ requests by spacing them out by least a day, so a user isn’t overwhelmed if they go through multiple ‘wow’ paths of your app.
UserDefaults
is our friend here, as it’s simple to store a ‘last request date’ and flags for each context from which we’ve already requested a review.
The wow moment
The flow for most apps looks like this:
Launch → Onboarding → Sign-up → Deliver Value
This value is why your users want the app — it’s having fun; a cool user experience; learning something; paying off the investment made during onboarding.
The important thing is it’s a wow moment. The user is the most happy with your app that they will ever be.
This is the point where you hit them with a review request.
The time-to-first-wow is a critical metric to optimise, since it has a direct impact on your app rating, user acquisition, and short-term retention. The optimal flow might look like this:
Launch → Onboarding → Deliver Value → Review Request → Sign-up
However, your product manager will probably insist you do this:
Launch → Onboarding → Sign-up → Deliver Value → Review Request
The critical path
There will always be a small number of users you simply can’t please, who were going to leave a 1* review anyway. This is inevitable.
Therefore you need to balance out this noise with a disproportionate number of users leaving a review.
This is a tricky balancing act:
On the one hand, you must ensure you request a review early on the critical path of your app, which a majority of users will see.
On the other hand, you need to maximise the probability that the users you ask are going to be happy enough to give an easy 5*.
You should make sure to embed the first wow moment in the critical path.
This is a lesson I learned the hard way:
I removed a review request from the critical path, replacing it with a request attached to a bigger wow moment.
Unfortunately, this bigger wow moment lay on a path which far fewer users experienced. This temporarily tanked our rating — because we were asking less overall, the low-level background radiation of 1* ratings became a higher proportion of total reviews.
Carbn: 4.8*
In Carbn, my former climate-action startup, the onboarding process was a lengthy 10-screen questionnaire about your eating, travel, and spending habits. From this information, we calculated your carbon footprint.
Somewhat surprisingly, more than 90% of the people who began the questionnaire finished it. We discovered that this is because the users made an investment which we promised to pay off.
In a typical bit of startup growth-hacking, we forced users to sign up after this questionnaire, but before they saw their results. Since they’d invested so much time already, this had phenomenally low drop-off.
After burning this small amount of goodwill, we showed the user a beautiful, slow-running animation which revealing their carbon footprint, alongside several nifty graphs to break it down and benchmark it against other users.
5 seconds into this — enough time to be awed, but not enough time for the novelty to wear off — we asked for an app review.
This drove an average review score of 4.8* which, at the time, was the best rating for a climate action app. Unfortunately, this wasn’t enough to convince prospective seed investors in the hellscape that was the 2022 venture capital environment.
Aviator: 4.9*
With Aviator, my recent indie project, I don’t care about making money or retention, therefore the flow is even more simple:
Launch → Deliver Value → Review Request
After requesting necessary location permissions, the app immediately displays aircraft in the sky overhead — a time-to-value of approximately three seconds.
After 20 seconds I ask for a review. I estimated that this is enough time for a user to orient themselves, find an aircraft icon on the radar, and cross-reference it with the corresponding plane in the sky, achieving that first wow moment. But, hopefully, not enough time for them to get bored and quit.
The easy value and simple flow led to a very generous 4.9* rating.
Grr moments
The evil cousin of time-to-first wow is the time-to-first grr.
As mentioned, any bug, crash, or embarrassing accessibility oversight may lead a user to take the time out of their day to locate you on the app store and give your review score a bloody nose.
More insidiously, a product team under the thumb of an evil CFO might plant a forest of dark patterns and erect Trumpian paywalls throughout your app.
These are brilliant for revenue in the short term, but they’ll strangle the life out of your app review score (let alone your brand reputation).
Review gating is dumb
One of the most proliferative dark patterns is review gating. This is a simple algorithm you’ve seen a million times before:
“Are you enjoying our app?”
(yes / no)
if yes:
GOTO → app review request
else:
GOTO → feedback request
Google’s guidelines forbid this, but for some reason Apple often tolerates the practice (though rejection for this isn’t unheard of).
Not only is this unethical, but it’s stupid.
The majority of this time, this popup happens as soon as I open the app. I’m taken away from the flow I wanted to do, and slapped with two popups in a row. This frustration often motivates me to take the time out of my day to leave a well-deserved 1* review.
Intelligent apps treat the app review request like a marriage proposal:
💍 ~ you only ask when you know what the answer is going to be ~ 💍
I did the math
It’s simple to consistently get 4.8* on the App Store.
I promised to prove it mathematically, and prove it I shall.
As I have (hopefully) hammered home; people have to have an exceptional level of negative sentiment towards your app before making the effort to leave a 1* review. Or, perhaps, they are just having a bad day.
It’s simple to cash in on our users’ goodwill. When you know about your wow moments, you can make it extremely to leave a rating. Placing these on the critical path might mean that 50% of your users, in a well-designed app, will experience the wow and see the review prompt.
With an easily-achievable 99.9% crash-free rate, bugs mostly cleared from the critical path, and 1000 users, this means…
385 users drop out of your funnel, uninterested, and never think about your app again.
1 user experiences a crash and leaves a 1* review. Ruh-roh.
4 users drop out of your funnel with such intense vitriol for the experience you subjected them to that they seek you on the store to leave a 1* rating.
2 users experienced a weird UI bug which slipped past QA, which broke their immersion and compelled them to leave a 1* review (the other 8 users who saw it simply dropped out of the funnel).
290 users reached the first wow, were asked for a review, and hit not now.
290 users reached the first wow, and were happy enough with the experience to grant you a 5* rating.
6 users made it to the wow moment, but were so offended at being asked to review that they automatically put a 1* rating.
20 users got to the wow, but everyone’s a critic and the app didn’t immediately fellate them so they left a 4* rating.
This very plausible funnel rounds out to a healthy, extremely achievable, 4.75851. When rounded to one decimal place, the app store displays a glorious 4.8* rating for your app.
Conclusion
I hope I’ve shown how you can set your sights high and aim for a stellar 4.8* app review in your projects.
All apps should hit the table stakes of being crash-free, bugs-free, and accessible. Once you know your app is solid, you can implement review requests.
Take care to design these requests in a way that places them on the critical path—alongside the wow moments which deliver value to your users.
It’s a lot of work to leave a negative app review, and so with a well-thought-out user experience, it’s straightforward to propose to your users intelligently and achieve a best-in-class score.
Thank you for reading. If you want to see some of these review request techniques in person, download my indie apps (and read their write-ups) today!
Aviator: Radar on your Phone
My Toddler Loves Planes, So I Built Her A Radar
My Toddler Still Loves Planes, So I Upgraded Her RadarCheck ’em: The Based 2FA App
The 2FA app that tells you when you get `012345`
High Performance Swift Apps
Don’t feel like to subscribing yet? Follow me on Twitter!