Hi! 👋🏻
We’re in the final stages of our testing of some StoreKit 2 features before fully calling it ready for production, and we’d love your help!
Context:
Starting with v4.0.0, our SDK already uses StoreKit 2 by default on compatible devices for some features where the StoreKit 1 functionality was problematic, buggy or unreliable, and StoreKit 2 is essentially guaranteed to be an improvement (like checkTrialOrIntroDiscountEligibility). For devices that aren’t compatible with StoreKit 2, it defaults to a StoreKit 1 implementation.
However, we haven’t enabled StoreKit 2 by default for making actual purchases. We’ve tested it extensively in Sandbox and StoreKit Test (see our blog post on how we test our SDKs) but we need to see how well StoreKit2 behaves in production before calling it ready.
How to help:
Our SDK includes an optional flag in the configure method, called useStoreKit2IfAvailable. In order to help, all you need to do is to set that flag to true!
With this flag set, the SDK will use StoreKit 2 APIs for almost all features including making purchases, subscription offers, and more. For devices where StoreKit 2 isn’t available (devices running iOS/tvOS 14 and below, macOS 11 and below, and watchOS 7.0 and below), the SDK will continue to use StoreKit 1 as usual.
Since we’re aiming to see how it behaves in production, though, we’re encouraging beta testers to use a remotely-configured feature flag to selectively enable / disable that flag.
If you already have remotely-configured feature flags in place for your app, you can use the same system you have in place to add a feature flag for useStoreKit2IfAvailable.
If you see anything unusual or experience any issues with StoreKit 2, please file a bug in our iOS SDK repo!
The rest of this post will provide a small tutorial on setting up remotely-configured Feature Flags using Firebase Remote Config.
Setting up remotely-configured Feature Flags using Firebase Remote Config
Firebase Remote Config lets you set up configuration values for your app in a few short steps.
Configuration values are provided as key-value storage and set up through the web app.
To get started, head over to Firebase Console and set up a new project if you haven’t yet.
Name it the same as your app. I’m using `StoreKit2FeatureFlagApp` for this example.
Next, Firebase will offer to add analytics for your app. They’re not needed for this test, so I’m keeping them disabled.
After a short loading screen, you should see something like the following:
Add a new iOS app to your Firebase project by clicking on the iOS+ button
Set the bundle id, an app nickname and the App Store ID.
Important: make sure that the bundle ID is the same as the one in App Store Connect and the RevenueCat Dashboard. It can’t be changed afterwards.
Download the GoogleService-Info.plist file and add it to the project as described in the image.
Add Firebase Remote Config to your project.
Note that for this test, we don’t need any Firebase features other than FirebaseRemoteConfig, so we’re only enabling that one in Swift Package Manager.
If you’re using Cocoapods, you can include FirebaseRemoteConfig by adding
pod 'Firebase/RemoteConfig'
in your Podfile, then calling pod install
.
Set up a Feature Flag for StoreKit 2 in Firebase
Select Remote Config under Engage on the left pane and click Create configuration
Name it something easy to remember, set its Data type to Boolean and default value to false.
Using Firebase Remote Config to selectively enable / disable StoreKit 2 in your app
Important: Since the flag we want to set is a configuration parameter, we need to wait until we get the value from Firebase before using it to set up RevenueCat.
1: Configure Firebase
First, you need to configure the Firebase app.
Early in your app’s lifecycle, like in AppDelegate’s application:didFinishLaunchingWithOptions:
, do:
Import Firebase
And then
FirebaseApp.configure()
2: Get Remote Config values
do {
status = try await remoteConfig.fetch()
try await remoteConfig.activate()
} catch {
print("can't configure, error: \(error.localizedDescription)")
return
}
let useSK2 = remoteConfig.configValue(forKey: useSK2Key).boolValue
3: Configure the SDK with the obtained value
Purchases.configure(withAPIKey: Constants.apiKey,
appUserID: nil,
observerMode: false,
userDefaults: nil,
useStoreKit2IfAvailable: useSK2)
#if DEBUG
Purchases.logLevel = .debug
#else
Purchases.logLevel = .info
#endif
4: (Optional) set a subscriber attribute to the value of useSK2 so you can see it in the dashboard afterwards.
Purchases.shared.setAttributes(o"usingSK2" : "\(useSK2)"]
5: (Optional) Notify the app that the SDK is ready
Since we’re delaying the configuration of the SDK, if the app makes any calls to Purchases.shared early on in its life cycle (for example, in a viewDidAppear for the initial view), the SDK might not be ready for use yet.
There are dozens of workarounds for this. In this example, we’re using Combine to create a publisher that lets us know when the SDK is configured.
enum AppConfig {
static var sdkConfigured = CurrentValueSubject<Bool, Never>(false)
}
// right after the Purchases.configure(...) line
AppConfig.sdkConfigured.send(true)
Then in the place where we need to wait until the SDK is configured:
var cancellable: Cancellable?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
cancellable = AppConfig.sdkConfigured
.filter { $0 }
.sink() { (weak self] _ in
self?.setUpView()
}
}
Enabling StoreKit 2
That’s it!
Now that we have all of the setup and code in place, we can control the use of our feature flag directly from the Firebase Console.
To do that, we can either:
Edit our Feature Flag and set the Default value to true for everyone:
Or add Conditional values in the Firebase Console, which allows further control of the rollout, allowing us to tweak the proportion of users getting one vs the other, using various different parameters or even just setting a percentage.
Please give it a shot! If you see anything unusual or experience any issues with StoreKit 2, please file a bug in our iOS SDK repo.