StarsKit is a Swift library to simplify, customize and configure your iOS app rating workflow.
It can be based on a remote, local or static configuration data with optionnals properties.
- iOS 9.0+
- Swift 4+
- Xcode 9.2+
To run the example project, clone the repo, and run pod install
from the Example directory first.
StarsKit is available through CocoaPods. To install it, add the following line to your Podfile:
pod 'StarsKit'
Today we have third-parties dependencies, but the purpose is to avoid them the most.
We also want to have a quickly available library and significant customization, we use 3 dependencies:
- Extra/UIKit: our library to simplify UIKit operation code
- Jelly: a simple UI component to simplify the rating transition display
- Cosmos: a powerful and flexible stars slider UI component
The main feature of the library is to use static or dynamic (remote) configuration to show native or custom app rating screen.
If the user chooses a negative rate, he will be redirected to the feedback screen. If the user chooses a positive rate, he will be redirected to the Store review screen.
You and only you choose what to do when the user chooses to give a feedback, like:
- send an e-mail
- launch your own feedback screen
It's the same when the user chooses to rate the app:
- redirect the user to the AppStore review page
- call a custom analytics
You can also display the native StoreKit
screen instead of custom screens (iOS 10.3+ only):
- Use localizable or configuration strings
- Default localizable strings :
-
- EN
-
- FR
- Overridable localizable strings
- Static configuration strings
- Cocoapods integration
- Default & configurable step transitions
- Default display algorithm behavior
- Customizable display algorithm behavior
- Customizable stars style
- Customizable fonts, text & tint colors
- Rating & screen actions callbacks
- Configurable with dictionary/data or remote URL: everything you want!
- Native iOS 10.3+ StoreKit integration
- Overridable layouts
- Lifecycle display events ([will/did]appear/disappear)
- Additional condition checking on the default check
- Carthage integration
- Configurable key for parsing
- Firebase extension to bind Remote Config to StarsKit data
You can specify metrics to trigger the default display behavior or use your own one.
- Disable/enable the component
- Increment sessions counter
- Increment crashes counter
- Static configuration strings
- Days without crashes
- Days before asking again
- Number of reminding
- Maximum of days between session count
- email properties: mail address, mail subject, mail header body
- Step 1: Rate screen properties
- Step 2: Feedback screen properties
- Step 3: Store review screen properties
// Call this, the algorithm will do the rest:
StarsKit.shared.displayRateIfNeeded()
// You can also force the display:
StarsKit.shared.displayRateIfNeeded(forced: true)
See also: StarsKitConfigProperties
enum keys.
You have to conform the data dictionary to the expected keys.
StarsKit offers you the possibility of using any configuration source: local JSON file, static dictionnary, remote file (remote JSON or Firebase remote configuration file).
JSON StarsKit configuration example:
{
"disabled": false,
"prefersNativeRating": false,
"displaySessionCount": 3,
"mainTitle": "Your opinion interests us :)",
"mainText": "Do you like the app StarsKit?",
"mainActionButton": "Submit",
"positiveStarsLimit": 4,
"dislikeMainTitle": "Your opinion interests us",
"dislikeMainText": "Help us to improve the app StarsKit",
"dislikeActionButton": "Make a suggestion",
"dislikeExitButton": "Later",
"likeMainTitle": "You like our app! Thanks!",
"likeMainText": "Let us know on the AppStore in a minute!",
"likeActionButton": "Let's go!",
"likeExitButton": "Later π₯",
"maxNumberOfReminder": 3,
"maxDaysBetweenSession": 3,
"emailSupport": "[email protected]",
"emailObject": "Application StarsKit",
"daysWithoutCrash": 15,
"daysBeforeAskingAgain": 3,
"emailHeaderContent": "Why do you not like the app?"
}
To update the configuration, give the dictionnary data :
let data = try Data(contentsOf: URL(fileURLWithPath: path))
let localJSONConfiguration = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String: Any?]
StarsKit.shared.updateConfig(from: localJSONConfiguration)
Today StarsKit manages a default singleton instance.
You can set-up your own configuration
, context
and graphicContext
for StarsKit.
You can also decide of:
validateRatingButtonEnable
: disable or enable the submit step rating. If disabled, the rate will be instantly submited after user touch.useDefaultBehavior
: disable the default StarsKit display checking behavior and implement your own in theStarsKitDelegate
useSessionSpaceChecking
: enable/disable the time checking when incrementing StarsKit's sessions counter. Default istrue
which means StarsKit will only count 1 session a day, but also that StarsKit will reset the sessoins counter if too much time has passed since the last session. (seeStarsKitConfiguration.maxDaysBetweenSession
).That behavior allow us to target only active users.localLocalizableStringsEnabled
: enable the localization titles instead of configuration one. It will use the default StarKit strings. If you override them in your app localizable strings (with the same key), it will take them π.
To trigger the pop-up rating display, you have to update the metrics.
// Increment the number of crash, this will automatically update the last crash date (lastCrashDate)
StarsKit.shared.context.nbCrashes += 1
// Increment the session directly
StarsKit.shared.context.nbSessions += 1
// or
StarsKit.shared.incrementSession(by: 10)
// You can also reset all the app context values
StarsKit.shared.resetContext()
// You can also reset all the configuration properties
// After a new major version update for instance
StarsKit.shared.resetConfig()
You can also use the nbCrashes
property with Fabric and Crashlytics:
extension AppDelegate {
func setupFabricSDK(_ application: UIApplication) {
Fabric.with([Crashlytics.self])
Crashlytics.sharedInstance().delegate = self
}
}
// MARK: - CrashlyticsDelegate
extension AppDelegate: CrashlyticsDelegate {
func crashlyticsDidDetectReport(forLastExecution report: CLSReport) {
StarsKit.shared.context.nbCrashes += 1
}
}
See also StarsKitContextProperties
for the user defaults properties.
Customizable items :
- titles fonts
- titles colors
- button tintColor
- button backgroundColor
- header background image
- ViewController presentation transition (via Jelly)
- Stars style (via Cosmos)
StarsKit uses Jelly fro customizable transitions. You can specify your own via the jellyCustomTransition
property in the StarsKitGraphicContext
.
Cosmos provides a CosmosSettings
property that can be set in the StarsKitGraphicContext
.
You specify your own stars images (filled/empty).
If nil, Cosmos will use the specified star path via starPoints
.
- Create the desired xib screen, with the same name than in StarsKit
- Specify the custom class and the module as "StarsKit"
- Uncheck "Inherit Module From Target"
IBOutlets are optionnals, so you can decide if you want to implement them or not.
**Note**: if you want to test it in the demo project, check the `FeedbackViewController.xib` in the StarsKit-Example target.Simple add in your Localizable strings the localizable key(s) to override
See the default StarsKit.strings
keys.
"starskit.mainTitle" = "My overrided title";
// MARK: - StarsKitDelegate
extension ViewController: StarsKitDelegate {
func didValidateRating(to rate: Int) {
// Why not send an analytic ?
print("Did validate rating to rate \(rate)")
}
func didChooseAction(at step: RatingStep) {
print("Did choose action button at step \(step)")
}
func didChooseLater(at step: RatingStep) {
print("Did choose later button at step \(step)")
}
func needCustomDisplayRateScreen() -> Bool {
//Implement your own behavior if you want
return false
}
func didUpdateRating(from context: StarsKitContext, to rate: Int) {
print("Did update rating at \(rate)")
}
}
// MARK: - StarsKitUIDelegate
extension ViewController: StarsKitUIDelegate {
func didRatingScreenWillAppear() {
print("didRatingScreenWillAppear")
}
func didRatingScreenDidAppear() {
print("didRatingScreenDidAppear")
}
func didRatingScreenWillDisappear() {
print("didRatingScreenWillDisappear")
}
func didRatingScreenDidDisappear() {
print("didRatingScreenDidDisappear")
}
func presenterController() -> UIViewController {
// Return the controller where the rate screen will be presented
// The current, the top most one, anywhere, anyone
return self
}
}
Made in π«π· by the Smart&Soft iOS Team.
StarsKit is available under the MIT license. See the LICENSE file for more info.