A modern utility that reminds your iOS app's users to review the app in a non-invasive way.
- SwiftUI and UIKit support
- Configurable rating conditions
- Write your own rating conditions to further stimulate positive reviews.
- Modern design
- Non-invasive approach
- Specification pattern used to build the rating conditions
- Recurring prompts that are configurable using back-off factors
- No need to reset usage trackers each app version
- Option to create your own prompt style
- Unit tested rating conditions
- Show prompt even while dismissing view controllers
- Xcode 11.1+
- iOS 13.0+
Configure a SiriusRating shared instance, typically in your App's initializer or app delegate's application(_:didFinishLaunchingWithOptions:)
method:
SiriusRating.setup()
By default the following rating conditions are used:
Default rating conditions |
---|
EnoughDaysUsedRatingCondition(totalDaysRequired: 30) |
EnoughAppSessionsRatingCondition(totalAppSessionsRequired: 15) |
EnoughSignificantEventsRatingCondition(significantEventsRequired: 20) |
NotPostponedDueToReminderRatingCondition(totalDaysBeforeReminding: 7) |
NotDeclinedToRateAnyVersionRatingCondition(daysAfterDecliningToPromptUserAgain: 30, backOffFactor: 2.0, maxRecurringPromptsAfterDeclining: 2) |
NotRatedCurrentVersionRatingCondition() |
NotRatedAnyVersionRatingCondition(daysAfterRatingToPromptUserAgain: 240, maxRecurringPromptsAfterRating: UInt.max) |
SiriusRating.setup(
requestPromptPresenter: StyleTwoRequestPromptPresenter(),
debugEnabled: true,
ratingConditions: [
EnoughDaysUsedRatingCondition(totalDaysRequired: 14),
EnoughAppSessionsRatingCondition(totalAppSessionsRequired: 20),
EnoughSignificantEventsRatingCondition(significantEventsRequired: 30),
// Important rating conditions, do not forget these:
NotPostponedDueToReminderRatingCondition(totalDaysBeforeReminding: 14),
NotDeclinedToRateAnyVersionRatingCondition(daysAfterDecliningToPromptUserAgain: 30, backOffFactor: 2.0, maxRecurringPromptsAfterDeclining: 3),
NotRatedCurrentVersionRatingCondition(),
NotRatedAnyVersionRatingCondition(daysAfterRatingToPromptUserAgain: 240, maxRecurringPromptsAfterRating: UInt.max)
],
canPromptUserToRateOnLaunch: true,
didOptInForReminderHandler: {
// analytics.track(.didOptInForReminderToRateApp)
},
didDeclineToRateHandler: {
// analytics.track(.didDeclineToRateApp)
},
didRateHandler: {
// analytics.track(.didRateApp)
}
)
A significant event defines an important event that occurred in your app. In a time tracking app it might be that a user registered a time entry. In a game, it might be completing a level.
SiriusRating.shared.userDidSignificantEvent()
To see how the request prompt will look like in your app simply use the following code.
// For test purposes only.
SiriusRating.shared.showRequestPrompt()
The rating conditions are used to validate if the user can be prompted to rate the app. The validation process happens after the user did a significant event (userDidSignificantEvent()
). The user will be prompted to rate the app if all rating conditions are satisfied (returning true
).
Rating conditions | Description |
---|---|
EnoughAppSessionsRatingCondition |
The rating condition that validates if the app has been launched or brought into the foreground enough times. |
EnoughDaysUsedRatingCondition |
The rating condition that validates if the app has been used long enough. |
EnoughSignificantEventsRatingCondition |
The rating condition that validates whether the user has done enough significant events. |
NotDeclinedToRateAnyVersionRatingCondition |
The rating condition that validates that the user didn't decline to rate a version of the app. If the user did decline to rate the app, validate if we can show the prompt again by checking the number of days that have passed after the user's initial decline. |
NotPostponedDueToReminderRatingCondition |
The rating condition that validates if the user didn't decline the current version of the app. With this condition we do not want to prompt the user to rate the app again if it declined to rate the current version of the app. |
NotPostponedDueToReminderRatingCondition |
The rating condition that validates if the prompt was not postponed due an opted-in reminder. If the user did opt-in for a reminder, it will check if the total number of days have passed to show the prompt again. |
NotRatedCurrentVersionRatingCondition |
The rating condition that checks if the user didn't already rate the current version of the app. We do not want to prompt the user to rate the app again if it already rated this version of the app. |
NotRatedAnyVersionRatingCondition |
The rating condition that validates that the user didn't rate any version of the app. If the user did rate the app, validate if we can show the prompt again by checking the number of days that have passed since the user's rated last. |
You can write your own rating conditions in addition to the current rating conditions to further stimulate positive reviews.
class GoodWeatherRatingCondition: RatingCondition {
private let weatherRepository: WeatherRepository
init(weatherRepository: WeatherRepository) {
self.weatherRepository = weatherRepository
}
func isSatisfied(dataStore: DataStore) -> Bool {
// Only show the rating prompt when it's sunny outside.
return self.weatherRepository.getWeather().isSunny
}
}
To make use of the new rating condition simply add it to list.
SiriusRating.setup(
ratingConditions: [
...,
GoodWeatherRatingCondition(weatherRepository: WeatherDataRepository())
]
)
StyleOneRequestPromptPresenter (light, default) | StyleOneRequestPromptPresenter (dark, default) |
---|---|
StyleTwoRequestPromptPresenter (light) | StyleTwoRequestPromptPresenter (dark) |
---|---|
You can change the presenter to the style you wish.
SiriusRating.setup(
requestPromptPresenter: StyleTwoRequestPromptPresenter()
)
You can even create your own presenter by extending from RequestPromptPresenter
.
class YourCustomStyleRequestPromptPresenter: RequestPromptPresenter {
func show(didAgreeToRateHandler: (() -> Void)?, didOptInForReminderHandler: (() -> Void)?, didDeclineHandler: (() -> Void)?) {
// Your implementation here. Make sure you call the handlers.
}
}
And implement it as follows.
SiriusRating.setup(
requestPromptPresenter: YourCustomStyleRequestPromptPresenter()
)
You can change the texts by giving the presenter a bundle that contains your custom localized strings.
SiriusRating.setup(
requestPromptPresenter: StyleOneRequestPromptPresenter(localizationsBundle: Bundle.main)
)
Then you can change the texts in your localizable strings file, for example in: Localizable.strings
.
// ...
"request_prompt_title" = "Rate %@";
"request_prompt_duration" = "(duration: less than 10 seconds)";
"request_prompt_description" = "If you enjoy using %@, would you mind taking a moment to rate it? Thanks for your support!";
"request_prompt_rate_button_text" = "Rate %@";
"request_prompt_dont_rate_button_text" = "No, thanks";
"request_prompt_opt_in_for_reminder_button_text" = "Remind me later";
SiriusRating will automatically use the global tint color.
UIView.appearance().tintColor = .red
Or you can set it manually.
SiriusRating.setup(
requestPromptPresenter: StyleOneRequestPromptPresenter(tintColor: .red)
)
SiriusRating will automatically use the app's display name in the localized texts. If you don't want to use this name you can set it manually.
SiriusRating.setup(
requestPromptPresenter: StyleOneRequestPromptPresenter(appName: "App Name")
)
CocoaPods is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate SiriusRating into your Xcode project using CocoaPods, specify it in your Podfile
:
pod 'SiriusRating'
Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate SiriusRating into your Xcode project using Carthage, specify it in your Cartfile
:
github "theappcapital/SiriusRating-iOS"
The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift
compiler.
Once you have your Swift package set up, adding SiriusRating as a dependency is as easy as adding it to the dependencies
value of your Package.swift
.
dependencies: [
.package(url: "https://github.com/theappcapital/SiriusRating-iOS.git", .upToNextMajor(from: "1.0.0"))
]
If you prefer not to use any of the aforementioned dependency managers, you can integrate SiriusRating into your project manually.
SiriusRating is released under the MIT license. See LICENSE for details.