Contents

theappcapital/siriusrating-ios

A non-invasive and friendly way to remind users to review and rate an iOS app.

Features

  • [x] Supports 32 languages
  • [x] Unit tested
  • [x] Dark mode compatibility
  • [x] Supports SwiftUI and UIKit
  • [x] Configurable rating conditions
  • [x] Write your own rating conditions to further stimulate positive reviews.
  • [x] Modern, sleek design
  • [x] Non-invasive prompts
  • [x] Configurable recurring prompts with back-off factors
  • [x] Create custom prompt styles

Requirements

  • iOS 13.0+
  • Swift 5.4+

Setup

Configure a SiriusRating shared instance, typically in your AppDelegate or your app's initializer. SiriusRating automatically uses your app's icon and display name in the prompt.

Simple One-line Setup

Using default configuration (e.g. in AppDelegate):

SiriusRating.setup()

For example:

//...
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    //...
    SiriusRating.setup()

    return true
}

Or with custom thresholds:

SiriusRating.setup { config in
    // Prompt thresholds
    config.daysUntilPrompt = 14
    config.appSessionsUntilPrompt = 10
    config.significantEventsUntilPrompt = 5

    // Reminder behavior
    config.daysBeforeReminding = 7

    // Decline behavior
    config.daysAfterDecliningToPromptAgain = 30
    config.declineBackOffFactor = 2.0
    config.maxPromptsAfterDeclining = 2

    // Re-prompt after rating
    config.daysAfterRatingToPromptAgain = 240
    config.maxPromptsAfterRating = 3

    // Custom conditions
    config.additionalConditions = [
        /* ... */
    ]
    config.customCondition = { dataStore in
        // Don't prompt on weekends.
        let weekday = Calendar.current.component(.weekday, from: Date())
        return weekday != 1 && weekday != 7
    }

    // Handlers
    config.didAgreeToRateHandler = { /* ... */ }
    config.didOptInForReminderHandler = { /* ... */ }
    config.didDeclineToRateHandler = { /* ... */ }

    // Misc
    config.canPromptUserToRateOnLaunch = true
}

By default, the user will be prompted to rate the app when the following conditions are met:

  • The app has been installed for at least 30 days,
  • The user has opened the app at least 15 times, and
  • The user has completed 20 significant events.

If the user selects 'Remind me later,' they will be prompted again after 7 days. If the user declines the prompt, they will be prompted again after 30 days, with a back-off factor of 2. This means that if the user declines a second time, they will be prompted again in 60 days, a third time in 120 days, and so on.

Usage

Significant event

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()

SiriusRating will validate the conditions after each significant event and prompt the user if all conditions are satisfied.

Test request prompt

To see how the request prompt will look like in your app simply use the following code.

// For test purposes only.
SiriusRating.shared.showRequestPrompt()

Available Configuration Properties

| Property | Default | Description | |---|---|---| | daysUntilPrompt | 30 | The number of days the app must be installed before prompting | | appSessionsUntilPrompt | 15 | The number of app sessions (launches or foreground entries) before prompting | | significantEventsUntilPrompt | 20 | The number of significant events before prompting | | daysBeforeReminding | 7 | The number of days to wait before reminding a user who chose "Remind me later" | | daysAfterDecliningToPromptAgain | 30 | The number of days to wait before prompting again after the user declines | | declineBackOffFactor | 2.0 | The back-off multiplier applied for each successive decline (e.g. 30, 60, 120 days). Set to nil to disable | | maxPromptsAfterDeclining | 2 | The maximum number of times the user can be re-prompted after declining | | daysAfterRatingToPromptAgain | 240 | The number of days to wait before prompting a user who has already rated | | maxPromptsAfterRating | UInt.max | The maximum number of times the user can be re-prompted after rating | | debugEnabled | false | When true, prints diagnostic information to the console. Automatically disabled in non-DEBUG builds | | canPromptUserToRateOnLaunch | false | When true, checks conditions and potentially shows the prompt on app launch or foreground |

Installation

CocoaPods

To integrate SiriusRating into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'SiriusRating'

Carthage

To integrate SiriusRating into your Xcode project using Carthage, specify it in your Cartfile:

github "theappcapital/SiriusRating-iOS"

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/theappcapital/SiriusRating-iOS.git", .upToNextMajor(from: "2.0.0"))
]

Styles

| StyleOneRequestPromptPresenter (light, default) | StyleOneRequestPromptPresenter (dark, default) | | --- | --- | | [Style One (light)] | [Style One (dark)] |

| StyleTwoRequestPromptPresenter (light) | StyleTwoRequestPromptPresenter (dark) | | --- | --- | | [Style Two (light)] | [Style Two (dark)] |

Customization

Custom rating conditions

You can write your own rating conditions in addition to the default 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
    }
    
}

Add it alongside the default conditions:

SiriusRating.setup { config in
    config.additionalConditions = [
        GoodWeatherRatingCondition(weatherRepository: WeatherDataRepository())
    ]
}

For simple conditions, you can use an inline closure instead of a class:

SiriusRating.setup { config in
    config.customCondition = { dataStore in
        // Don't prompt on weekends.
        let weekday = Calendar.current.component(.weekday, from: Date())
        return weekday != 1 && weekday != 7
    }
}

Change prompt style

SiriusRating.setup { config in
    config.requestPromptPresenter = StyleTwoRequestPromptPresenter()
}

Change texts

You can change the texts by giving the presenter a bundle that contains your custom localized strings.

SiriusRating.setup { config in
    config.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";

Change tint color

SiriusRating will automatically use the global tint color.

UIView.appearance().tintColor = .red

Or you can set it manually.

SiriusRating.setup { config in
    config.requestPromptPresenter = StyleOneRequestPromptPresenter(tintColor: .red)
}

Change app name

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 { config in
    config.requestPromptPresenter = StyleOneRequestPromptPresenter(appName: "App Name")
}

License

SiriusRating is released under the MIT license. See LICENSE for details.

Package Metadata

Repository: theappcapital/siriusrating-ios

Default branch: master

README: README.md