One of the best ways to increase App Store ranking is increase the amount and quality of the ratings and reviews that your app gets.
The goal is to request reviews from users that use your app multiple times because if they are using it more, it is more likely that they enjoy it and will rate it highly. If we were to request a review often or too early, it increases the chances of lower star ratings because the user may feed infringed upon and the inconvenience would lower your star rating
Store Review Request API
Today we are going to learn how to track sessions in and iOS app, and then request users ratings within the application after they’ve had three sessions. We can change the number of sessions if we want to but I’ve found three to a be a good number.
Apple provides an API called SKStoreReviewController
that allows us to request ratings from within our app and we can call this API after certain actions have been taken inside of the app. In this case we will request a review after three successful sessions on the next app open.
The way we will do this is to use notifications that Apple provides, UIApplication.didBecomeActiveNotification
and UIApplication.willResignActiveNotification
, to tell us when the application becomes active to start a session timer and then when the app goes into the background or terminates we will stop the timer and log the session. We can also include a minimum session time in seconds so that if the user just opens the app accidentally and closes it we can skip that and not log it as a session.
Create a new app
Go to Xcode and create a new app using a SwiftUI interface.
Create a Ratings Request Class
Inside your project, create a new File call RatingRequest.swift
import Foundation
import StoreKit
class RatingRequester {
private let userDefaultsSessionKey = "app-sessions"
private let userDefaultsSeenReviewKey = "seen-app-review"
private let notificationCenter: NotificationCenter
private let userDefaults: UserDefaults
private var minimumDuration: Int
private var sessionStartDate = Date()
public static let shared = RatingRequester(minimumDuration: 10)
private var numSessions: Int {
userDefaults.integer(forKey: userDefaultsSessionKey)
}
init(
minimumDuration: Int,
userDefaults: UserDefaults = .standard,
notificationCenter: NotificationCenter = .default
) {
self.minimumDuration = minimumDuration
self.userDefaults = userDefaults
self.notificationCenter = notificationCenter
self.registerNotifications()
}
public func showReviewIfNeeded(minimumSessions: Int) {
let seenReview = userDefaults.bool(forKey: userDefaultsSeenReviewKey)
let numSessions = numSessions
guard !seenReview, numSessions > minimumSessions else { return }
requestRating()
}
private func requestRating() {
userDefaults.set(true, forKey: userDefaultsSeenReviewKey)
DispatchQueue.main.async {
if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
SKStoreReviewController.requestReview(in: scene)
}
}
}
@objc private func startSession() {
self.sessionStartDate = Date()
}
@objc private func endSession() {
let diff = Date().timeIntervalSince1970 - sessionStartDate.timeIntervalSince1970
guard diff > Double(minimumDuration) else {
return
}
userDefaults.setValue(numSessions + 1, forKey: userDefaultsSessionKey)
}
private func registerNotifications() {
notificationCenter.addObserver(
self,
selector: #selector(startSession),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
notificationCenter.addObserver(
self,
selector: #selector(endSession),
name: UIApplication.willResignActiveNotification,
object: nil
)
notificationCenter.addObserver(
self,
selector: #selector(endSession),
name: UIApplication.willTerminateNotification,
object: nil
)
}
}
SwiftThis will allow you to call RatingRequester.shared.showReviewIfNeeded(minimumSessions: 3)
and the object will ask the system to show the review request alert to the user on the main scene.
For a session to count as a session it will need to last for at least 10 seconds. This minimum session length can be changed by changing the minimumDuration
property on the shared
instance.
Also after the review gets requested a flag is set in the UserDefaults that will block the review from being requested again in the future when showReviewIfNeeded
is called. If you want to keep attempting to show the review you can remove this check by removing the seenReview
variable and guard statement inside the showReviewIfNeeded
method.
Note: Per Apple’s documentation there is no way to know if the review box was actually shown or can we know what the review is. Alls we can do is request the rating and the system handles the rest:
Add RatingRequester to your app
So in order for the alert to be shown we will need to call the RatingRequester.shared.showReviewIfNeeded
method in the SceneDelegate if we’re building a UIKit application or in the ContentView if we’re building a SwiftUI app:
...
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
// Bootstrap your apps UI...
RatingRequester.shared.showReviewIfNeeded(minimumSessions: 3)
}
...
SwiftOr for SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
.padding()
.onAppear {
RatingRequester.shared.showReviewIfNeeded(minimumSessions: 3)
}
}
}
SwiftThe Resulting Alert
After completing 3 sessions of the app for at least 10 seconds per session, on the next app load you swill see:
Hope you enjoyed this article, if you need any help feel free to get in touch!