Testing Purchases: Sandbox, TestFlight and Test Mode
Pick the right way to test your paywall and purchases: test mode, StoreKit files, Apple sandbox and TestFlight, Google Play testers, or Stripe sandbox.
There are several ways to test a Superwall paywall and the purchases it makes. Some simulate the purchase, some run a real store transaction in a test environment, and some only show you the paywall. This page compares them and links to the full guide for each.
Compare the methods
| Method | Platforms | Real store transactions? | What it's for |
|---|---|---|---|
| Test mode | iOS, Android | No. Superwall simulates them. | The whole paywall flow, entitlement gating and restores, with no store setup. |
| StoreKit configuration file | iOS | Local StoreKit transactions in Xcode, not App Store servers. | Real StoreKit behavior on a simulator or device, before products exist in App Store Connect. |
| Apple sandbox and TestFlight | iOS | Yes, in Apple's sandbox. No money is charged. | Purchases against App Store Connect products, renewals, and server-side events such as webhooks. |
| Google Play testing | Android | Yes, as test purchases. | Purchases against Google Play Console products. |
| Web Checkout sandbox | Web | Yes, with Stripe sandbox products and test cards. | Web paywalls, checkout and redemption in your app. |
| Paywall previews | iOS, Android | No purchases. | How a paywall looks on a device before it goes live. |
Test mode
Test mode is built into the Superwall SDK. When it's on, product data comes from the Superwall dashboard instead of the store, and a purchase opens a test mode drawer instead of the system payment sheet. You choose whether the purchase succeeds or fails, and the usual transaction events still fire. Restores open a drawer where you pick which entitlements to restore.
When test mode starts, a configuration modal lets you set each entitlement's starting state and override free trial availability, so you can test what different users see. Your choices persist across sessions.
Requirements
| SDK | Test mode | testModeBehavior option |
|---|---|---|
| iOS | 4.14.0 or later | 4.14.0 or later |
| Android | 2.7.4 or later | 2.7.4 or later |
| Flutter | Through the native SDKs | 2.4.11 or later |
| Expo | Through the native SDKs | 1.0.4 or later |
Turn it on
There are three ways to turn on test mode:
- From the dashboard. Open Users, open the user, and turn on Simulated purchases under Test mode. When the SDK sees that user's ID, it starts test mode. Users in test mode are listed under In test mode at the top of the Users page. This option shows for iOS and Android apps. If you don't see it, use the SDK option instead.
- From the SDK. Set
testModeBehavioronSuperwallOptionsbefore you configure the SDK.alwaysturns it on for every launch, which is useful during development. - From a local dev server (iOS). When
SuperwallOptions.devServerconnects to a runningsuperwall devserver, test mode turns on by itself and the intro modal is skipped. This needs iOS SDK 4.17.0 or later. See Local paywall development.
let options = SuperwallOptions()
options.testModeBehavior = .always
Superwall.configure(apiKey: "your-api-key", options: options)val options = SuperwallOptions().apply {
testModeBehavior = TestModeBehavior.ALWAYS
}
Superwall.configure(this, "your-api-key", options = options)final options = SuperwallOptions()
..testModeBehavior = TestModeBehavior.always;
await Superwall.configure('your-api-key', options: options);<SuperwallProvider
apiKeys={{ ios: "ios_key", android: "android_key" }}
options={{ testModeBehavior: "always" }}
>
{/* your app */}
</SuperwallProvider>The default, automatic, also turns on test mode when the app's bundle ID (on Android, its application ID) doesn't match the one saved in the dashboard. whenEnabledForUser only turns it on for users marked in the dashboard, and never turns it off. The full behavior is in the iOS and Android test mode guides.
Things to know
- On iOS, test mode marks the device as sandbox, so its events go to sandbox and stay out of your production data.
- From iOS SDK 4.18.0, a bundle ID mismatch only starts test mode in simulator, TestFlight and development builds. App Store builds ignore it. Users marked in the dashboard still get test mode in any build. See the bundle ID warning in Settings.
automaticnever starts test mode during UI tests on iOS, or when JUnit or Espresso is on the classpath on Android.- A simulated purchase grants entitlements without a store transaction, so it can't exercise the Customer Center. Use a StoreKit configuration file or a sandbox account for that.
StoreKit configuration files
A StoreKit configuration file is Xcode's local test environment for in-app purchases. It doesn't connect to App Store servers, and the products in it don't have to exist in App Store Connect yet. It works in the simulator, where you can't sign in to a real Apple Account.
To set it up, add a StoreKit Configuration File to your project, add your products to it, and select it under Run → Options → StoreKit Configuration in your scheme. Each product ID must match the product ID on your paywall. Then use Xcode's Transaction Manager, under Debug → StoreKit → Manage Transactions..., to delete or refund purchases and reset your subscription state without reinstalling.
The setup guide is per SDK: iOS, Flutter and Expo. Expo needs a development build, not Expo Go.
Things to know
- StoreKit configuration file purchases don't trigger webhooks. Use TestFlight with a sandbox account to test those.
- If a test transaction looks stuck or stays active, see StoreKit Transactions Not Clearing in Xcode.
- If you see Sign in to Apple Account in the simulator, the StoreKit file isn't set on your current scheme. See Why am I seeing "Sign in to Apple Account".
Apple sandbox accounts and TestFlight
On a physical device, development and TestFlight builds buy your App Store Connect products in Apple's sandbox. To use a sandbox account on a development build, go to Settings → App Store → Sandbox Account on the device and sign in.
Sandbox and TestFlight behave differently from the App Store:
- Subscriptions renew faster. In TestFlight, every subscription renews once a day, up to 6 times, then stops renewing.
- Reinstalling resets the user. After a reinstall, the user looks new and anonymous until they tap purchase, which restores their existing subscription.
- Free trials can be missing after a reinstall. The SDK can't read the receipt until a purchase or restore. Restore purchases first, then try again.
- Entitlements can persist after a reset. Apple's sandbox keeps subscription state on its servers, and
Superwall.shared.reset()can't clear it. Use a fresh sandbox account for a clean test. - Prices can show in another currency. In TestFlight, StoreKit can return prices from another storefront, often USD.
The details are in TestFlight Subscriptions, Sandbox Free Trial Isn't Appearing, Sandbox Entitlements Persist After Reset, and How to Test Paywalls with Local Currency.
Google Play testing
To test real Google Play Billing, use Google Play's license test accounts. For your products to load, you need at least one build with the com.android.vending.BILLING permission uploaded to a test track, and the device or emulator must have the Play Store and be signed in. See Products not loading on Android for the full checklist.
Superwall treats an Android build as sandbox when it's debuggable. Release builds count as production, including builds installed from Google Play testing tracks.
Web Checkout sandbox
To test a web paywall, create a sandbox product in Stripe, import it to Superwall, and add it to the paywall. Every product on the paywall must be a sandbox product. Then open the paywall URL, pay by card with 4242 4242 4242 4242, any future expiration date and any CVC, and follow the redemption flow into your app.
Your Stripe test keys go under Stripe Sandbox Configuration in Settings. The full guide is Sandbox Purchases.
Keep test data out of production metrics
The SDK reports whether each device is a sandbox device. On iOS, simulator, Xcode and TestFlight builds are sandbox, and App Store installs are production. On Android, debuggable builds are sandbox. You use the same API key for both.
To see sandbox data, choose Sandbox from the environment picker at the top of the Overview or Campaigns page. The top bar then shows a Sandbox badge. Production is the default.
To show testers a different paywall, add an audience to your campaign with the filter isSandbox is true, and put it above your production audiences. Superwall checks audiences from top to bottom, so sandbox devices match it first. See How to set up sandbox testing without affecting production metrics.
Preview a paywall without purchasing
To see a paywall on your own device before it goes live, click Preview in the paywall editor and scan the QR code with your phone. It opens the paywall in your app. This needs a URL scheme and the SDK's deep link handler. See In-App Paywall Previews and Previewing. Preview links only work for a few minutes, so scan a fresh code if one expires.
To check a layout without a device, use the editor's device preview. See Device view vs. Canvas view.
Related
How is this guide?
Haptic Feedback on Paywalls
Play a native haptic when someone taps a paywall button, pick light, medium, heavy, success, warning, error or selection, and turn off the SDK's own haptics.
Query ClickHouse
Use the Superwall API to query your organization's ClickHouse-backed analytics data and find the event names and attribute keys each app sends.