ExpoGuides

Configuring

Expo-specific options

Expo apps inherit the native Superwall option surface. The following fields were added in release 1.0.0 and later and live directly on the options object that you pass to <SuperwallProvider />.

Prop

Type

import { SuperwallProvider } from "expo-superwall";

export function App() {
  return (
    <SuperwallProvider
      apiKeys={{ ios: "ios_key", android: "android_key" }}
      options={{
        shouldObservePurchases: true,
        maxConfigRetryCount: 4,
        useMockReviews: __DEV__,
        testModeBehavior: "automatic",
      }}
    >
      {/* your app */}
    </SuperwallProvider>
  );
}

Logging

Logging is enabled by default in the SDK and is controlled by two properties: level and scopes.

level determines the minimum log level to print to the console. There are five types of log level:

  1. debug: Prints all logs from the SDK to the console. Useful for debugging your app if something isn't working as expected.
  2. info: Prints errors, warnings, and useful information from the SDK to the console.
  3. warn: Prints errors and warnings from the SDK to the console.
  4. error: Only prints errors from the SDK to the console.
  5. none: Turns off all logs.

The SDK defaults to info.

scopes defines the scope of logs to print to the console. For example, you might only care about logs relating to paywallPresentation and paywallTransactions. This defaults to .all. Check out LogScope for all possible cases.

You set these properties like this:

const options = new SuperwallOptions()
options.logging.level = LogLevel.Warn
options.logging.scopes = [LogScope.PaywallPresentation, LogScope.PaywallTransactions]

Superwall.configure(
  "MY_API_KEY",
  null,
  options: options
);

// Or you can set:
await Superwall.shared.setLogLevel(LogLevel.Warn)

Preloading Paywalls

Paywalls are preloaded by default when the app is launched from a cold start. The paywalls that are preloaded are determined by the list of placements that result in a paywall for the user when registered. Preloading is smart, only preloading paywalls that belong to audiences that could be matched.

Paywalls are cached by default, which means after they load once, they don't need to be reloaded from the network unless you make a change to them on the dashboard. However, if you have a lot of paywalls, preloading may increase network usage of your app on first load of the paywalls and result in slower loading times overall.

To make an onboarding or first-launch paywall load before the rest of your campaigns, prioritize the campaign from the dashboard with Priority Placements. Use the SDK methods below when you need to disable automatic preloading or manually preload specific placements.

You can turn off preloading by setting shouldPreload to false:

const options = new SuperwallOptions()
options.paywalls.shouldPreload = false

Superwall.configure(
  "MY_API_KEY",
  null,
  options: options
);

// Or you can set:
Superwall.instance.logLevel = LogLevel.Warn

Then, if you'd like to preload paywalls for specific placements you can use preloadPaywalls(forPlacements:):

var placements = {"campaign_trigger"};
Superwall.shared.preloadPaywalls(placements);

If you'd like to preload all paywalls you can use preloadAllPaywalls():

// Coming soon

Note: These methods will not reload any paywalls that have already been preloaded.

Event Tracking Behavior

By default, Superwall allows the SDK to send event collection that supports paywall analytics, reporting, and targeting. Use the platform-specific options below when your app needs to control which SDK events are sent to Superwall.

On Expo SDK 1.2.0 and later, use the eventTrackingBehavior option on the hooks/provider API (expo-superwall). It is a string-union field — pass one of the following string values:

BehaviorWhat Superwall sends
"all"All SDK event collection is enabled. This is the default.
"superwallOnly"Internal Superwall events continue to be sent, but user-initiated Superwall.track(...) calls, trigger-fire events, and user-attribute updates are suppressed.
"none"No SDK events are sent to Superwall. Paywalls still work because paywall logic runs on device, but dashboard analytics, attribution matching, and audience rules that depend on acquisition_* attributes will not receive this event data.

Set the initial behavior by passing it in options to SuperwallProvider:

import { SuperwallProvider } from "expo-superwall"

export default function App() {
  return (
    <SuperwallProvider
      apiKeys={{ ios: "MY_IOS_API_KEY", android: "MY_ANDROID_API_KEY" }}
      options={{ eventTrackingBehavior: "none" }}
    >
      <YourApp />
    </SuperwallProvider>
  )
}

You can also change the behavior at runtime after the SDK is configured. This is useful when a user changes a privacy or consent setting in your app.

import { useSuperwall } from "expo-superwall"

function PrivacySettings() {
  const setEventTrackingBehavior = useSuperwall((state) => state.setEventTrackingBehavior)

  const disableTracking = async () => {
    await setEventTrackingBehavior("none")
  }

  // Call disableTracking() from your consent UI.
}

isExternalDataCollectionEnabled is deprecated on Expo SDK 1.2.0 and later. If older code sets it to false, the SDK maps that to "superwallOnly", not "none". Use "none" when your app needs to stop SDK event collection entirely.

The compat API (expo-superwall/compat) also adds eventTrackingBehavior in 1.2.0, but its EventTrackingBehavior enum is not yet exported from that entry point. Use the hooks/provider API shown above until a later SDK release exports it.

Automatically Dismissing the Paywall

By default, Superwall automatically dismisses the paywall when a product is purchased or restored. You can disable this by setting automaticallyDismiss to false:

const options = SuperwallOptions()
options.paywalls.automaticallyDismiss = false

Superwall.configure(
  "MY_API_KEY",
  null,
  options: options
);

To manually dismiss the paywall , call Superwall.shared.dismiss().

Custom Restore Failure Message

You can set the title, message and close button title for the alert that appears after a restoration failure:

const options = SuperwallOptions()
options.paywalls.restoreFailed.title = "My Title"
options.paywalls.restoreFailed.message = "My message";
options.paywalls.restoreFailed.closeButtonTitle = "Close";

Superwall.configure(
  "MY_API_KEY",
  null,
  options: options
);

Haptic Feedback

On iOS, the paywall uses haptic feedback by default after a user purchases or restores a product, opens a URL from the paywall, or closes the paywall. To disable this, set the isHapticFeedbackEnabled PaywallOption to false:

const options = SuperwallOptions()
options.paywalls.isHapticFeedbackEnabled = false;

Superwall.configure(
  "MY_API_KEY",
  null,
  options: options
);

Note: Android does not use haptic feedback.

Transaction Background View

During a transaction, we add a UIActivityIndicator behind the view to indicate a loading status. However, you can remove this by setting the transactionBackgroundView to nil:

const options = SuperwallOptions()
options.paywalls.transactionBackgroundView = TransactionBackgroundView.none

Superwall.configure(
  "MY_API_KEY",
  null,
  options: options
);

Purchase Failure Alert

When a purchase fails, we automatically present an alert with the error message. If you'd like to show your own alert after failure, set the shouldShowPurchaseFailureAlert PaywallOption to false:

const options = SuperwallOptions()
options.paywalls.shouldShowPurchaseFailureAlert = false;

Superwall.configure(
  "MY_API_KEY",
  null,
  options: options
);

Web Purchase Confirmation Alert

When a user completes a purchase via web checkout (app2web flow), you can control whether to show a confirmation alert. By default, this is set to false to prevent duplicate alerts. Set shouldShowWebPurchaseConfirmationAlert to true if you want to show the native confirmation alert:

const options = new SuperwallOptions()
options.paywalls.shouldShowWebPurchaseConfirmationAlert = true

Superwall.configure(
  "MY_API_KEY",
  null,
  options: options
);

Locale Identifier

When evaluating rules, the device locale identifier is set to autoupdatingCurrent. However, you can override this if you want to test a specific locale:

const options = SuperwallOptions()
options.localeIdentifier = "en_GB";

Superwall.configure(
  "MY_API_KEY",
  null,
  options: options
);

For a list of locales that are available on iOS, take a look at this list. You can also preview your paywall in different locales using In-App Previews.

Game Controller

If you're using a game controller, you can enable this in SuperwallOptions too. Check out our Game Controller Support article.

Take a look at SuperwallOptions in our SDK reference for more info.

How is this guide?

On this page