> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appstack.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Superwall

<Prompt description="Use Cursor, Claude Code, or another AI to help you implement the Superwall integration with Appstack." actions={["copy", "cursor"]}>
  You are an expert mobile monetization engineer helping me integrate Superwall with the Appstack SDK. You are running inside an IDE assistant such as Cursor or Claude Code and you can see my codebase.

  Use the reference below to wire the integration for my platform (Swift, Kotlin, Expo, or Flutter). When I paste this prompt and share my code, you should:

  1. Show exactly where to call the Appstack + Superwall integration methods in my app lifecycle and produce ready-to-paste code for my platform, using the snippets below.
  2. Ensure the Appstack ID and attribution parameters are passed to Superwall exactly as described in the documentation.
  3. Confirm that any required SDK versions and ordering (Appstack vs Superwall initialization) are respected.
  4. Propose concrete edits that minimize duplication and keep the integration in one clear place in my code.
  5. Give me a short checklist of what you configured (IDs, attributes, lifecycle placement) so I can see that everything from the docs is covered.

  ***

  ## Reference: Superwall + Appstack integration

  **Superwall SDK requirements**

  Use a Superwall SDK version that includes the Appstack integration attribute:

  | Platform            | Package             | Minimum version |
  | :------------------ | :------------------ | :-------------- |
  | iOS                 | `Superwall-iOS`     | `4.12.11`       |
  | Android             | `Superwall-Android` | `2.7.5`         |
  | Flutter             | `Superwall-Flutter` | `2.4.11`        |
  | React Native / Expo | `expo-superwall`    | `1.0.5`         |

  For React Native apps, use `expo-superwall`. The legacy `react-native-superwall` package is archived.

  **1. Pass the Appstack ID to Superwall**

  Call these after both Appstack and Superwall are configured:

  ```swift theme={null}
  // Swift
  // Use Superwall-iOS version >= 4.12.11
  Superwall.shared.setIntegrationAttributes([
    IntegrationAttribute.appstackId: AppstackAttributionSdk.shared.getAppstackId()
  ])
  ```

  ```kotlin theme={null}
  // Kotlin
  // Use Superwall-Android version >= 2.7.5
  Superwall.instance.setIntegrationAttributes(
      mapOf(IntegrationAttribute.appstackId to AppstackAttributionSdk.getAppstackId())
  )
  ```

  ```typescript theme={null}
  // React Native / Expo
  // Use expo-superwall version >= 1.0.5
  const { setIntegrationAttributes } = useUser();
  const appstackId = await AppstackSDK.getAppstackId();
  await setIntegrationAttributes({ appstackId });
  ```

  ```dart theme={null}
  // Flutter
  // Use Superwall-Flutter version >= 2.4.11
  await Superwall.shared.setIntegrationAttributes({
    IntegrationAttribute.appstackId: await AppstackPlugin.getAppstackId(),
  });
  ```

  **2. Pass Appstack attribution params as Superwall user attributes**

  Add this once before your first `Superwall.register` call so all placements include the attributes:

  ```swift theme={null}
  // Swift
  Task {
    Superwall.shared.setUserAttributes(
      await AppstackAttributionSdk.shared.getAttributionParams() ?? [:]
    )

    // Now, your placements will attach those user attributes,
    // making them available for use in campaign filters.
    Superwall.shared.register(placement: "onboarding_paywall")
  }
  ```

  ```kotlin theme={null}
  // Kotlin
  fun prepareSuperwallPlacement() {
      Superwall.instance.setUserAttributes(
          AppstackAttributionSdk.getAttributionParams()
      )

      // Now, your placements will attach those user attributes,
      // making them available for use in campaign filters.
      Superwall.instance.register("onboarding_paywall")
  }

  // Call prepareSuperwallPlacement() after Appstack initialization and before this placement can be shown.
  ```

  ```typescript theme={null}
  // Expo
  const { update } = useUser();
  const { registerPlacement } = usePlacement();

  await update((await AppstackSDK.getAttributionParams()) ?? {});

  // Now, your placements will attach those user attributes,
  // making them available for use in campaign filters.
  await registerPlacement({ placement: 'onboarding_paywall' });
  ```

  ```dart theme={null}
  // Flutter
  await Superwall.shared.setUserAttributes(
    (await AppstackPlugin.getAttributionParams()) ?? {},
  );

  // Now, your placements will attach those user attributes,
  // making them available for use in campaign filters.
  await Superwall.shared.register('onboarding_paywall');
  ```

  **3. Credentials in dashboards (non-code steps)**

  * In Appstack: `Integrations` → `Superwall` → copy **access token** and **app ID**.

  * In Superwall: `Integrations` → `Appstack` → paste **access token** and **app ID**.

  * Once active in Superwall, it can take **30–60 minutes** to appear active in Appstack.

  * Avoid editing the integration in Superwall to prevent attribution issues.
</Prompt>

With the Superwall integration, you can:

1. Use Superwall in-app events to run enhanced app campaigns.
2. Unlock attribution-based paywall optimization.

<Note>
  **To successfully connect Superwall, you must:**

  1. Have Owner/Admin access to an Appstack organization.
  2. Have access to the correct Superwall account.
</Note>

## Requirements

Use a Superwall SDK version that includes the Appstack integration attribute:

| Platform            | Package             | Minimum version |
| :------------------ | :------------------ | :-------------- |
| iOS                 | `Superwall-iOS`     | `4.12.11`       |
| Android             | `Superwall-Android` | `2.7.5`         |
| Flutter             | `Superwall-Flutter` | `2.4.11`        |
| React Native / Expo | `expo-superwall`    | `1.0.5`         |

For React Native apps, use `expo-superwall`. The legacy `react-native-superwall` package is archived.

## Connect to Superwall

Follow the steps to ensure the Superwall integration works:

<Steps>
  <Step title="SDK configuration">
    To successfully receive the Appstack ID, set the Appstack integration attribute after the calls to Superwall and Appstack configure methods:

    <CodeGroup>
      ```swift Swift theme={null}
      // Use Superwall-iOS version >= 4.12.11

      Superwall.shared.setIntegrationAttributes([
        IntegrationAttribute.appstackId: AppstackAttributionSdk.shared.getAppstackId()
      ])
      ```

      ```kotlin Kotlin theme={null}
      // Use Superwall-Android version >= 2.7.5

      Superwall.instance.setIntegrationAttributes(
          mapOf(IntegrationAttribute.appstackId to AppstackAttributionSdk.getAppstackId())
      )
      ```

      ```typescript Expo theme={null}
      // Use expo-superwall version >= 1.0.5

      const { setIntegrationAttributes } = useUser();
      const appstackId = await AppstackSDK.getAppstackId();
      await setIntegrationAttributes({ appstackId });
      ```

      ```dart Flutter theme={null}
      // Use Superwall-Flutter version >= 2.4.11

      await Superwall.shared.setIntegrationAttributes({
        IntegrationAttribute.appstackId: await AppstackPlugin.getAppstackId(),
      });
      ```
    </CodeGroup>

    To show paywalls based on where your users came from (paid ads), set Appstack's attribution params as [user attributes](https://superwall.com/docs/ios/quickstart/setting-user-properties) before your first `Superwall.register` call. You do not need to repeat this for every placement.

    <Note>
      Learn more about how to use ad campaign data to show personalized paywalls and increase subscription revenue by [reading this article.](https://superwall.com/blog/show-paywalls-based-on-where-your-users-came-from-with-appstack-and)
    </Note>

    <CodeGroup>
      ```swift Swift theme={null}
      Task {
        Superwall.shared.setUserAttributes(
          await AppstackAttributionSdk.shared.getAttributionParams() ?? [:]
        )

        // Now, your placements will attach those user attributes, making
        // them available for use in campaign filters.
        Superwall.shared.register(placement: "onboarding_paywall")
      }
      ```

      ```kotlin Kotlin theme={null}
      fun prepareSuperwallPlacement() {
          Superwall.instance.setUserAttributes(
              AppstackAttributionSdk.getAttributionParams()
          )

          // Now, your placements will attach those user attributes, making
          // them available for use in campaign filters.
          Superwall.instance.register("onboarding_paywall")
      }

      // Call prepareSuperwallPlacement() after Appstack initialization and before this placement can be shown.
      ```

      ```typescript Expo theme={null}
      const { update } = useUser();
      const { registerPlacement } = usePlacement();

      await update((await AppstackSDK.getAttributionParams()) ?? {});

      // Now, your placements will attach those user attributes, making
      // them available for use in campaign filters.
      await registerPlacement({ placement: 'onboarding_paywall' });
      ```

      ```dart Flutter theme={null}
      // Use Superwall-Flutter version >= 2.4.11

      await Superwall.shared.setUserAttributes(
        (await AppstackPlugin.getAttributionParams()) ?? {},
      );

      // Now, your placements will attach those user attributes, making
      // them available for use in campaign filters.
      await Superwall.shared.register("onboarding_paywall");
      ```
    </CodeGroup>
  </Step>

  <Step title="Copy the credentials" stepNumber={2}>
    1. In Appstack, from the side menu, select **Integrations** > **Superwall.**
    2. Copy the **access token.**
    3. Copy the **app ID.**
  </Step>

  <Step title="Paste the credentials" stepNumber={3}>
    1. In Superwall, from the side menu, select **Integrations** > **Appstack.**
    2. Paste the **access token.**
    3. Paste the **app ID.**

    <Note>
      **Information**

      1. After the integration is active on Superwall's platform, it can take 30-60 minutes to appear as active on Appstack's side.
      2. It's recommended not to edit or modify the integration on Superwall's platform to avoid attribution issues.
    </Note>
  </Step>
</Steps>

<Warning>
  The integration will show an error if less than 50% of events received over the last 24 hours include an `appstackId`. When this threshold is not met, these events cannot be used in ad network integration pages.
</Warning>

## List of events

Below is a list of events you can forward to ad networks to optimize your campaigns.

| Name                            | Definition                                                                                                                                                                                                                                                                   |
| :------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sw_trial_started`              | Fired when a user begins a free trial. Triggered on the initial purchase when the period type is `TRIAL`.                                                                                                                                                                    |
| `sw_trial_qualified`            | Fired when a free trial is still active two hours after it started — meaning the user did not cancel within the qualification window.                                                                                                                                        |
| `sw_trial_converted`            | Fired when a free trial successfully converts to a paid subscription. This happens on the first renewal after the trial period ends.                                                                                                                                         |
| `sw_intro_started`              | Fired when a user begins an intro offer — a paid trial at a discounted price (e.g., \$0.99 for the first week). Triggered on the initial purchase when the period type is `INTRO`                                                                                            |
| `sw_trial_intro_started`        | Fired when either a free trial starts (`sw_trial_started`) or an intro offer starts (`sw_intro_started`). The event triggers as soon as at least one of these conditions is met.                                                                                             |
| `sw_trial_intro_qualified`      | Fired when either a free trial qualifies (`sw_trial_qualified`) or an intro offer starts (`sw_intro_started`). The event triggers as soon as at least one of these conditions is met.                                                                                        |
| `sw_initial_purchase`           | Fired when any of the following occur: a free trial starts (`sw_trial_started`), an intro offer starts (`sw_intro_started`), or a full-price subscription starts (`sw_subscription_started`). The event triggers as soon as at least one of these conditions is met.         |
| `sw_initial_purchase_qualified` | Fired when any of the following occur: a trial qualified happens (`sw_trial_qualified`), an intro offer starts (`sw_intro_started`), or a full-price subscription starts (`sw_subscription_started`). The event triggers as soon as at least one of these conditions is met. |
| `sw_subscription_started`       | Fired when a user starts a paid subscription at full price, with no trial or intro offer involved. Triggered on the initial purchase when the period type is `NORMAL`                                                                                                        |
| `sw_subscription_renewed`       | Fired on each successful renewal of an active subscription. Indicates the user was billed again and remains subscribed for another period.                                                                                                                                   |
| `sw_non_renewing_purchase`      | Fired when a user makes a one-time, non-subscription purchase — any product that is not an auto-renewing subscription (e.g., consumables or non-consumable in-app purchases). Unlike subscription events, this purchase does not renew automatically.                        |

<Prompt description="Use Cursor, Claude Code, or another AI to validate your existing Superwall \+ Appstack integration." actions={["copy", "cursor"]}>
  You are an expert mobile monetization engineer reviewing my existing Superwall + Appstack integration. You are running inside an IDE assistant such as Cursor or Claude Code and you can see my codebase.

  Your goal is to **validate that my Superwall integration fully matches the documentation** and that event and attribution data can flow correctly between Appstack and Superwall. When I paste this prompt and share my platform-specific code and configuration, you should:

  1. **SDK and version checks**
     * Confirm that:
       * The Appstack SDK is installed and initialized correctly for the platform (Swift, Kotlin, Expo, or Flutter).
       * The Superwall SDK version supports Appstack: `Superwall-iOS` 4.12.11+, `Superwall-Android` 2.7.5+, `Superwall-Flutter` 2.4.11+, or `expo-superwall` 1.0.5+.
       * React Native apps use `expo-superwall`, not the archived `react-native-superwall` package.
     * Point out any missing dependencies, outdated versions, or incorrect initialization order (e.g. Superwall methods being used before Appstack has an ID).

  2. **Appstack ID integration**
     * Locate calls to:
       * `Superwall.shared.setIntegrationAttributes(...)` (Swift)
       * `Superwall.instance.setIntegrationAttributes(...)` (Kotlin)
       * `setIntegrationAttributes({ appstackId })` from `expo-superwall` (React Native / Expo)
       * `Superwall.shared.setIntegrationAttributes(...)` with `await AppstackPlugin.getAppstackId()` (Flutter)
     * Verify that:
       * They use the Appstack SDK methods (`getAppstackId` / `getAppstackId()`) exactly as shown in the docs.
       * They are called **after** both SDKs are configured and not redundantly in multiple places.
     * Propose concrete code changes if these calls are missing, misordered, or incorrectly parameterized.

  3. **User attributes / attribution params**
     * Find where I call:
       * `Superwall.shared.setUserAttributes(await AppstackAttributionSdk.shared.getAttributionParams() ?? [:])` inside `Task {}` or another async context (Swift)
       * `Superwall.instance.setUserAttributes(AppstackAttributionSdk.getAttributionParams())` (Kotlin)
       * `useUser().update((await AppstackSDK.getAttributionParams()) ?? {})` (Expo)
       * `Superwall.shared.setUserAttributes((await AppstackPlugin.getAttributionParams()) ?? {})` (Flutter)
     * Validate that:
       * These lines run **once** before the first `Superwall.register` or Expo `registerPlacement` call.
       * Registrations like `"onboarding_paywall"` happen **after** attributes are set so campaign filters can use them.
     * Suggest exact placement and code if the attributes are missing or set too late.

  4. **Validation report & checklist**
     * Produce a clear report summarizing:
       * What is correctly implemented and safe for production.
       * What is missing, misconfigured, or risky, with platform-specific file names and snippets to change.
     * End with a **Superwall-specific checklist** (SDK versions, Appstack ID integration attribute, attribution params as user attributes, register ordering, dashboard credentials) that I can use to confirm my integration fully matches the Superwall integration guide.
</Prompt>
