Superwall

Superwall Integration Guide

Integrate Botsi AI Pricing with Superwall to show each user the optimal paywall based on Botsi's machine learning predictions. Superwall handles paywall display via Campaigns and Audiences, while Botsi determines which paywall each user should see.

Integration Flow Summary

  1. Create Botsi Profile → Get profileId
  2. Call Botsi Get Paywall API → Get predicted paywall externalID
  3. Set Superwall User Attribute → Store Botsi's externalID
  4. Register Superwall Placement → Superwall returns targeted paywall based on Campaign audience matching user attributes
  5. Show Paywall to User → Superwall presents the paywall
  6. Send Paywall Impression → Call Botsi Profile Events API when paywall is presented
  7. Handle Purchase → Extract transaction data when purchase completes
  8. Validate Purchase → Send transaction to Botsi Purchase Validate API

1. Normal Botsi AI API Setup

Complete the standard Botsi AI Pricing integration following the AI Pricing Integration Guide.

2. Set Up Different Paywalls in Superwall and Botsi

Decide what prices you want to show and how you want to present them on different paywalls.

In Superwall, you'll configure Paywalls with different products/price points in their dashboard — Superwall Paywalls define which products are shown to users.

For example, if you want to use multiple annual price points, you could set up:

  • Paywall: "standard_paywall" — annual → com.app.pro.annual_standard
  • Paywall: "discounted_paywall" — annual → com.app.pro.annual_discounted

Then, you'll set up corresponding Paywalls in Botsi that match your Superwall Paywalls. Add the same products you have in a Superwall Paywall to the Botsi Paywall. This lets the AI model know what prices/products are available.

3. Botsi Get Paywall API

You will specify the external ID value (data.externalID) in the Botsi dashboard when setting up a paywall.

The exact value is not important as long as it's unique, but we recommend using a common naming convention so you can keep track in other tools. (e.g. onboardingPaywall_29.99Annual_v2)

When you call the Botsi Get Paywall API, it will return that "external ID" value to you. Technically, you can use data.ID or data.externalID, but ID is always a number that you cannot adjust and so is less easily understood.

You will then use this value to set a "User Attribute" in Superwall using their SDK. See Superwall's Setting User Attributes documentation for setting up your audience rules based on the user attribute you added.

The naming of this user attribute is not important as you'll parse out the value from the Botsi API and write it via the Superwall SDK. We recommend an understandable name for other internal users. (e.g. "botsi_paywall_id" or "botsi_paywall_prediction")

You will use the externalID as the value.

Botsi Paywall Dashboard showing external ID and products

4. Superwall Campaign and Audience Targeting using Botsi

You will use Superwall's Campaign Audiences with user attributes to show the right paywall to the right user. Follow Superwall's Campaigns and Audience documentation for setting up your audience rules based on the user attribute you added.

Superwall Campaign audience targeting with Botsi paywall ID filter

Set the user attribute in Superwall before registering a placement:

  • Swift
  • Kotlin
  • Flutter
  • React Native
// Set the user attribute with Botsi's predicted paywall ID
Superwall.shared.setUserAttributes([
    "botsi_paywall_id": botsiExternalPaywallId
])

// Then register the placement - Superwall will use the user attribute for targeting
Superwall.shared.register(event: "your_placement_name") { paywallInfo in
    switch paywallInfo {
    case .presented:
        // Paywall was presented
        break
    case .dismissed:
        // Paywall was dismissed
        break
    case .declined:
        // User declined the paywall
        break
    case .purchased:
        // User made a purchase
        break
    }
}
// Set the user attribute with Botsi's predicted paywall ID
Superwall.setUserAttributes(
    mapOf("botsi_paywall_id" to botsiExternalPaywallId)
)

// Then register the placement - Superwall will use the user attribute for targeting
Superwall.instance.register(
    event = "your_placement_name",
) { }
Superwall.shared.registerPlacement(
    "placement", handler: null, feature: () {
 });

See @superwall/react-native-superwall on npm. Note: Superwall recommends migrating to the Expo SDK for new projects.

import Superwall from '@superwall/react-native-superwall';

// Set the user attribute with Botsi's predicted paywall ID
await Superwall.shared.setUserAttributes({
    "botsi_paywall_id": botsiExternalPaywallId
});

// Then register the placement - Superwall will use the user attribute for targeting
await Superwall.shared.register({
    placement: "your_placement_name",
    feature: () => {
        // Feature block - runs if user doesn't see a paywall
    }
});

5. Send the Paywall Impression

Continue with API call 3, Profile Events API in the documentation, to send the paywall impression.

This should reference the Get Paywall API response field "id" (not externalID).

You can send the paywall impression event when Superwall presents the paywall (in the .presented case).

6. Send Purchase Transaction Data to Botsi

You will need to send the iOS Transaction ID/Original Transaction ID, or Android Purchase token after a successful purchase through Superwall.

  • Swift (iOS)
  • Kotlin (Android)
  • Flutter
  • React Native

See Superwall's iOS SDK documentation for more details on handling purchases.

// When using Superwall
// SuperwallDelegate
func handleSuperwallEvent(withInfo eventInfo: SuperwallEventInfo) {
    switch eventInfo.event {
    case .transactionComplete(let transaction, _, _, _):
        if let transaction {
            let id = transaction.storeTransactionId
            let original = transaction.originalTransactionIdentifier

            // Send to Botsi backend API (Section 4a in Botsi documentation)
            // POST to /api/v1/web-api/purchases/apple-store/validate
        }
    default:
        break
    }
}

See Superwall's Android SDK documentation for more details on handling purchases.

// When using Superwall with Google Play Billing
class SWDelegate : SuperwallDelegate {
  override fun handleSuperwallEvent(eventInfo: SuperwallEventInfo) {
    when (eventInfo.event) {
        is SuperwallPlacement.TransactionComplete -> {
            val transaction = (eventInfo.event as
SuperwallPlacement.TransactionComplete).transaction
            val product = (eventInfo.event as SuperwallPlacement.TransactionComplete).product
            val paywallInfo = (eventInfo.event as
SuperwallPlacement.TransactionComplete).paywallInfo
            // Extract purchase token from your billing implementation
            // This depends on how you've configured Superwall with your purchase controller
            val purchaseToken = paywallInfo.purchaseToken

            // Send to Botsi backend API (Section 4b in Botsi documentation)
            // POST to /api/v1/web-api/purchases/play-store/validate
        }
      else -> {
        // Handle other cases
      }
    }
  }
}
}
class _MyAppState extends State<MyApp> implements SuperwallDelegate {
  // ...

  @override
  Future<void> handleSuperwallEvent(SuperwallEventInfo eventInfo) async {
    switch (eventInfo.event.type) {
      case PlacementType.transactionComplete:
        final product = eventInfo.params?['product'];
        // Send to Botsi backend API (Section 4b in Botsi documentation)
        // POST to /api/v1/web-api/purchases/play-store/validate
        break;
      // Handle other events if necessary
      default:
        logging.info('Unhandled event type: ${eventInfo.event.type}');
        break;
    }
  }
  // ...
}

See Superwall's Delegate documentation for more details on handling events.

import Superwall from '@superwall/react-native-superwall';

// Set up the Superwall delegate to handle events
const delegate = {
    handleSuperwallEvent: (eventInfo) => {
        if (eventInfo.event.type === 'transactionComplete') {
            const transaction = eventInfo.event.transaction;
            const storeTransactionId = transaction?.storeTransactionId;
            const originalTransactionId = transaction?.originalTransactionIdentifier;

            // Send to Botsi backend API
            // iOS: POST to /api/v1/web-api/purchases/apple-store/validate
            // Android: POST to /api/v1/web-api/purchases/play-store/validate
        }
    }
};

Superwall.shared.setDelegate(delegate);

Important: Superwall URL Forwarding

Superwall only has one URL slot for event forwarding. If you need to send events to both Botsi and Superwall, you must either build a custom router on your backend that receives events and forwards them to both services, or use Botsi's URL for forwarding and configure Botsi to relay events to Superwall.

Notes

  • Ensure server-side notifications are configured in both Superwall and Botsi for accurate analytics
  • The user attribute set in Superwall should match the audience filters you configure in your Superwall Campaign
  • Superwall uses Campaigns with Audiences to determine which paywall shows to which user based on their attributes
  • Always handle errors appropriately when calling both Botsi and Superwall APIs
  • Test the integration thoroughly in sandbox/test environments before going to production
  • Superwall's register() method can be called at any point in your app where you want to potentially show a paywall
  • Superwall does not currently offer a Unity SDK. For Unity projects, consider using the Native Paywall Display approach or one of the other supported integrations.