Skip to main content
The SuperwallProvider is the core component that initializes the Superwall SDK with your API keys and configuration options. It should wrap the root of your application or the part that requires Superwall functionality.

Basic Setup

1

Install the package

Install expo-superwall using your package manager:
npx expo install expo-superwall
# or
bunx expo install expo-superwall
2

Wrap your app with SuperwallProvider

Import and configure the provider with your API keys:
import { SuperwallProvider } from "expo-superwall";

export default function App() {
  return (
    <SuperwallProvider apiKeys={{ ios: "YOUR_IOS_API_KEY", android: "YOUR_ANDROID_API_KEY" }}>
      {/* Your app content */}
    </SuperwallProvider>
  );
}
3

Find your API keys

Get your API keys from your Superwall dashboard. You can provide separate keys for iOS and Android, or use the same key for both platforms.

API Keys Configuration

The apiKeys prop accepts an object with platform-specific keys:
apiKeys={{
  ios: "pk_1234567890abcdef",      // Required for iOS
  android: "pk_0987654321fedcba"    // Required for Android
}}
You must provide at least one API key for the platform you’re targeting. The SDK will throw an error if no key is provided for the current platform.

Configuration Options

Customize SDK behavior by passing the options prop:
import { SuperwallProvider } from "expo-superwall";

export default function App() {
  return (
    <SuperwallProvider
      apiKeys={{ ios: "YOUR_API_KEY" }}
      options={{
        paywalls: {
          shouldPreload: true,
          isHapticFeedbackEnabled: true,
          automaticallyDismiss: true,
        },
        logging: {
          level: "debug",
          scopes: ["all"],
        },
      }}
    >
      {/* Your app content */}
    </SuperwallProvider>
  );
}

Paywall Options

OptionTypeDefaultDescription
shouldPreloadbooleanfalsePreload all paywalls on SDK initialization
isHapticFeedbackEnabledbooleantrueEnable haptic feedback for paywall interactions
automaticallyDismissbooleantrueAutomatically dismiss paywall after purchase
shouldShowPurchaseFailureAlertbooleantrueShow alert when purchase fails
transactionBackgroundView"spinner" | "none""spinner"View shown behind Apple’s payment sheet

Restore Failed Messaging

Customize the alert shown when restore fails:
options={{
  paywalls: {
    restoreFailed: {
      title: "No Subscription Found",
      message: "We couldn't find an active subscription for your account.",
      closeButtonTitle: "Okay",
    },
  },
}}

Logging Options

Control SDK logging for debugging:
options={{
  logging: {
    level: "debug",  // "debug" | "info" | "warn" | "error" | "none"
    scopes: ["all"],  // Or specific scopes like ["paywallPresentation", "network"]
  },
}}
Use level: "debug" during development and level: "error" or level: "none" in production.

Advanced Options

options={{
  networkEnvironment: "release",  // "release" | "releaseCandidate" | "developer"
  isExternalDataCollectionEnabled: true,
  isGameControllerEnabled: false,
  shouldObservePurchases: false,
  testModeBehavior: "automatic",  // "automatic" | "whenEnabledForUser" | "never" | "always"
  
  // iOS-specific
  storeKitVersion: "STOREKIT2",  // "STOREKIT1" | "STOREKIT2"
  shouldBypassAppTransactionCheck: false,
  maxConfigRetryCount: 6,
  
  // Android-specific
  passIdentifiersToPlayStore: false,
  useMockReviews: false,
}}

Configuration Error Handling

Handle SDK initialization errors using the onConfigurationError callback:
import { SuperwallProvider } from "expo-superwall";

export default function App() {
  const handleConfigError = (error: Error) => {
    console.error("Superwall config failed:", error);
    // Log to error tracking service
    // Sentry.captureException(error);
  };

  return (
    <SuperwallProvider
      apiKeys={{ ios: "YOUR_API_KEY" }}
      onConfigurationError={handleConfigError}
    >
      {/* Your app content */}
    </SuperwallProvider>
  );
}
The SDK gracefully handles offline scenarios and configuration failures. Your app won’t hang indefinitely in a loading state.

Managing Loading States

Use the provided components to handle loading states:
import {
  SuperwallProvider,
  SuperwallLoading,
  SuperwallLoaded,
  SuperwallError,
} from "expo-superwall";
import { ActivityIndicator, View, Text, Button } from "react-native";

export default function App() {
  return (
    <SuperwallProvider apiKeys={{ ios: "YOUR_API_KEY" }}>
      <SuperwallLoading>
        <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
          <ActivityIndicator size="large" />
          <Text>Loading Superwall...</Text>
        </View>
      </SuperwallLoading>

      <SuperwallError>
        {(error) => (
          <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
            <Text style={{ fontSize: 18, marginBottom: 10 }}>
              Failed to initialize Superwall
            </Text>
            <Text style={{ color: "gray", marginBottom: 20 }}>{error}</Text>
            <Button title="Retry" onPress={() => {/* retry logic */}} />
          </View>
        )}
      </SuperwallError>

      <SuperwallLoaded>
        <MainAppScreen />
      </SuperwallLoaded>
    </SuperwallProvider>
  );
}

Component Reference

  • <SuperwallLoading> - Renders children while SDK is initializing
  • <SuperwallLoaded> - Renders children once SDK is ready
  • <SuperwallError> - Renders children when configuration fails

Complete Example

Here’s a complete setup with all features:
import {
  SuperwallProvider,
  SuperwallLoading,
  SuperwallLoaded,
  SuperwallError,
} from "expo-superwall";
import { ActivityIndicator, View, Text } from "react-native";

const SUPERWALL_CONFIG = {
  apiKeys: {
    ios: "pk_your_ios_key",
    android: "pk_your_android_key",
  },
  options: {
    paywalls: {
      shouldPreload: true,
      isHapticFeedbackEnabled: true,
      automaticallyDismiss: true,
    },
    logging: {
      level: __DEV__ ? "debug" : "error",
      scopes: ["all"],
    },
    shouldObservePurchases: true,
  },
};

export default function App() {
  const handleConfigError = (error: Error) => {
    console.error("Superwall initialization failed:", error.message);
  };

  return (
    <SuperwallProvider
      apiKeys={SUPERWALL_CONFIG.apiKeys}
      options={SUPERWALL_CONFIG.options}
      onConfigurationError={handleConfigError}
    >
      <SuperwallLoading>
        <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
          <ActivityIndicator size="large" color="#0000ff" />
        </View>
      </SuperwallLoading>

      <SuperwallError>
        {(error) => (
          <View style={{ flex: 1, justifyContent: "center", alignItems: "center", padding: 20 }}>
            <Text style={{ fontSize: 18, fontWeight: "bold", marginBottom: 10 }}>
              Unable to Load
            </Text>
            <Text style={{ color: "#666", textAlign: "center" }}>
              {error}
            </Text>
          </View>
        )}
      </SuperwallError>

      <SuperwallLoaded>
        <MainApp />
      </SuperwallLoaded>
    </SuperwallProvider>
  );
}

function MainApp() {
  return (
    <View style={{ flex: 1 }}>
      {/* Your app screens and navigation */}
    </View>
  );
}

Next Steps

Displaying Paywalls

Learn how to trigger and present paywalls using usePlacement

Managing Users

Identify users and manage their attributes

Build docs developers (and LLMs) love