From 6f6560e2b864082520fddc26eaf22ef0ec0e528e Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Tue, 11 Aug 2026 15:51:15 -0500 Subject: [PATCH 1/9] docs(kmp): add the KMP SDK section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds content/docs/kmp for the Superwall KMP SDK (0.1.1, beta), registered under the SDKs group in the root meta.json. Pages are written standalone rather than reusing content/shared, because remark-sdk-filter only matches (ios|android|expo|flutter) — a /kmp/ page would no-op the filter and render every platform's blocks at once. Behavior is verified against the KMP source rather than ported blindly from the Android docs; the notable divergences (library-declared paywall activity, minSdk 26, the isStatic requirement, the SPM bridge, delegate threading) are documented in guides/platform-differences. Co-Authored-By: Claude Opus 5 --- .claude/launch.json | 11 + content/docs/kmp/changelog.mdx | 32 +++ .../docs/kmp/guides/3rd-party-analytics.mdx | 165 +++++++++++++++ .../kmp/guides/advanced-configuration.mdx | 172 ++++++++++++++++ .../docs/kmp/guides/handling-deep-links.mdx | 137 +++++++++++++ .../docs/kmp/guides/platform-differences.mdx | 138 +++++++++++++ .../kmp/guides/using-superwall-delegate.mdx | 140 +++++++++++++ content/docs/kmp/index.mdx | 84 ++++++++ content/docs/kmp/meta.json | 24 +++ content/docs/kmp/quickstart/configure.mdx | 191 ++++++++++++++++++ .../docs/kmp/quickstart/feature-gating.mdx | 94 +++++++++ content/docs/kmp/quickstart/install.mdx | 153 ++++++++++++++ .../kmp/quickstart/present-first-paywall.mdx | 166 +++++++++++++++ .../tracking-subscription-state.mdx | 156 ++++++++++++++ .../docs/kmp/quickstart/user-management.mdx | 145 +++++++++++++ content/docs/meta.json | 1 + 16 files changed, 1809 insertions(+) create mode 100644 .claude/launch.json create mode 100644 content/docs/kmp/changelog.mdx create mode 100644 content/docs/kmp/guides/3rd-party-analytics.mdx create mode 100644 content/docs/kmp/guides/advanced-configuration.mdx create mode 100644 content/docs/kmp/guides/handling-deep-links.mdx create mode 100644 content/docs/kmp/guides/platform-differences.mdx create mode 100644 content/docs/kmp/guides/using-superwall-delegate.mdx create mode 100644 content/docs/kmp/index.mdx create mode 100644 content/docs/kmp/meta.json create mode 100644 content/docs/kmp/quickstart/configure.mdx create mode 100644 content/docs/kmp/quickstart/feature-gating.mdx create mode 100644 content/docs/kmp/quickstart/install.mdx create mode 100644 content/docs/kmp/quickstart/present-first-paywall.mdx create mode 100644 content/docs/kmp/quickstart/tracking-subscription-state.mdx create mode 100644 content/docs/kmp/quickstart/user-management.mdx diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 00000000..f5383e5e --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "docs", + "runtimeExecutable": "bun", + "runtimeArgs": ["run", "dev"], + "port": 3000 + } + ] +} diff --git a/content/docs/kmp/changelog.mdx b/content/docs/kmp/changelog.mdx new file mode 100644 index 00000000..346985d9 --- /dev/null +++ b/content/docs/kmp/changelog.mdx @@ -0,0 +1,32 @@ +--- +title: "Changelog" +description: "Release notes for the Superwall KMP SDK" +--- + +# CHANGELOG + +The changelog for `Superwall-KMP`. Also see the [releases](https://github.com/superwall/Superwall-KMP/releases) on GitHub. + +## 0.1.1 + +## Enhancements +- Adds threading improvements to reduce main thread load + +## 0.1.0 + +Initial release of the Kotlin Multiplatform SDK for Superwall. + +## Enhancements +- Adds `com.superwall.sdk:superwall-kmp`, a Kotlin Multiplatform wrapper over the native Superwall SDKs. The entire public API lives in `commonMain` — no platform types leak into it, and `Superwall.configure` has an identical signature on both platforms (no `Context` parameter on Android). +- Android support (`minSdk 26`) wrapping `com.superwall.sdk:superwall-android` 2.8.0. The dependency is bundled transitively and an `androidx.startup` initializer captures the `Application`, so integration is a single Gradle dependency. +- iOS support (iOS 14+, `iosArm64`/`iosSimulatorArm64`/`iosX64`) forwarding through **SuperwallKMPBridge**, a self-authored `@objc` Swift facade over SuperwallKit iOS 4.16.1 (pinned exactly). The bridge destructures Swift-only constructs — enum associated values, structs, `async` — into ObjC-visible envelopes consumed via cinterop. +- Adds `Superwall.register(placement:params:handler:feature:)` for gating features behind paywalls, with a `PaywallPresentationHandler` exposing `onPresent`, `onDismiss`, `onError` and `onSkip`. +- Adds `Superwall.subscriptionStatusFlow`, a `StateFlow` that is collectable before `configure` (seeded with `SubscriptionStatus.Unknown`) and emits on the main thread. +- Adds `PurchaseController` for apps that own their purchase logic, with separate `purchaseFromAppStore` and `purchaseFromGooglePlay` entry points. +- Adds `SuperwallDelegate` covering the paywall presentation lifecycle, subscription-status changes, deep links, URLs, custom paywall actions, logging, and link redemption. +- Adds `SuperwallOptions` (including `PaywallOptions` and `TestModeBehavior`), user identity (`identify`, `reset`, user attributes), and deep-link handling via `handleDeepLink`. +- Adds `configureAndAwait`, a suspending twin of `configure`, plus the `Superwall.isConfigured` flag for ordering calls. + +## Notes +- There is no pre-configure call queue: most members throw `SuperwallError.NotConfigured` before `configure`. Guard-exempt members are `handleDeepLink`, the flows, `delegate`, and the introspection properties. +- iOS integration is two steps — the Gradle dependency plus the `SuperwallKMPBridge` Swift package — and the Kotlin framework must be exported as `isStatic = true`, because it does not embed the bridge binary. See the [README](README.md#ios) for details. diff --git a/content/docs/kmp/guides/3rd-party-analytics.mdx b/content/docs/kmp/guides/3rd-party-analytics.mdx new file mode 100644 index 00000000..2d194510 --- /dev/null +++ b/content/docs/kmp/guides/3rd-party-analytics.mdx @@ -0,0 +1,165 @@ +--- +title: "3rd Party Analytics" +description: "Forward Superwall events to your own analytics stack." +--- + + + +**Beta** + +The KMP SDK is in beta and its API may change between releases. + + + +Superwall tracks events internally — paywalls opening, transactions completing, placements firing. You can forward all of them to your own analytics provider through `SuperwallDelegate`. + +## Forwarding events + +Implement `handleSuperwallEvent`: + +```kotlin +import com.superwall.sdk.kmp.SuperwallDelegate +import com.superwall.sdk.kmp.models.events.SuperwallEventInfo + +class AnalyticsDelegate : SuperwallDelegate { + override fun handleSuperwallEvent(eventInfo: SuperwallEventInfo) { + analytics.track( + name = eventInfo.eventType.name, + properties = eventInfo.params.orEmpty(), + ) + } +} + +Superwall.delegate = AnalyticsDelegate() +``` + +
+ +`handleSuperwallEvent` arrives on a **background thread on Android** and on the main thread on iOS. That is ideal for forwarding to an analytics SDK — but do not touch UI from it without hopping to main yourself. See [Platform differences](/kmp/guides/platform-differences#delegate-threading). + +
+ +## The event envelope + +`SuperwallEventInfo` is a flat envelope. `eventType` identifies the event, and only the fields relevant to that event are non-null: + +```kotlin +override fun handleSuperwallEvent(eventInfo: SuperwallEventInfo) { + when (eventInfo.eventType) { + EventType.PAYWALL_OPEN -> { + analytics.track("paywall_open", mapOf( + "paywall_id" to eventInfo.paywallInfo?.identifier, + "paywall_name" to eventInfo.paywallInfo?.name, + )) + } + EventType.TRANSACTION_COMPLETE -> { + analytics.track("purchase", mapOf( + "product_id" to eventInfo.product?.productIdentifier, + )) + } + else -> analytics.track(eventInfo.eventType.name, eventInfo.params.orEmpty()) + } +} +``` + +Commonly useful fields on the envelope: + +?", + }, + placementName: { + description: "The placement that produced the event, where applicable.", + type: "String?", + }, + paywallInfo: { + description: "The paywall involved in the event.", + type: "PaywallInfo?", + }, + transaction: { + description: "The store transaction involved in the event.", + type: "StoreTransaction?", + }, + product: { + description: "The store product involved in the event.", + type: "StoreProduct?", + }, + error: { + description: "A description of the error, for failure events.", + type: "String?", + }, + }} +/> + +## Sending your identifiers to Superwall + +The reverse direction matters too — Superwall can attribute better if it knows your analytics identifiers: + +```kotlin +import com.superwall.sdk.kmp.models.events.IntegrationAttribute + +Superwall.setIntegrationAttributes( + mapOf( + IntegrationAttribute.AMPLITUDE_USER_ID to amplitude.userId, + IntegrationAttribute.MIXPANEL_DISTINCT_ID to mixpanel.distinctId, + IntegrationAttribute.APPSFLYER_ID to appsFlyer.uid, + ), +) +``` + +Supported providers include Adjust, Amplitude, AppsFlyer, Braze, OneSignal, Meta, Firebase, Singular, Iterable, Mixpanel, mParticle, CleverTap, Airship, Kochava, Tenjin, PostHog, Customer.io, and Appstack. Passing `null` for a value removes it. + + + `IntegrationAttribute.FIREBASE_INSTALLATION_ID` is **iOS only** — setting it on Android is skipped + and logs a warning. Every other attribute works on both platforms. + + +## Capturing SDK logs + +`handleLog` gives you the SDK's own log stream: + +```kotlin +override fun handleLog( + level: LogLevel, + scope: LogScope, + message: String?, + info: Map?, + error: String?, +) { + if (level == LogLevel.ERROR) { + crashReporter.log("Superwall/${scope.name}: $message") + } +} +``` + + + `handleLog` fires for **every** internal log line, regardless of the configured log level — that is + hundreds of calls for a single `register`. Filter early, keep the body cheap, and never block in + it. + + +## Controlling what Superwall collects + +To limit what leaves the device, set `eventTrackingBehavior`: + +```kotlin +Superwall.configure( + apiKey = "pk_your_api_key", + options = SuperwallOptions( + eventTrackingBehavior = EventTrackingBehavior.SUPERWALL_ONLY, + ), +) +``` + +| Value | Effect | +| --- | --- | +| `ALL` | Everything is tracked. The default. | +| `SUPERWALL_ONLY` | Only internal Superwall events; your tracking calls, trigger-fire events, and user-attribute updates are suppressed. | +| `NONE` | Nothing is sent to Superwall's servers. | diff --git a/content/docs/kmp/guides/advanced-configuration.mdx b/content/docs/kmp/guides/advanced-configuration.mdx new file mode 100644 index 00000000..dd47b542 --- /dev/null +++ b/content/docs/kmp/guides/advanced-configuration.mdx @@ -0,0 +1,172 @@ +--- +title: "Purchases and Subscription Status" +description: "Own your purchase logic with a PurchaseController." +--- + + + +**Beta** + +The KMP SDK is in beta and its API may change between releases. + + + +By default Superwall handles purchases and subscription status for you, and most apps should leave it that way. If you already have purchase logic — your own billing stack, or a provider like RevenueCat — you can take it over with a `PurchaseController`. + + + Passing a `PurchaseController` means **you** own subscription status. Superwall will not set it for + you, so you must set `Superwall.subscriptionStatus` yourself after every purchase, restore, and app + launch. + + +## The interface + +One interface covers both stores. Each platform invokes only its own store's method, so you implement all three and only two ever run on a given device. + +```kotlin +import com.superwall.sdk.kmp.PurchaseController +import com.superwall.sdk.kmp.models.results.PurchaseResult +import com.superwall.sdk.kmp.models.results.RestorationResult + +class MyPurchaseController : PurchaseController { + + override suspend fun purchaseFromAppStore(productId: String): PurchaseResult { + // Your StoreKit logic + return PurchaseResult.Purchased + } + + override suspend fun purchaseFromGooglePlay( + productId: String, + basePlanId: String?, + offerId: String?, + ): PurchaseResult { + // Your Play Billing logic + return PurchaseResult.Purchased + } + + override suspend fun restorePurchases(): RestorationResult { + // Your restore logic + return RestorationResult.Restored + } +} +``` + +All three are `suspend` functions, so you can do the real asynchronous work inline without callbacks. + + + `purchaseFromGooglePlay` takes `basePlanId` and `offerId` alongside the product id, because Play + models subscriptions with base plans and offers. iOS has no equivalent, which is why the two entry + points are separate rather than one method with platform-shaped arguments. + + +## Handling every case + +`PurchaseResult` is a sealed interface — handle all four: + +| Result | When | +| --- | --- | +| `Purchased` | The product was purchased | +| `Cancelled` | The user cancelled. StoreKit 2's `.userCancelled`, or RevenueCat's `userCancelled == true` | +| `Pending` | Awaiting action. StoreKit 1's `.deferred`, or RevenueCat's `paymentPendingError` | +| `Failed(error)` | Anything else | + +```kotlin +override suspend fun purchaseFromAppStore(productId: String): PurchaseResult { + return try { + when (val outcome = myStore.purchase(productId)) { + is Success -> PurchaseResult.Purchased + is UserCancelled -> PurchaseResult.Cancelled + is Deferred -> PurchaseResult.Pending + is Error -> PurchaseResult.Failed(outcome.message) + } + } catch (e: Exception) { + PurchaseResult.Failed(e.message ?: "Unknown error") + } +} +``` + +There are convenience factories if you prefer them: `PurchaseResult.purchased()`, `.cancelled()`, `.pending()`, `.failed(error)`. + +`RestorationResult` has two cases, `Restored` and `Failed(error)`. + + + `RestorationResult.Restored` means the restore completed **without errors** — not that the user has + an active subscription. Set subscription status from the entitlements you actually resolved, not + from the fact that restore succeeded. + + +## Wire it up + +Pass the controller at configure time: + +```kotlin +Superwall.configure( + apiKey = "pk_your_api_key", + purchaseController = MyPurchaseController(), +) +``` + + + A second `configure` call will **not** install a different purchase controller — repeat calls are + a no-op. Set it on the first call. + + +## Keep subscription status current + +This is the part that is easy to forget. After any purchase, restore, or launch-time entitlement check, tell Superwall what you found: + +```kotlin +import com.superwall.sdk.kmp.models.entitlements.Entitlement +import com.superwall.sdk.kmp.models.entitlements.SubscriptionStatus + +fun syncSubscriptionStatus(activeEntitlementIds: Set) { + Superwall.subscriptionStatus = if (activeEntitlementIds.isEmpty()) { + SubscriptionStatus.Inactive + } else { + SubscriptionStatus.Active( + activeEntitlementIds.map { Entitlement(id = it) }.toSet(), + ) + } +} +``` + +`Entitlement` requires only an `id`; the remaining fields have defaults. + + + Do not leave the status at `SubscriptionStatus.Unknown` once you know the answer. Gated paywalls + and your own UI both branch on it. + + +## Consumables on Android + +Play Billing requires consuming a purchase before the same product can be bought again: + +```kotlin +val token = Superwall.consume(purchaseToken) +``` + +This is an **Android** operation. On iOS it echoes the token back unchanged, so it is safe to call from shared code without a platform check. + +## Restoring + +`Superwall.restorePurchases()` routes through your controller's `restorePurchases()` when one is configured, and through the native SDK otherwise: + +```kotlin +when (val result = Superwall.restorePurchases()) { + is RestorationResult.Restored -> println("Restored") + is RestorationResult.Failed -> println("Failed: ${result.error}") +} +``` + +Failure stays in the return type — it does not throw. + +## Observing purchases you did not make + +If you want Superwall to see transactions that happen outside of a paywall without taking over purchasing entirely, skip the controller and set an option instead: + +```kotlin +Superwall.configure( + apiKey = "pk_your_api_key", + options = SuperwallOptions(shouldObservePurchases = true), +) +``` diff --git a/content/docs/kmp/guides/handling-deep-links.mdx b/content/docs/kmp/guides/handling-deep-links.mdx new file mode 100644 index 00000000..f3a877b4 --- /dev/null +++ b/content/docs/kmp/guides/handling-deep-links.mdx @@ -0,0 +1,137 @@ +--- +title: "Handling Deep Links" +description: "Handle Superwall deep links for paywall previews and web checkout redemption." +--- + + + +**Beta** + +The KMP SDK is in beta and its API may change between releases. + + + +Superwall uses deep links for two things: previewing paywalls on a real device, and redeeming web checkout codes. Both flow through one call. + +## Pass the URL to Superwall + +```kotlin +val handled = Superwall.handleDeepLink(url) +``` + +It returns whether the SDK recognized and handled the link, so you can fall through to your own routing when it did not: + +```kotlin +fun onDeepLink(url: String) { + if (Superwall.handleDeepLink(url)) return + myRouter.navigate(url) +} +``` + +
+ +`handleDeepLink` is **guard-exempt** — you can call it before `Superwall.configure` without hitting `SuperwallError.NotConfigured`. That is deliberate: cold-starting from a deep link is its primary use, and it would be useless if you had to sequence it behind configuration. + +It takes a `String`, not a platform URL type, so it is callable from `commonMain`. + +
+ +## Wiring it up per platform + +The SDK takes a plain `String`, so the only platform-specific part is getting the URL from the OS to your shared code. + +**Android** — from the activity that receives the intent: + +```kotlin +// androidMain +override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + intent?.data?.let { Superwall.handleDeepLink(it.toString()) } +} + +override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + intent.data?.let { Superwall.handleDeepLink(it.toString()) } +} +``` + +Declare your intent filter in `AndroidManifest.xml` as you would for any deep link. + +**iOS** — from your `App` or `AppDelegate`: + +```swift +// SwiftUI +.onOpenURL { url in + Superwall.shared.handleDeepLink(url: url.absoluteString) +} +``` + + + Register your URL scheme with the OS as usual — an `intent-filter` on Android, a URL type in your + Xcode target on iOS. Superwall does not do that part for you. + + +## Web checkout redemption + +When a user buys on the web and returns to your app, the redemption arrives as a deep link. Observe the outcome through the delegate: + +```kotlin +import com.superwall.sdk.kmp.models.redemption.RedemptionResult + +class MyDelegate : SuperwallDelegate { + override fun willRedeemLink() { + showSpinner() + } + + override fun didRedeemLink(result: RedemptionResult) { + hideSpinner() + when (result) { + is RedemptionResult.Success -> unlock(result.redemptionInfo) + is RedemptionResult.Error -> showError(result.error) + is RedemptionResult.ExpiredCode -> showExpired(result.info) + is RedemptionResult.InvalidCode -> showInvalid() + is RedemptionResult.ExpiredSubscription -> showExpiredSubscription() + } + } +} +``` + +Every case carries the `code` that was redeemed. + +
+ +`willRedeemLink` and `didRedeemLink` are analytics-shaped hooks: they arrive on a **background thread on Android**. The spinner calls above need a main-thread hop on Android — see [Platform differences](/kmp/guides/platform-differences#delegate-threading). + +
+ +## Superwall app links + +`SuperwallDelegate.handleSuperwallDeepLink` reports links of the form `yoursubdomain.superwall.app/app-link/...`, broken into path components and query parameters: + +```kotlin +override fun handleSuperwallDeepLink( + fullURL: String, + pathComponents: List, + queryParameters: Map, +) { + // Route based on pathComponents +} +``` + + + +**This hook is iOS only.** `superwall-android` has no equivalent delegate method, so it is never invoked on Android. + +`Superwall.handleDeepLink(url)` itself works on **both** platforms — it is only this structured callback that is missing. On Android, parse the URL yourself in the activity that receives it. + + + +## Paywall previews + +Deep links are also how you preview a paywall on a real device from the dashboard. Point the link at your app and pass it to `handleDeepLink`. + +
+ +On **Android**, previews need the SDK's debug activities declared in your own manifest — the KMP library declares the paywall activity but not the debug ones. See [Platform differences](/kmp/guides/platform-differences#in-app-paywall-previews-on-android) for the snippet. This path is not yet verified end-to-end on KMP. + +
diff --git a/content/docs/kmp/guides/platform-differences.mdx b/content/docs/kmp/guides/platform-differences.mdx new file mode 100644 index 00000000..0fa5f1ae --- /dev/null +++ b/content/docs/kmp/guides/platform-differences.mdx @@ -0,0 +1,138 @@ +--- +title: "Platform Differences" +description: "Where Android and iOS behavior is not one-to-one in the KMP SDK." +--- + + + +**Beta** + +The KMP SDK is in beta and its API may change between releases. + + + +The KMP SDK's public API is identical on both platforms — one signature, no platform types, no `expect`/`actual` of your own. But it wraps two different native SDKs, and in a handful of places they do not offer the same thing. + +This page is the complete list. Everything not mentioned here behaves the same on Android and iOS. + +## APIs that differ + +| API | Behavior | +| --- | --- | +| `SuperwallDelegate.handleSuperwallDeepLink` | **iOS only.** `superwall-android` has no equivalent delegate hook, so this is never invoked on Android. | +| `Superwall.consume(purchaseToken)` | **Android.** Consumes a Play Billing purchase so it can be bought again. On iOS it echoes the token back unchanged. | +| `IntegrationAttribute.FIREBASE_INSTALLATION_ID` | **iOS only.** `superwall-android` has no counterpart; setting it on Android is skipped and logs a warning. Every other `IntegrationAttribute` works on both. | + +That is the whole list of behavioral gaps. Notably, customer info is **not** on it — see [below](#what-is-not-a-difference). + +## Options that only apply to one platform + +Setting one of these on the other platform is harmless — it is simply ignored. + +**Android only** + +| Option | What it does | +| --- | --- | +| `SuperwallOptions.passIdentifiersToPlayStore` | Sends the raw `appUserId` to Play instead of a SHA-256 hash | +| `SuperwallOptions.useMockReviews` | Enables mock review functionality | +| `PaywallOptions.preloadDeviceOverrides` | Per-device-tier overrides for `shouldPreload` | +| `PaywallOptions.onBackPressed` | Callback for the hardware back button while a paywall shows | + +**iOS only** + +| Option | What it does | +| --- | --- | +| `SuperwallOptions.shouldBypassAppTransactionCheck` | Skips the app transaction check on launch | +| `SuperwallOptions.maxConfigRetryCount` | Retry attempts for fetching configuration (default `6`) | +| `PaywallOptions.transactionBackgroundView` | The view behind Apple's payment sheet | + +## Delegate threading + +This is the difference most likely to bite you, because it is a runtime behavior rather than a missing method. + +`SuperwallDelegate` callbacks are **not** forced onto the main thread. They arrive on whatever thread the native SDK called from, which splits cleanly: + +| Hooks | Android | iOS | +| --- | --- | --- | +| `willPresentPaywall`, `didPresentPaywall`, `willDismissPaywall`, `didDismissPaywall`, `handleCustomPaywallAction`, `paywallWillOpenURL`, `paywallWillOpenDeepLink` | Main | Main | +| `handleSuperwallEvent`, `handleLog`, `subscriptionStatusDidChange`, `customerInfoDidChange`, `userAttributesDidChange`, `willRedeemLink`, `didRedeemLink` | **Background** | Main | + +So the paywall lifecycle hooks are safe for UI work everywhere. The analytics-shaped hooks are not, on Android. + +```kotlin +override fun handleSuperwallEvent(eventInfo: SuperwallEventInfo) { + // Fine — forwarding to an analytics SDK. + analytics.track(eventInfo.eventType.name) + + // NOT fine on Android — this is a background thread. + // updateMyUi() +} +``` + +If you need UI from one of those, hop yourself, or collect a flow instead: + +```kotlin +scope.launch(Dispatchers.Main) { updateMyUi() } +``` + + + `Superwall.subscriptionStatusFlow` emits on the main thread on both platforms, so collecting it is + the easier path when you want subscription changes to drive UI. It does the hop for you. + + +Two more consequences worth designing for: delegate implementations should be **thread-safe** (the analytics hooks are not serialized against each other), and they run **synchronously on an SDK thread** — blocking in one slows the SDK, so keep them short. + + + `PaywallPresentationHandler` closures and the `register` `feature` closure are a different story: + those *are* delivered on the main thread on both platforms, deliberately, because they gate UI. + + +## Install differences + +The two platforms do not take the same amount of setup. See [Install the SDK](/kmp/quickstart/install) for the detail. + +| | Android | iOS | +| --- | --- | --- | +| Steps | One Gradle dependency | Gradle dependency **plus** the `SuperwallKMPBridge` Swift package | +| Manifest / project edits | None — the library manifest declares the paywall activity and the startup initializer | Kotlin framework must be exported with `isStatic = true` | +| Native SDK | `superwall-android` 2.8.0, transitively | SuperwallKit 4.16.1, pinned exactly by the bridge | +| Minimum | `minSdk` 26 | iOS 14 | + +## In-app paywall previews on Android + +
+ +The KMP library manifest declares `SuperwallPaywallActivity`, which is what paywall presentation needs. It does **not** declare the debug activities that the standalone Android SDK's [in-app paywall previews](/android/quickstart/in-app-paywall-previews) rely on, and neither does `superwall-android`. + +If you need previews on Android, declare them in your own `AndroidManifest.xml`: + +```xml + + + +``` + +This path is not yet verified end-to-end on KMP. If you try it, we would like to hear how it goes — [open an issue](https://github.com/superwall/Superwall-KMP/issues). + +
+ +## What is *not* a difference + +Some things look like platform gaps if you read the SDK's inline documentation, but are not: + +
+ +`Superwall.customerInfoFlow`, `Superwall.getCustomerInfo()`, +`SuperwallDelegate.customerInfoDidChange`, and +`Superwall.getEntitlementsByProductIds()` carry `@platform iOS` annotations or +"pending upstream support" notes in the SDK's KDoc. **Those annotations are stale.** All four are +wired on Android against `superwall-android` 2.8.0, which added the native APIs they were waiting +on. + +We have flagged this for the SDK team. Trust this page over the inline docs until the KDoc catches up. + +
+ +## Getting the right API key + +Android and iOS have separate Public API Keys in the dashboard. The SDK does not need `expect`/`actual`, but your key does — supply the right one per platform via an `expect val`, a build-time constant, or whatever your project already uses for platform config. diff --git a/content/docs/kmp/guides/using-superwall-delegate.mdx b/content/docs/kmp/guides/using-superwall-delegate.mdx new file mode 100644 index 00000000..793de965 --- /dev/null +++ b/content/docs/kmp/guides/using-superwall-delegate.mdx @@ -0,0 +1,140 @@ +--- +title: "Using the Superwall Delegate" +description: "Observe the paywall lifecycle and SDK events from shared Kotlin code." +--- + + + +**Beta** + +The KMP SDK is in beta and its API may change between releases. + + + +`SuperwallDelegate` is how you observe what the SDK is doing — paywalls opening and closing, subscription status changing, events being tracked, links being redeemed. + +Every method has a default no-op implementation, so override only the ones you need. + +## Setting the delegate + +```kotlin +import com.superwall.sdk.kmp.Superwall +import com.superwall.sdk.kmp.SuperwallDelegate +import com.superwall.sdk.kmp.models.paywall.PaywallInfo + +class MyDelegate : SuperwallDelegate { + override fun didPresentPaywall(paywallInfo: PaywallInfo) { + println("Presented ${paywallInfo.name}") + } + + override fun didDismissPaywall(paywallInfo: PaywallInfo) { + println("Dismissed ${paywallInfo.name}") + } +} + +Superwall.delegate = MyDelegate() +``` + + + `delegate` is one of the few members you can set **before** `configure`. The value is stored + immediately and installed into the native SDK when configuration happens, so you will not miss + early events. Setting it to `null` clears it. + + +## What you can observe + +**Paywall lifecycle** + +```kotlin +override fun willPresentPaywall(paywallInfo: PaywallInfo) {} +override fun didPresentPaywall(paywallInfo: PaywallInfo) {} +override fun willDismissPaywall(paywallInfo: PaywallInfo) {} +override fun didDismissPaywall(paywallInfo: PaywallInfo) {} +``` + +**Paywall interactions** + +```kotlin +override fun handleCustomPaywallAction(name: String) {} +override fun paywallWillOpenURL(url: String) {} +override fun paywallWillOpenDeepLink(url: String) {} +``` + +**State changes** + +```kotlin +override fun subscriptionStatusDidChange(from: SubscriptionStatus, to: SubscriptionStatus) {} +override fun customerInfoDidChange(from: CustomerInfo, to: CustomerInfo) {} +override fun userAttributesDidChange(newAttributes: Map) {} +``` + +**Analytics and logging** + +```kotlin +override fun handleSuperwallEvent(eventInfo: SuperwallEventInfo) {} + +override fun handleLog( + level: LogLevel, + scope: LogScope, + message: String?, + info: Map?, + error: String?, +) {} +``` + +**Web checkout redemption** + +```kotlin +override fun willRedeemLink() {} +override fun didRedeemLink(result: RedemptionResult) {} +``` + +## Threading — read this before you touch UI + +
+ +Delegate callbacks are **not** forced onto the main thread. They arrive on whatever thread the native SDK called from, and that is not the same on both platforms. + +- **Paywall lifecycle hooks** arrive on the **main thread** on Android and iOS. Update UI from these directly. +- **Analytics-shaped hooks** (`handleSuperwallEvent`, `handleLog`, `subscriptionStatusDidChange`, `customerInfoDidChange`, `userAttributesDidChange`, `willRedeemLink`, `didRedeemLink`) arrive on a **background thread on Android**, and on the main thread on iOS. + +This is deliberate. `handleLog` fires for every internal log line regardless of log level — forcing that onto the main thread would cost you frames. + +
+ +Two things this asks of your implementation: + +1. **Be thread-safe.** The analytics hooks are not serialized against each other. +2. **Be quick.** They run synchronously on an SDK thread, so blocking in one slows the SDK. + +If you need UI work from an analytics-shaped hook, hop yourself: + +```kotlin +override fun subscriptionStatusDidChange(from: SubscriptionStatus, to: SubscriptionStatus) { + scope.launch(Dispatchers.Main) { + updateUi(to) + } +} +``` + +Or skip the delegate for that case entirely and collect [`subscriptionStatusFlow`](/kmp/quickstart/tracking-subscription-state), which already emits on main. + +## Platform gap + +`handleSuperwallDeepLink` is **iOS only** — `superwall-android` has no equivalent delegate hook, so it is never invoked on Android. See [Platform differences](/kmp/guides/platform-differences). + +```kotlin +// iOS only +override fun handleSuperwallDeepLink( + fullURL: String, + pathComponents: List, + queryParameters: Map, +) {} +``` + +## The delegate and the flows + +Setting or clearing the delegate never uninstalls the SDK's own internal delegate, so `subscriptionStatusFlow` and `customerInfoFlow` keep working whether or not you have one set. Use whichever fits: + +- **Delegate** when you want the full event firehose, or the paywall lifecycle. +- **Flows** when you want subscription state to drive UI, and you would rather not think about threads. diff --git a/content/docs/kmp/index.mdx b/content/docs/kmp/index.mdx new file mode 100644 index 00000000..415e6d12 --- /dev/null +++ b/content/docs/kmp/index.mdx @@ -0,0 +1,84 @@ +--- +title: "Welcome" +description: "Welcome to the Superwall KMP SDK documentation" +--- + + + +**Beta** + +The KMP SDK is in beta. The API may change between releases, and these docs describe behavior that is still settling. If you hit something that does not match what you see, please [open an issue](https://github.com/superwall/Superwall-KMP/issues). + + + +The Superwall KMP SDK brings paywalls, placements, and entitlements to Kotlin Multiplatform. It wraps the native Superwall SDKs — `superwall-android` on Android, SuperwallKit on iOS — behind a single API that lives entirely in `commonMain`. + +The practical consequence: no `expect`/`actual` of your own, no platform types in your shared code, and an identical `configure` signature on both platforms. There is no `Context` parameter on Android. + +```kotlin +import com.superwall.sdk.kmp.Superwall + +Superwall.configure(apiKey = "pk_your_api_key") + +Superwall.register(placement = "campaign_trigger") { + launchTheFeature() +} +``` + +## Platform support + +| Platform | Support | Wraps | +| --- | --- | --- | +| Android | `minSdk 26` | `com.superwall.sdk:superwall-android` 2.8.0 | +| iOS | iOS 14+ (`iosArm64`, `iosSimulatorArm64`, `iosX64`) | SuperwallKit iOS 4.16.1, pinned exactly | + +Those are the only two targets. There are no JVM, JS, desktop, or watchOS artifacts — the SDK is a wrapper over two native SDKs, so it goes where they go. + + + Android's `minSdk` here is **26**, higher than the standalone Android SDK's 23. If you are adding + KMP to an existing project, check your `minSdk` before you start. + + +## How it fits together + +Your shared Kotlin code calls one API. Underneath, each platform resolves to its own native SDK: + +- **Android** wraps `superwall-android` directly. One Gradle dependency pulls it in, and an `androidx.startup` initializer captures the `Application` for you. +- **iOS** forwards through **SuperwallKMPBridge**, an `@objc` Swift facade over SuperwallKit that flattens Swift-only constructs (enum associated values, structs, `async`) into something Kotlin can consume via cinterop. Your app supplies that bridge as a Swift package. + +That second point is the one that catches people, and it is covered in [Install the SDK](/kmp/quickstart/install). + +## Quick Links + + + + Install, configure, and present your first paywall + + + Where Android and iOS behavior is not one-to-one + + + Own your purchase logic with a `PurchaseController` + + + Observe the paywall lifecycle and SDK events + + + A runnable Compose Multiplatform sample for Android and iOS + + + Release notes for the KMP SDK + + + +## Feedback + +The KMP SDK is actively developed and we want to hear what is missing. + +If you have feedback on these docs, please leave a rating and message at the bottom of the page. For SDK bugs, [open an issue on GitHub](https://github.com/superwall/Superwall-KMP/issues). + + diff --git a/content/docs/kmp/meta.json b/content/docs/kmp/meta.json new file mode 100644 index 00000000..44a9a4b0 --- /dev/null +++ b/content/docs/kmp/meta.json @@ -0,0 +1,24 @@ +{ + "title": "KMP SDK", + "root": true, + "pages": [ + "index", + "changelog", + + "---Quickstart---", + "quickstart/install", + "quickstart/configure", + "quickstart/present-first-paywall", + "quickstart/user-management", + "quickstart/feature-gating", + "quickstart/tracking-subscription-state", + + "---Common Use Cases---", + "guides/platform-differences", + "guides/advanced-configuration", + "guides/using-superwall-delegate", + "guides/3rd-party-analytics", + "guides/handling-deep-links", + "[Example App](https://github.com/superwall/Superwall-KMP/tree/main/sample)" + ] +} diff --git a/content/docs/kmp/quickstart/configure.mdx b/content/docs/kmp/quickstart/configure.mdx new file mode 100644 index 00000000..642f03e8 --- /dev/null +++ b/content/docs/kmp/quickstart/configure.mdx @@ -0,0 +1,191 @@ +--- +title: "Configure the SDK" +description: Configure Superwall in your shared Kotlin code. +--- + + + +**Beta** + +The KMP SDK is in beta and its API may change between releases. + + + +## Configure + +Call `Superwall.configure` as early as possible in your app's lifecycle, from shared code: + +```kotlin +import com.superwall.sdk.kmp.Superwall + +Superwall.configure(apiKey = "pk_your_api_key") { result -> + result.onFailure { println("Superwall configuration failed: $it") } +} +``` + +The signature is identical on both platforms: + +) -> Unit)?", + default: "null", + }, + }} +/> + +The call is fire-and-forget. `completion` reports the real outcome — an invalid API key surfaces there, not as a thrown exception. + + + Calling `configure` a second time is a no-op. The repeat call logs a warning through the delegate's + `handleLog`, does not re-install your options or purchase controller, and invokes its completion + with the first call's outcome. + + +## There is no pre-configure call queue + +This is the thing to internalize before you write anything else. + +
+ +Calls made before `configure` are **not** buffered and replayed. Almost every member throws `SuperwallError.NotConfigured` instead. + +The deliberate exemptions, which are safe to touch at any time: + +- `handleDeepLink` — deep-link cold start is its whole purpose +- `subscriptionStatusFlow` and `customerInfoFlow` — pre-seeded, common-owned flows +- `delegate` — stored immediately, installed natively at configure +- `isConfigured`, `isInitialized`, and `configurationStatus` + +
+ +Everything else — `register`, `identify`, `setUserAttributes`, `entitlements`, and the rest — needs configuration to have happened first. + +## Ordering your calls + +Two supported ways to sequence work behind configuration. + +**Await it.** `configureAndAwait` is the suspending twin, and the sanctioned ordering tool. It resumes when the native SDK reports completion and throws `SuperwallError.ConfigurationFailed` on failure: + +```kotlin +suspend fun startSuperwall() { + Superwall.configureAndAwait(apiKey = "pk_your_api_key") + + // Safe from here on. + Superwall.identify(userId = "abc123") +} +``` + +**Gate on the flag.** `Superwall.isConfigured` is readable at any time: + +```kotlin +if (Superwall.isConfigured) { + Superwall.register(placement = "campaign_trigger") +} +``` + +`Superwall.configurationStatus` gives you the fuller picture — `PENDING`, `CONFIGURED`, or `FAILED`. + +## Options + +Pass `SuperwallOptions` to customize behavior. Every field has a default, so set only what you need: + +```kotlin +import com.superwall.sdk.kmp.models.options.PaywallOptions +import com.superwall.sdk.kmp.models.options.SuperwallOptions + +Superwall.configure( + apiKey = "pk_your_api_key", + options = SuperwallOptions( + paywalls = PaywallOptions( + shouldPreload = false, + isHapticFeedbackEnabled = false, + ), + ), +) +``` + +Frequently used `SuperwallOptions` fields: + + + +Some options only apply to one platform. `passIdentifiersToPlayStore` and `useMockReviews` are Android-only; `shouldBypassAppTransactionCheck` and `maxConfigRetryCount` are iOS-only. Setting one on the other platform is harmless — it is ignored. See [Platform differences](/kmp/guides/platform-differences). + + + Leave `networkEnvironment` alone unless the Superwall team has explicitly told you otherwise. + + +## Logging + +Set the log level at configure time, or change it later: + +```kotlin +import com.superwall.sdk.kmp.models.options.LogLevel + +Superwall.logLevel = LogLevel.WARN +``` + +Levels are `DEBUG`, `INFO`, `WARN`, `ERROR`, and `NONE`. + + + On iOS, `LogLevel.NONE` maps to Swift's `.none`. If you are reading native logs or Swift docs + alongside these, do not mistake it for an absent optional. + + +Next, [present your first paywall](/kmp/quickstart/present-first-paywall). diff --git a/content/docs/kmp/quickstart/feature-gating.mdx b/content/docs/kmp/quickstart/feature-gating.mdx new file mode 100644 index 00000000..4ffa9279 --- /dev/null +++ b/content/docs/kmp/quickstart/feature-gating.mdx @@ -0,0 +1,94 @@ +--- +title: "Feature Gating" +description: "Control access to premium features with Superwall placements." +--- + + + +**Beta** + +The KMP SDK is in beta and its API may change between releases. + + + +## The idea + +`Superwall.register` lets you register a [placement](/dashboard/dashboard-campaigns/campaigns-placements) to access a feature that may or may not be paywalled later in time. Whether the user can access that feature without paying is a dashboard decision, not a code decision. + +```kotlin +fun pressedWorkoutButton() { + // Remotely decide if a paywall is shown, and whether + // startWorkout() is a paid-only feature. + Superwall.register(placement = "StartWorkout") { + navigation.startWorkout() + } +} +``` + +Given how cheap `register` is, we strongly recommend registering **all core functionality** — that is what lets you change what is gated without shipping an app update. + +## What actually happens + +When you register a placement: + +1. The SDK checks your campaigns for a matching audience filter. +2. If one matches and the user is not in a holdout, the assigned paywall is presented. +3. Once a user is assigned a paywall for an audience, they keep seeing that paywall until you remove it from the audience or reset assignments. +4. After the paywall closes, the SDK looks at the paywall's **Feature Gating** value, set in the paywall editor under **General → Feature Gating**: + - **Non Gated** — the `feature` closure runs when the paywall is dismissed, whether they paid or not. + - **Gated** — the `feature` closure runs only if the user is already paying, or begins paying. +5. If no paywall is configured for the placement, the feature runs immediately with no extra network calls. + +## Gating with entitlements directly + +Sometimes you need to branch on subscription state rather than gate a call. Read it synchronously: + +```kotlin +import com.superwall.sdk.kmp.models.entitlements.SubscriptionStatus + +if (Superwall.subscriptionStatus.isActive) { + showProContent() +} else { + showFreeContent() +} +``` + +Or collect the flow to keep UI in sync — see [Tracking subscription state](/kmp/quickstart/tracking-subscription-state). + + + Prefer `register` with a `feature` closure over hand-rolled `if` checks where you can. The closure + keeps the decision on the dashboard; an `if` statement hard-codes it into the build. + + +## Inspecting entitlements + +`Superwall.entitlements` is an immutable snapshot: + +```kotlin +val entitlements = Superwall.entitlements + +entitlements.active // Set +entitlements.inactive // Set +entitlements.all // Set +entitlements.web // Set — granted via web checkout +``` + +Each `Entitlement` carries its `id`, `productIds`, `store`, expiry and renewal dates, and whether it is a lifetime purchase. + +To resolve entitlements for specific products, use `getEntitlementsByProductIds`, which asks the native SDK on both platforms: + +```kotlin +val granted = Superwall.getEntitlementsByProductIds(setOf("pro_monthly", "pro_annual")) +``` + +## Previewing the outcome + +To adjust UI *before* a placement fires — hiding an upgrade button for users who would never see a paywall, say — ask what registering would do: + +```kotlin +val result = Superwall.getPresentationResult(placement = "StartWorkout") +``` + +This presents nothing. It just tells you what would happen. + +Next, [track subscription state](/kmp/quickstart/tracking-subscription-state). diff --git a/content/docs/kmp/quickstart/install.mdx b/content/docs/kmp/quickstart/install.mdx new file mode 100644 index 00000000..90444b40 --- /dev/null +++ b/content/docs/kmp/quickstart/install.mdx @@ -0,0 +1,153 @@ +--- +title: "Install the SDK" +description: Add the Superwall KMP SDK to your Kotlin Multiplatform project. +--- + + + +**Beta** + +The KMP SDK is in beta and its API may change between releases. + + + +## Requirements + +| Target | Requirement | +| --- | --- | +| Android | `minSdk` 26, `compileSdk` 36 | +| iOS | iOS 14+ (`iosArm64`, `iosSimulatorArm64`, `iosX64`) | +| Kotlin | 2.3.10 | + +Android is the shorter path: one Gradle dependency and you are done. iOS needs a second step, because the Kotlin framework does not embed the Swift bridge binary it compiles against. + +## Android + +Add the dependency to your shared module. Because the public API lives in `commonMain`, you can declare it there and both targets pick it up. + + + +```kotlin build.gradle.kts +kotlin { + sourceSets { + commonMain.dependencies { + implementation("com.superwall.sdk:superwall-kmp:0.1.1") + } + } +} +``` + +```toml libs.versions.toml +[versions] +superwall-kmp = "0.1.1" + +[libraries] +superwall-kmp = { module = "com.superwall.sdk:superwall-kmp", version.ref = "superwall-kmp" } + +# And in your shared module's build.gradle.kts +# commonMain.dependencies { implementation(libs.superwall.kmp) } +``` + + + +`superwall-android` comes along transitively — do not add it yourself. + +
+ +**You do not need to edit `AndroidManifest.xml`.** This is the main way KMP install differs from the [standalone Android SDK](/android/quickstart/install), whose docs ask you to declare the paywall activity and permissions by hand. + +The KMP library manifest already declares `SuperwallPaywallActivity`, and `superwall-android` declares the `INTERNET`, `ACCESS_NETWORK_STATE`, and `POST_NOTIFICATIONS` permissions. Manifest merging folds all of it into your app. + +
+ +### No `Context`, and what to do if that breaks + +`Superwall.configure` takes no `Context` on Android. An `androidx.startup` initializer in the library manifest captures the `Application` before any of your code runs, which is what lets the `commonMain` signature stay platform-free. + +If your app strips the startup provider — some apps remove `InitializationProvider` deliberately, and some shrinkers remove it by accident — that capture never happens and `configure()` fails with `SuperwallError.NotInitialized`. The escape hatch is an Android-only extension function: + +```kotlin +// androidMain — only needed if the androidx.startup provider was removed +import com.superwall.sdk.kmp.androidSetup + +class MyApplication : Application() { + override fun onCreate() { + super.onCreate() + Superwall.androidSetup(this) + } +} +``` + +It is idempotent, so calling it defensively alongside a working initializer is harmless. + +## iOS + +iOS is two steps. Miss the second one and the app fails to link. + +### 1. Export the Kotlin framework as static + +In your shared module, the framework **must** be static: + +```kotlin +// shared/build.gradle.kts +kotlin { + listOf(iosArm64(), iosSimulatorArm64(), iosX64()).forEach { + it.binaries.framework { + baseName = "Shared" + isStatic = true // required + } + } +} +``` + +
+ +`isStatic = true` is not a preference. The Kotlin framework compiles against the bridge's Objective-C headers only (compile-only cinterop) and never embeds the bridge binary, so a dynamic framework has nothing to resolve those symbols against at link time. + +
+ +### 2. Add the SuperwallKMPBridge Swift package + +In Xcode: **File → Add Package Dependencies…**, then paste the repository URL: + +``` +https://github.com/superwall/Superwall-KMP +``` + +Add the **`SuperwallKMPBridge`** product to your app target. + + + +**Do not add SuperwallKit separately.** + +The bridge package pins SuperwallKit iOS to exactly `4.16.1` and pulls it in transitively. The pinned binary and the headers the Kotlin side was compiled against are one release unit — adding SuperwallKit yourself invites a version conflict that SPM cannot resolve. + + + +
+ +**A missing bridge is a build-time failure, not a runtime one.** Because the Kotlin side uses compile-only cinterop, forgetting this step surfaces as undefined-symbol link errors when Xcode builds your app — not as a crash on launch or a paywall that silently fails to present. If you see linker errors mentioning bridge symbols, this step is what is missing. + +
+ +## Get your API key + +You need your **Public API Key** from the Superwall dashboard, under your app's settings. It is safe to ship in client code. + +Android and iOS have separate keys in the dashboard. In a KMP app your `configure` call usually lives in shared code, so if you want one call site you will need to supply the right key per platform — an `expect`/`actual` value or a build-time constant both work. + + + The SDK itself needs no `expect`/`actual`. This is only about which API key string you hand it. + + +## Verify the install + +Build both targets before you write any integration code. On iOS in particular, a successful build is the signal that step 2 landed: + +```bash +./gradlew :shared:build +``` + +Then build the iOS app from Xcode. + +**And you're done!** Now you're ready to [configure the SDK](/kmp/quickstart/configure) 👇 diff --git a/content/docs/kmp/quickstart/present-first-paywall.mdx b/content/docs/kmp/quickstart/present-first-paywall.mdx new file mode 100644 index 00000000..4f8ffbc9 --- /dev/null +++ b/content/docs/kmp/quickstart/present-first-paywall.mdx @@ -0,0 +1,166 @@ +--- +title: "Present your first paywall" +description: Register a placement and present a Superwall paywall from shared code. +--- + + + +**Beta** + +The KMP SDK is in beta and its API may change between releases. + + + +## Register a placement + +Paywalls are presented by registering a **placement**. You do not tell the SDK to show a paywall — you tell it a placement occurred, and your campaign on the dashboard decides what happens. + +```kotlin +Superwall.register(placement = "campaign_trigger") +``` + +That one line is a complete integration. Whether a paywall appears, which one, and to whom, is all configured on the dashboard without shipping an app update. + + + The placement name must match one you have added to a campaign on the + [dashboard](https://superwall.com/dashboard). A name that is not in any campaign resolves to + `PaywallSkippedReason.PlacementNotFound`. + + +## Gate a feature behind it + +Pass a `feature` closure to run code that should only happen if the user is entitled to it: + +```kotlin +Superwall.register(placement = "campaign_trigger") { + launchTheFeature() +} +``` + +When the closure runs depends on the paywall's feature-gating behavior — immediately when no paywall shows, or after a purchase or restore when the placement is gated. [Feature gating](/kmp/quickstart/feature-gating) covers the rules. + +## Pass parameters + +`params` are usable in audience filters and on the paywall itself: + +```kotlin +Superwall.register( + placement = "campaign_trigger", + params = mapOf( + "source" to "onboarding", + "isTrialEligible" to true, + ), +) +``` + +Values may be `String`, `Boolean`, `Long`, `Double`, `List`, `Map`, or `Set`. Anything else is stringified. + +## Observe what happened + +A `PaywallPresentationHandler` reports on the presentation. Set only the closures you care about; unset ones are never invoked. + +```kotlin +import com.superwall.sdk.kmp.PaywallPresentationHandler +import com.superwall.sdk.kmp.models.results.PaywallResult +import com.superwall.sdk.kmp.models.results.PaywallSkippedReason + +val handler = PaywallPresentationHandler() + +handler.onPresent { info -> + println("Presented ${info.name}") +} + +handler.onDismiss { info, result -> + when (result) { + is PaywallResult.Purchased -> println("Purchased ${result.productId}") + is PaywallResult.Restored -> println("Restored") + is PaywallResult.Declined -> println("Declined") + } +} + +handler.onSkip { reason -> + when (reason) { + is PaywallSkippedReason.Holdout -> println("Holdout: ${reason.experiment.id}") + is PaywallSkippedReason.NoAudienceMatch -> println("No audience match") + is PaywallSkippedReason.PlacementNotFound -> println("Placement not found") + } +} + +handler.onError { error -> + println("Paywall error: $error") +} + +Superwall.register( + placement = "campaign_trigger", + handler = handler, +) { + launchTheFeature() +} +``` + + + `onSkip` is not a failure path. A holdout or an unmatched audience filter means your campaign + worked as configured — the user simply was not meant to see a paywall. + + +All handler closures and the `feature` closure are delivered on the **main thread**, on both platforms. You can touch UI from them directly. + +### Custom callbacks + +`onCustomCallback` is the one closure that returns a value. A paywall can request an action from your app and branch on the result: + +```kotlin +import com.superwall.sdk.kmp.models.callbacks.CustomCallbackResult + +handler.onCustomCallback { callback -> + when (callback.name) { + "validate_email" -> { + val email = callback.variables?.get("email") as? String + if (isValidEmail(email)) { + CustomCallbackResult.success(mapOf("validated" to true)) + } else { + CustomCallbackResult.failure(mapOf("error" to "Invalid email")) + } + } + else -> CustomCallbackResult.failure() + } +} +``` + +It is a `suspend` closure, so you can do real work in it. When it is unset, the SDK responds with `CustomCallbackResult.failure()`. + +## Check before you register + +`getPresentationResult` previews what registering *would* do without presenting anything — useful for adjusting UI ahead of time, like hiding an upgrade button for users who would not see a paywall: + +```kotlin +val result = Superwall.getPresentationResult(placement = "campaign_trigger") +``` + +## Controlling the paywall + +A few members act on the presented paywall: + +```kotlin +Superwall.dismiss() // suspend; resumes once dismissed +Superwall.isPaywallPresented // Boolean +Superwall.latestPaywallInfo // PaywallInfo? +Superwall.togglePaywallSpinner(isHidden = true) +``` + +## Preloading + +Paywalls preload by default. To take over the timing, disable it and preload yourself: + +```kotlin +Superwall.configure( + apiKey = "pk_your_api_key", + options = SuperwallOptions(paywalls = PaywallOptions(shouldPreload = false)), +) + +// Later +Superwall.preloadAllPaywalls() +Superwall.preloadPaywalls(placementNames = setOf("campaign_trigger")) +``` + +Next, [manage your users](/kmp/quickstart/user-management). diff --git a/content/docs/kmp/quickstart/tracking-subscription-state.mdx b/content/docs/kmp/quickstart/tracking-subscription-state.mdx new file mode 100644 index 00000000..e400b072 --- /dev/null +++ b/content/docs/kmp/quickstart/tracking-subscription-state.mdx @@ -0,0 +1,156 @@ +--- +title: "Tracking Subscription State" +description: "Observe whether a user is on a paid plan from shared Kotlin code." +--- + + + +**Beta** + +The KMP SDK is in beta and its API may change between releases. + + + +Superwall tracks subscription state for you. But there are times you need to know directly whether a user is on a paid plan — to show different UI, or to unlock something without a placement. + +## Read it synchronously + +```kotlin +import com.superwall.sdk.kmp.models.entitlements.SubscriptionStatus + +when (val status = Superwall.subscriptionStatus) { + is SubscriptionStatus.Active -> showPro(status.entitlements) + is SubscriptionStatus.Inactive -> showFree() + is SubscriptionStatus.Unknown -> showLoading() +} +``` + +`SubscriptionStatus` has three states: + +| State | Meaning | +| --- | --- | +| `Unknown` | Not yet determined — typically before configuration completes | +| `Active(Set)` | The user has one or more active entitlements | +| `Inactive` | The user has no active entitlements | + +There is also a convenience boolean: + +```kotlin +if (Superwall.subscriptionStatus.isActive) { /* ... */ } +``` + + + Treat `Unknown` as its own case, not as "not subscribed". Showing free-tier UI during `Unknown` + will flash the wrong state at paying users on cold start. + + +## Observe changes + +`subscriptionStatusFlow` is a `StateFlow`, so it always has a current value and emits on change: + +```kotlin +import kotlinx.coroutines.launch + +scope.launch { + Superwall.subscriptionStatusFlow.collect { status -> + when (status) { + is SubscriptionStatus.Active -> showPro(status.entitlements) + is SubscriptionStatus.Inactive -> showFree() + is SubscriptionStatus.Unknown -> showLoading() + } + } +} +``` + +
+ +**Two naming details worth catching, if you are coming from the Android SDK.** + +The flow is `Superwall.subscriptionStatusFlow`. The plain `Superwall.subscriptionStatus` is a synchronous property, not a flow — on the Android SDK, `subscriptionStatus` *is* the flow. + +And this flow is **guard-exempt**: you can collect it before `configure`, where it is seeded with `SubscriptionStatus.Unknown` and attached to the native source once configuration completes. You do not have to sequence collection behind configuration. + +
+ +Emissions are delivered on the **main thread**, so updating UI from the collector is safe. + +### With Compose Multiplatform + +```kotlin +@Composable +fun ContentScreen() { + val status by Superwall.subscriptionStatusFlow.collectAsState() + + when (val current = status) { + is SubscriptionStatus.Active -> PremiumContent(current.entitlements) + is SubscriptionStatus.Inactive -> FreeContent() + is SubscriptionStatus.Unknown -> LoadingIndicator() + } +} +``` + +## Setting it yourself + +If you configured with a [`PurchaseController`](/kmp/guides/advanced-configuration), you own subscription state and must set it: + +```kotlin +Superwall.subscriptionStatus = SubscriptionStatus.Active(entitlements) +``` + + + Only set this when you have a `PurchaseController`. Without one, Superwall manages the value and + writing to it will fight the SDK. + + +## Detailed purchase history + +`CustomerInfo` carries more than `SubscriptionStatus` does — full transaction history, merging device and web purchases: + +```kotlin +val info = Superwall.getCustomerInfo() + +info.subscriptions // List +info.nonSubscriptions // List +info.entitlements // List +info.userId // String +``` + +Each `SubscriptionTransaction` includes `productId`, `purchaseDate`, `expirationDate`, `willRenew`, `isActive`, `isInGracePeriod`, and more. + +Observe changes with `customerInfoFlow`: + +```kotlin +scope.launch { + Superwall.customerInfoFlow.collect { info -> + render(info) + } +} +``` + +
+ +Customer info works on **both** platforms. If you are reading the SDK's own KDoc, note that the +`@platform iOS` annotations on `customerInfoFlow` and `getCustomerInfo` are out of date — they +describe a limitation that no longer applies. On Android the flow is fed by the native +`customerInfoDidChange` delegate hook, and `getCustomerInfo()` calls straight through to +`superwall-android` 2.8.0. + +
+ + + `customerInfoFlow` has no replay — a new collector gets nothing until the next change. Use + `getCustomerInfo()` for the current value. + + +## Restoring purchases + +```kotlin +import com.superwall.sdk.kmp.models.results.RestorationResult + +when (val result = Superwall.restorePurchases()) { + is RestorationResult.Restored -> println("Restored") + is RestorationResult.Failed -> println("Restore failed: ${result.error}") +} +``` + +Restoration failure stays in the return type — it does not throw. And `Restored` means the restore completed without errors, not that the user necessarily has an active subscription. diff --git a/content/docs/kmp/quickstart/user-management.mdx b/content/docs/kmp/quickstart/user-management.mdx new file mode 100644 index 00000000..0d59fb9a --- /dev/null +++ b/content/docs/kmp/quickstart/user-management.mdx @@ -0,0 +1,145 @@ +--- +title: "User Management" +description: "Identify users and set attributes from shared Kotlin code." +--- + + + +**Beta** + +The KMP SDK is in beta and its API may change between releases. + + + +It is necessary to uniquely identify users to track their journey within Superwall. + +## Anonymous users + +Superwall automatically generates a random user ID that persists until the user deletes or reinstalls your app. You do not have to do anything to get one. + +```kotlin +Superwall.userId // the generated alias, or your ID once identified +Superwall.isLoggedIn // false until identify() is called +``` + +## Identified users + +If you have your own user management system, call `identify` as soon as you have an ID — right after log in or sign up. This aliases your ID with the anonymous Superwall ID, which is what lets us load that user's assigned paywalls. + +```kotlin +// After retrieving a user's ID, e.g. from logging in or creating an account +Superwall.identify(userId = user.id) + +// When the user signs out +Superwall.reset() +``` + +`reset()` returns the user to a fresh random ID and clears on-device paywall assignments and stored data. + +### Waiting for assignments + +If your users switch accounts often, or delete and reinstall frequently, you can make the SDK hold paywalls back until assignments have been restored from the server: + +```kotlin +import com.superwall.sdk.kmp.models.identity.IdentityOptions + +Superwall.identify( + userId = user.id, + options = IdentityOptions(restorePaywallAssignments = true), +) +``` + + + This is an advanced option and defaults to `false`. Turning it on delays paywall presentation until + assignments arrive, so only reach for it when logging a user into an *existing* account. + + +## User attributes + +Attributes are usable in audience filters and can be templated onto paywalls. + +```kotlin +Superwall.setUserAttributes( + mapOf( + "firstName" to "Jack", + "plan" to "trial", + "workoutCount" to 12L, + ), +) +``` + +Values may be `String`, `Boolean`, `Long`, `Double`, `List`, `Map`, or `Set`. Anything else is stringified. + +
+ +**`setUserAttributes` merges — it does not replace.** Keys you pass are merged into the existing attributes, a `null` value **removes** that key, and keys you leave out are untouched. + +That asymmetry is deliberate, and it is why this is a method rather than a settable property: reading `Superwall.userAttributes` after setting will not give you back only what you set. + +
+ +```kotlin +// Remove a single attribute +Superwall.setUserAttributes(mapOf("plan" to null)) + +// Read the current snapshot +val attributes = Superwall.userAttributes +``` + +## Third-party integration attributes + +To line Superwall up with your analytics and attribution providers, set integration attributes: + +```kotlin +import com.superwall.sdk.kmp.models.events.IntegrationAttribute + +Superwall.setIntegrationAttribute(IntegrationAttribute.AMPLITUDE_DEVICE_ID, "device-123") + +Superwall.setIntegrationAttributes( + mapOf( + IntegrationAttribute.AMPLITUDE_USER_ID to "user-abc", + IntegrationAttribute.MIXPANEL_DISTINCT_ID to "distinct-xyz", + ), +) + +// Passing null removes an attribute +Superwall.setIntegrationAttribute(IntegrationAttribute.AMPLITUDE_USER_ID, null) +``` + +Read them back with `Superwall.integrationAttributes`. + +## Device attributes + +The device attributes Superwall tracks are also available for audience filters: + +```kotlin +val deviceAttributes = Superwall.getDeviceAttributes() +``` + +## Google Play account identifiers + +
+ +By default the SDK SHA-256 hashes your `userId` before forwarding it to Google Play. If you need the raw `appUserId` to appear in Play Console and downstream server events, set `passIdentifiersToPlayStore = true` when configuring: + +```kotlin +Superwall.configure( + apiKey = "pk_your_api_key", + options = SuperwallOptions(passIdentifiersToPlayStore = true), +) +``` + +This option is **Android only** and is ignored on iOS. Make sure the value complies with [Google's policies](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.Builder#setObfuscatedAccountId) — it must not contain personally identifiable information. + +
+ +## Setting the locale + +Override the locale used to evaluate audience filters, or pass `null` to follow the device: + +```kotlin +Superwall.localeIdentifier = "en_GB" +Superwall.localeIdentifier = null // back to the device locale +``` + +Next, [gate your features](/kmp/quickstart/feature-gating). diff --git a/content/docs/meta.json b/content/docs/meta.json index 26920f61..4249bc7f 100644 --- a/content/docs/meta.json +++ b/content/docs/meta.json @@ -17,6 +17,7 @@ "android", "expo", "flutter", + "kmp", "unity", "react-native", "community" From 4695d7ad5a62b0f925809c6aa481f7ccb5990405 Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Tue, 11 Aug 2026 16:12:20 -0500 Subject: [PATCH 2/9] docs(kmp): correct platform and threading claims after source audit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A clean-context claim audit against the KMP and superwall-android sources turned up four wrong or incomplete claims, all verified independently before changing anything: - transactionBackgroundView was listed iOS-only. superwall-android has it (PaywallOptions.kt:109,138) and the KMP mapper wires it (OptionsMapper.kt:87-91) — the docs had copied a stale KDoc marker. - shouldShowWebRestorationAlert and shouldShowWebPurchaseConfirmationAlert are genuinely iOS-only and were missing from the "complete list". Neither carries an "iOS only" KDoc marker, which is why they were missed. - handleLog and handleSuperwallEvent were stated as unconditionally background on Android. Logger.log calls handleLog inline before the shouldPrint check, and track() adds no dispatcher hop, so both run on the caller's thread — main included. Now documented as not guaranteed. - subscriptionStatusFlow was said to emit on main. It is a bare MutableStateFlow; a StateFlow delivers on the collector's context. Also documents the manifest-merger conflict that hits apps migrating from the standalone Android SDK, which declares the same activity with a different theme. Co-Authored-By: Claude Opus 5 --- .claude/launch.json | 6 +++++ .../docs/kmp/guides/3rd-party-analytics.mdx | 6 ++++- .../docs/kmp/guides/platform-differences.mdx | 26 +++++++++++++++---- .../kmp/guides/using-superwall-delegate.mdx | 7 +++-- content/docs/kmp/quickstart/install.mdx | 4 ++- .../tracking-subscription-state.mdx | 8 +++++- 6 files changed, 45 insertions(+), 12 deletions(-) diff --git a/.claude/launch.json b/.claude/launch.json index f5383e5e..918d8e56 100644 --- a/.claude/launch.json +++ b/.claude/launch.json @@ -6,6 +6,12 @@ "runtimeExecutable": "bun", "runtimeArgs": ["run", "dev"], "port": 3000 + }, + { + "name": "docs-3100", + "runtimeExecutable": "bun", + "runtimeArgs": ["run", "dev:port", "3100"], + "port": 3100 } ] } diff --git a/content/docs/kmp/guides/3rd-party-analytics.mdx b/content/docs/kmp/guides/3rd-party-analytics.mdx index 2d194510..7fcb85a2 100644 --- a/content/docs/kmp/guides/3rd-party-analytics.mdx +++ b/content/docs/kmp/guides/3rd-party-analytics.mdx @@ -35,7 +35,9 @@ Superwall.delegate = AnalyticsDelegate()
-`handleSuperwallEvent` arrives on a **background thread on Android** and on the main thread on iOS. That is ideal for forwarding to an analytics SDK — but do not touch UI from it without hopping to main yourself. See [Platform differences](/kmp/guides/platform-differences#delegate-threading). +On Android, `handleSuperwallEvent` has **no guaranteed thread** — it adds no dispatcher hop, so it runs wherever the SDK tracked the event from. Usually that is a background thread. On iOS it is always main. + +Two consequences: do not touch UI from it without hopping to main yourself, and do not assume it is off the main thread either — keep the body cheap and non-blocking. See [Platform differences](/kmp/guides/platform-differences#delegate-threading).
@@ -44,6 +46,8 @@ Superwall.delegate = AnalyticsDelegate() `SuperwallEventInfo` is a flat envelope. `eventType` identifies the event, and only the fields relevant to that event are non-null: ```kotlin +import com.superwall.sdk.kmp.models.events.EventType + override fun handleSuperwallEvent(eventInfo: SuperwallEventInfo) { when (eventInfo.eventType) { EventType.PAYWALL_OPEN -> { diff --git a/content/docs/kmp/guides/platform-differences.mdx b/content/docs/kmp/guides/platform-differences.mdx index 0fa5f1ae..b12d4e37 100644 --- a/content/docs/kmp/guides/platform-differences.mdx +++ b/content/docs/kmp/guides/platform-differences.mdx @@ -44,7 +44,14 @@ Setting one of these on the other platform is harmless — it is simply ignored. | --- | --- | | `SuperwallOptions.shouldBypassAppTransactionCheck` | Skips the app transaction check on launch | | `SuperwallOptions.maxConfigRetryCount` | Retry attempts for fetching configuration (default `6`) | -| `PaywallOptions.transactionBackgroundView` | The view behind Apple's payment sheet | +| `PaywallOptions.shouldShowWebRestorationAlert` | Offers web restoration after a failed restore | +| `PaywallOptions.shouldShowWebPurchaseConfirmationAlert` | Confirms a successful web checkout purchase | + + + `PaywallOptions.transactionBackgroundView` works on **both** platforms, despite its KDoc saying + "iOS only". `superwall-android` has the same option, and the KMP mapper wires it — `SPINNER` maps + to the native spinner and `NONE` maps to the native `null` ("show nothing"). + ## Delegate threading @@ -55,9 +62,16 @@ This is the difference most likely to bite you, because it is a runtime behavior | Hooks | Android | iOS | | --- | --- | --- | | `willPresentPaywall`, `didPresentPaywall`, `willDismissPaywall`, `didDismissPaywall`, `handleCustomPaywallAction`, `paywallWillOpenURL`, `paywallWillOpenDeepLink` | Main | Main | -| `handleSuperwallEvent`, `handleLog`, `subscriptionStatusDidChange`, `customerInfoDidChange`, `userAttributesDidChange`, `willRedeemLink`, `didRedeemLink` | **Background** | Main | +| `subscriptionStatusDidChange`, `customerInfoDidChange`, `userAttributesDidChange`, `willRedeemLink`, `didRedeemLink` | Background | Main | +| `handleSuperwallEvent`, `handleLog` | **Not guaranteed** | Main | + +So the paywall lifecycle hooks are safe for UI work everywhere. The rest are not, on Android. -So the paywall lifecycle hooks are safe for UI work everywhere. The analytics-shaped hooks are not, on Android. +
+ +`handleSuperwallEvent` and `handleLog` deserve their own row because they are the least predictable. Neither adds a dispatcher hop on Android — they run on whatever thread the SDK happened to call from. `handleLog` is invoked inline wherever a log statement executes, which includes the main thread; `handleSuperwallEvent` inherits the context of the code that tracked the event. Usually that is a background thread, but do not rely on it in either direction: assume neither "safe for UI" nor "off the frame budget." + +
```kotlin override fun handleSuperwallEvent(eventInfo: SuperwallEventInfo) { @@ -76,8 +90,10 @@ scope.launch(Dispatchers.Main) { updateMyUi() } ``` - `Superwall.subscriptionStatusFlow` emits on the main thread on both platforms, so collecting it is - the easier path when you want subscription changes to drive UI. It does the hop for you. + Collecting `Superwall.subscriptionStatusFlow` is usually the easier path when you want subscription + changes to drive UI — but it is a plain `StateFlow`, so it delivers on *your* collector's context, + not on main. Collect it from a main-dispatched scope (`collectAsState`, `viewModelScope`, + `lifecycleScope`) and you are safe; collect it on `Dispatchers.IO` and you are not. Two more consequences worth designing for: delegate implementations should be **thread-safe** (the analytics hooks are not serialized against each other), and they run **synchronously on an SDK thread** — blocking in one slows the SDK, so keep them short. diff --git a/content/docs/kmp/guides/using-superwall-delegate.mdx b/content/docs/kmp/guides/using-superwall-delegate.mdx index 793de965..4d95f748 100644 --- a/content/docs/kmp/guides/using-superwall-delegate.mdx +++ b/content/docs/kmp/guides/using-superwall-delegate.mdx @@ -96,9 +96,8 @@ override fun didRedeemLink(result: RedemptionResult) {} Delegate callbacks are **not** forced onto the main thread. They arrive on whatever thread the native SDK called from, and that is not the same on both platforms. - **Paywall lifecycle hooks** arrive on the **main thread** on Android and iOS. Update UI from these directly. -- **Analytics-shaped hooks** (`handleSuperwallEvent`, `handleLog`, `subscriptionStatusDidChange`, `customerInfoDidChange`, `userAttributesDidChange`, `willRedeemLink`, `didRedeemLink`) arrive on a **background thread on Android**, and on the main thread on iOS. - -This is deliberate. `handleLog` fires for every internal log line regardless of log level — forcing that onto the main thread would cost you frames. +- **State-change hooks** (`subscriptionStatusDidChange`, `customerInfoDidChange`, `userAttributesDidChange`, `willRedeemLink`, `didRedeemLink`) arrive on a **background thread on Android**, and on the main thread on iOS. +- **`handleSuperwallEvent` and `handleLog`** are **not guaranteed** either way on Android. Neither adds a dispatcher hop, so they run on whatever thread the SDK called from — `handleLog` is invoked inline wherever a log statement executes, which includes the main thread. On iOS both are on main. @@ -117,7 +116,7 @@ override fun subscriptionStatusDidChange(from: SubscriptionStatus, to: Subscript } ``` -Or skip the delegate for that case entirely and collect [`subscriptionStatusFlow`](/kmp/quickstart/tracking-subscription-state), which already emits on main. +Or skip the delegate for that case entirely and collect [`subscriptionStatusFlow`](/kmp/quickstart/tracking-subscription-state) from a main-dispatched scope, which keeps the threading question in one place. ## Platform gap diff --git a/content/docs/kmp/quickstart/install.mdx b/content/docs/kmp/quickstart/install.mdx index 90444b40..3d3b8838 100644 --- a/content/docs/kmp/quickstart/install.mdx +++ b/content/docs/kmp/quickstart/install.mdx @@ -56,7 +56,9 @@ superwall-kmp = { module = "com.superwall.sdk:superwall-kmp", version.ref = "sup **You do not need to edit `AndroidManifest.xml`.** This is the main way KMP install differs from the [standalone Android SDK](/android/quickstart/install), whose docs ask you to declare the paywall activity and permissions by hand. -The KMP library manifest already declares `SuperwallPaywallActivity`, and `superwall-android` declares the `INTERNET`, `ACCESS_NETWORK_STATE`, and `POST_NOTIFICATIONS` permissions. Manifest merging folds all of it into your app. +The KMP library manifest already declares `SuperwallPaywallActivity`, and `superwall-android` declares the `INTERNET`, `ACCESS_NETWORK_STATE`, and `POST_NOTIFICATIONS` permissions. (`com.android.vending.BILLING` arrives from the Play Billing library.) Manifest merging folds all of it into your app. + +**Migrating from the standalone Android SDK?** Remove the `SuperwallPaywallActivity` declaration from your own manifest first. Keeping it will fail the manifest merger, because the KMP library declares the same activity with a different theme (`Theme.AppCompat.NoActionBar`). If you need your own theme, override it with `tools:replace="android:theme"` rather than declaring the activity twice. diff --git a/content/docs/kmp/quickstart/tracking-subscription-state.mdx b/content/docs/kmp/quickstart/tracking-subscription-state.mdx index e400b072..2dd1ffc6 100644 --- a/content/docs/kmp/quickstart/tracking-subscription-state.mdx +++ b/content/docs/kmp/quickstart/tracking-subscription-state.mdx @@ -72,7 +72,13 @@ And this flow is **guard-exempt**: you can collect it before `configure`, where -Emissions are delivered on the **main thread**, so updating UI from the collector is safe. +
+ +This is a plain `StateFlow`, which means it delivers on **your collector's context** — it does not force emissions onto the main thread. Collect it from a main-dispatched scope (`collectAsState`, `viewModelScope`, `lifecycleScope`) and updating UI from the collector is safe. Collect it on `Dispatchers.IO` and it is not. + +The SDK's own KDoc says emissions arrive on the main thread; that is true of the common case, not a guarantee the flow enforces. + +
### With Compose Multiplatform From de6639c5f7b27a3a5ecfd68232210ff9e196b9be Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Tue, 11 Aug 2026 16:15:27 -0500 Subject: [PATCH 3/9] docs(kmp): replace review wrappers with Note/Warning callouts Final cleanup pass. The temporary yellow review containers are converted to the proper MDX callout components; the wrapped prose is unchanged. Co-Authored-By: Claude Opus 5 --- content/docs/kmp/guides/3rd-party-analytics.mdx | 4 ++-- content/docs/kmp/guides/handling-deep-links.mdx | 12 ++++++------ content/docs/kmp/guides/platform-differences.mdx | 12 ++++++------ content/docs/kmp/guides/using-superwall-delegate.mdx | 4 ++-- content/docs/kmp/quickstart/configure.mdx | 4 ++-- content/docs/kmp/quickstart/install.mdx | 12 ++++++------ .../kmp/quickstart/tracking-subscription-state.mdx | 12 ++++++------ content/docs/kmp/quickstart/user-management.mdx | 8 ++++---- 8 files changed, 34 insertions(+), 34 deletions(-) diff --git a/content/docs/kmp/guides/3rd-party-analytics.mdx b/content/docs/kmp/guides/3rd-party-analytics.mdx index 7fcb85a2..9903a017 100644 --- a/content/docs/kmp/guides/3rd-party-analytics.mdx +++ b/content/docs/kmp/guides/3rd-party-analytics.mdx @@ -33,13 +33,13 @@ class AnalyticsDelegate : SuperwallDelegate { Superwall.delegate = AnalyticsDelegate() ``` -
+ On Android, `handleSuperwallEvent` has **no guaranteed thread** — it adds no dispatcher hop, so it runs wherever the SDK tracked the event from. Usually that is a background thread. On iOS it is always main. Two consequences: do not touch UI from it without hopping to main yourself, and do not assume it is off the main thread either — keep the body cheap and non-blocking. See [Platform differences](/kmp/guides/platform-differences#delegate-threading). -
+ ## The event envelope diff --git a/content/docs/kmp/guides/handling-deep-links.mdx b/content/docs/kmp/guides/handling-deep-links.mdx index f3a877b4..91f1aa75 100644 --- a/content/docs/kmp/guides/handling-deep-links.mdx +++ b/content/docs/kmp/guides/handling-deep-links.mdx @@ -28,13 +28,13 @@ fun onDeepLink(url: String) { } ``` -
+ `handleDeepLink` is **guard-exempt** — you can call it before `Superwall.configure` without hitting `SuperwallError.NotConfigured`. That is deliberate: cold-starting from a deep link is its primary use, and it would be useless if you had to sequence it behind configuration. It takes a `String`, not a platform URL type, so it is callable from `commonMain`. -
+ ## Wiring it up per platform @@ -98,11 +98,11 @@ class MyDelegate : SuperwallDelegate { Every case carries the `code` that was redeemed. -
+ `willRedeemLink` and `didRedeemLink` are analytics-shaped hooks: they arrive on a **background thread on Android**. The spinner calls above need a main-thread hop on Android — see [Platform differences](/kmp/guides/platform-differences#delegate-threading). -
+ ## Superwall app links @@ -130,8 +130,8 @@ override fun handleSuperwallDeepLink( Deep links are also how you preview a paywall on a real device from the dashboard. Point the link at your app and pass it to `handleDeepLink`. -
+ On **Android**, previews need the SDK's debug activities declared in your own manifest — the KMP library declares the paywall activity but not the debug ones. See [Platform differences](/kmp/guides/platform-differences#in-app-paywall-previews-on-android) for the snippet. This path is not yet verified end-to-end on KMP. -
+ diff --git a/content/docs/kmp/guides/platform-differences.mdx b/content/docs/kmp/guides/platform-differences.mdx index b12d4e37..b1b6e085 100644 --- a/content/docs/kmp/guides/platform-differences.mdx +++ b/content/docs/kmp/guides/platform-differences.mdx @@ -67,11 +67,11 @@ This is the difference most likely to bite you, because it is a runtime behavior So the paywall lifecycle hooks are safe for UI work everywhere. The rest are not, on Android. -
+ `handleSuperwallEvent` and `handleLog` deserve their own row because they are the least predictable. Neither adds a dispatcher hop on Android — they run on whatever thread the SDK happened to call from. `handleLog` is invoked inline wherever a log statement executes, which includes the main thread; `handleSuperwallEvent` inherits the context of the code that tracked the event. Usually that is a background thread, but do not rely on it in either direction: assume neither "safe for UI" nor "off the frame budget." -
+ ```kotlin override fun handleSuperwallEvent(eventInfo: SuperwallEventInfo) { @@ -116,7 +116,7 @@ The two platforms do not take the same amount of setup. See [Install the SDK](/k ## In-app paywall previews on Android -
+ The KMP library manifest declares `SuperwallPaywallActivity`, which is what paywall presentation needs. It does **not** declare the debug activities that the standalone Android SDK's [in-app paywall previews](/android/quickstart/in-app-paywall-previews) rely on, and neither does `superwall-android`. @@ -130,13 +130,13 @@ If you need previews on Android, declare them in your own `AndroidManifest.xml`: This path is not yet verified end-to-end on KMP. If you try it, we would like to hear how it goes — [open an issue](https://github.com/superwall/Superwall-KMP/issues). -
+ ## What is *not* a difference Some things look like platform gaps if you read the SDK's inline documentation, but are not: -
+ `Superwall.customerInfoFlow`, `Superwall.getCustomerInfo()`, `SuperwallDelegate.customerInfoDidChange`, and @@ -147,7 +147,7 @@ on. We have flagged this for the SDK team. Trust this page over the inline docs until the KDoc catches up. -
+ ## Getting the right API key diff --git a/content/docs/kmp/guides/using-superwall-delegate.mdx b/content/docs/kmp/guides/using-superwall-delegate.mdx index 4d95f748..286fdfec 100644 --- a/content/docs/kmp/guides/using-superwall-delegate.mdx +++ b/content/docs/kmp/guides/using-superwall-delegate.mdx @@ -91,7 +91,7 @@ override fun didRedeemLink(result: RedemptionResult) {} ## Threading — read this before you touch UI -
+ Delegate callbacks are **not** forced onto the main thread. They arrive on whatever thread the native SDK called from, and that is not the same on both platforms. @@ -99,7 +99,7 @@ Delegate callbacks are **not** forced onto the main thread. They arrive on whate - **State-change hooks** (`subscriptionStatusDidChange`, `customerInfoDidChange`, `userAttributesDidChange`, `willRedeemLink`, `didRedeemLink`) arrive on a **background thread on Android**, and on the main thread on iOS. - **`handleSuperwallEvent` and `handleLog`** are **not guaranteed** either way on Android. Neither adds a dispatcher hop, so they run on whatever thread the SDK called from — `handleLog` is invoked inline wherever a log statement executes, which includes the main thread. On iOS both are on main. -
+ Two things this asks of your implementation: diff --git a/content/docs/kmp/quickstart/configure.mdx b/content/docs/kmp/quickstart/configure.mdx index 642f03e8..6316f8b8 100644 --- a/content/docs/kmp/quickstart/configure.mdx +++ b/content/docs/kmp/quickstart/configure.mdx @@ -64,7 +64,7 @@ The call is fire-and-forget. `completion` reports the real outcome — an invali This is the thing to internalize before you write anything else. -
+ Calls made before `configure` are **not** buffered and replayed. Almost every member throws `SuperwallError.NotConfigured` instead. @@ -75,7 +75,7 @@ The deliberate exemptions, which are safe to touch at any time: - `delegate` — stored immediately, installed natively at configure - `isConfigured`, `isInitialized`, and `configurationStatus` -
+ Everything else — `register`, `identify`, `setUserAttributes`, `entitlements`, and the rest — needs configuration to have happened first. diff --git a/content/docs/kmp/quickstart/install.mdx b/content/docs/kmp/quickstart/install.mdx index 3d3b8838..81918520 100644 --- a/content/docs/kmp/quickstart/install.mdx +++ b/content/docs/kmp/quickstart/install.mdx @@ -52,7 +52,7 @@ superwall-kmp = { module = "com.superwall.sdk:superwall-kmp", version.ref = "sup `superwall-android` comes along transitively — do not add it yourself. -
+ **You do not need to edit `AndroidManifest.xml`.** This is the main way KMP install differs from the [standalone Android SDK](/android/quickstart/install), whose docs ask you to declare the paywall activity and permissions by hand. @@ -60,7 +60,7 @@ The KMP library manifest already declares `SuperwallPaywallActivity`, and `super **Migrating from the standalone Android SDK?** Remove the `SuperwallPaywallActivity` declaration from your own manifest first. Keeping it will fail the manifest merger, because the KMP library declares the same activity with a different theme (`Theme.AppCompat.NoActionBar`). If you need your own theme, override it with `tools:replace="android:theme"` rather than declaring the activity twice. -
+ ### No `Context`, and what to do if that breaks @@ -102,11 +102,11 @@ kotlin { } ``` -
+ `isStatic = true` is not a preference. The Kotlin framework compiles against the bridge's Objective-C headers only (compile-only cinterop) and never embeds the bridge binary, so a dynamic framework has nothing to resolve those symbols against at link time. -
+ ### 2. Add the SuperwallKMPBridge Swift package @@ -126,11 +126,11 @@ The bridge package pins SuperwallKit iOS to exactly `4.16.1` and pulls it in tra -
+ **A missing bridge is a build-time failure, not a runtime one.** Because the Kotlin side uses compile-only cinterop, forgetting this step surfaces as undefined-symbol link errors when Xcode builds your app — not as a crash on launch or a paywall that silently fails to present. If you see linker errors mentioning bridge symbols, this step is what is missing. -
+ ## Get your API key diff --git a/content/docs/kmp/quickstart/tracking-subscription-state.mdx b/content/docs/kmp/quickstart/tracking-subscription-state.mdx index 2dd1ffc6..623f16f9 100644 --- a/content/docs/kmp/quickstart/tracking-subscription-state.mdx +++ b/content/docs/kmp/quickstart/tracking-subscription-state.mdx @@ -62,7 +62,7 @@ scope.launch { } ``` -
+ **Two naming details worth catching, if you are coming from the Android SDK.** @@ -70,15 +70,15 @@ The flow is `Superwall.subscriptionStatusFlow`. The plain `Superwall.subscriptio And this flow is **guard-exempt**: you can collect it before `configure`, where it is seeded with `SubscriptionStatus.Unknown` and attached to the native source once configuration completes. You do not have to sequence collection behind configuration. -
+ -
+ This is a plain `StateFlow`, which means it delivers on **your collector's context** — it does not force emissions onto the main thread. Collect it from a main-dispatched scope (`collectAsState`, `viewModelScope`, `lifecycleScope`) and updating UI from the collector is safe. Collect it on `Dispatchers.IO` and it is not. The SDK's own KDoc says emissions arrive on the main thread; that is true of the common case, not a guarantee the flow enforces. -
+ ### With Compose Multiplatform @@ -133,7 +133,7 @@ scope.launch { } ``` -
+ Customer info works on **both** platforms. If you are reading the SDK's own KDoc, note that the `@platform iOS` annotations on `customerInfoFlow` and `getCustomerInfo` are out of date — they @@ -141,7 +141,7 @@ describe a limitation that no longer applies. On Android the flow is fed by the `customerInfoDidChange` delegate hook, and `getCustomerInfo()` calls straight through to `superwall-android` 2.8.0. -
+ `customerInfoFlow` has no replay — a new collector gets nothing until the next change. Use diff --git a/content/docs/kmp/quickstart/user-management.mdx b/content/docs/kmp/quickstart/user-management.mdx index 0d59fb9a..4a6df37a 100644 --- a/content/docs/kmp/quickstart/user-management.mdx +++ b/content/docs/kmp/quickstart/user-management.mdx @@ -70,13 +70,13 @@ Superwall.setUserAttributes( Values may be `String`, `Boolean`, `Long`, `Double`, `List`, `Map`, or `Set`. Anything else is stringified. -
+ **`setUserAttributes` merges — it does not replace.** Keys you pass are merged into the existing attributes, a `null` value **removes** that key, and keys you leave out are untouched. That asymmetry is deliberate, and it is why this is a method rather than a settable property: reading `Superwall.userAttributes` after setting will not give you back only what you set. -
+ ```kotlin // Remove a single attribute @@ -118,7 +118,7 @@ val deviceAttributes = Superwall.getDeviceAttributes() ## Google Play account identifiers -
+ By default the SDK SHA-256 hashes your `userId` before forwarding it to Google Play. If you need the raw `appUserId` to appear in Play Console and downstream server events, set `passIdentifiersToPlayStore = true` when configuring: @@ -131,7 +131,7 @@ Superwall.configure( This option is **Android only** and is ignored on iOS. Make sure the value complies with [Google's policies](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.Builder#setObfuscatedAccountId) — it must not contain personally identifiable information. -
+
## Setting the locale From c24a9bcc923d19d9edcf3982888a71ef0c86583e Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Wed, 12 Aug 2026 13:41:24 -0500 Subject: [PATCH 4/9] docs(kmp): add SPM screenshot for the bridge install step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the Xcode "Add Package Dependencies" screenshot to the iOS half of the install page — the only purely visual step in the section, and the one most likely to be done wrong. Lives under content/docs/images/kmp/ rather than a per-section images folder, since copy-docs-images.cjs only mirrors content/docs/images/** into public/. The screenshot shows Xcode's default Dependency Rule (Up to Next Major), so a note under it explains why to pin Exact Version while the SDK is in beta: the bridge binary and the Kotlin klib ship from one tag, and SPM drifting ahead of the version the shared module was built against is what breaks the link step. Co-Authored-By: Claude Opus 5 --- .../docs/images/kmp/spm-add-bridge-product.jpg | Bin 0 -> 217389 bytes content/docs/kmp/quickstart/install.mdx | 9 +++++++++ 2 files changed, 9 insertions(+) create mode 100644 content/docs/images/kmp/spm-add-bridge-product.jpg diff --git a/content/docs/images/kmp/spm-add-bridge-product.jpg b/content/docs/images/kmp/spm-add-bridge-product.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b2eb187b75ef6279c4cbbc9621a987a08b472eff GIT binary patch literal 217389 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�r$x&C?%b->=yi2DfTotORsmvBXJ$J@$x_ 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�{+jI7@B7mk=4so2b2DK}uL1 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 literal 0 HcmV?d00001 diff --git a/content/docs/kmp/quickstart/install.mdx b/content/docs/kmp/quickstart/install.mdx index 81918520..b9ae6c1c 100644 --- a/content/docs/kmp/quickstart/install.mdx +++ b/content/docs/kmp/quickstart/install.mdx @@ -118,6 +118,15 @@ https://github.com/superwall/Superwall-KMP Add the **`SuperwallKMPBridge`** product to your app target. +![Xcode's Add Package Dependencies sheet with the Superwall-KMP repository URL entered and the superwall-kmp package selected](/images/kmp/spm-add-bridge-product.jpg) + + + Xcode defaults the Dependency Rule to **Up to Next Major Version**, as shown. While the SDK is in + beta, pin **Exact Version** instead — the bridge binary and the Kotlin klib ship from the same tag + and are one release unit, so letting SPM drift ahead of the version your shared module was built + against is what breaks the link step. + + **Do not add SuperwallKit separately.** From 318669dd522bd07b9be1d1b901035210afb6bb57 Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Thu, 13 Aug 2026 11:54:07 -0500 Subject: [PATCH 5/9] Copy edits --- content/docs/kmp/index.mdx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/content/docs/kmp/index.mdx b/content/docs/kmp/index.mdx index 415e6d12..04e8aa5c 100644 --- a/content/docs/kmp/index.mdx +++ b/content/docs/kmp/index.mdx @@ -13,7 +13,7 @@ The KMP SDK is in beta. The API may change between releases, and these docs desc The Superwall KMP SDK brings paywalls, placements, and entitlements to Kotlin Multiplatform. It wraps the native Superwall SDKs — `superwall-android` on Android, SuperwallKit on iOS — behind a single API that lives entirely in `commonMain`. -The practical consequence: no `expect`/`actual` of your own, no platform types in your shared code, and an identical `configure` signature on both platforms. There is no `Context` parameter on Android. +This means there's no `expect`/`actual` of your own, no platform types in your shared code, and an identical `configure` signature on both platforms. There is no `Context` parameter on Android. ```kotlin import com.superwall.sdk.kmp.Superwall @@ -32,7 +32,7 @@ Superwall.register(placement = "campaign_trigger") { | Android | `minSdk 26` | `com.superwall.sdk:superwall-android` 2.8.0 | | iOS | iOS 14+ (`iosArm64`, `iosSimulatorArm64`, `iosX64`) | SuperwallKit iOS 4.16.1, pinned exactly | -Those are the only two targets. There are no JVM, JS, desktop, or watchOS artifacts — the SDK is a wrapper over two native SDKs, so it goes where they go. +Those are the only two targets. There are no JVM, JS, desktop, or watchOS artifacts since the SDK is a wrapper over two native SDKs. Android's `minSdk` here is **26**, higher than the standalone Android SDK's 23. If you are adding @@ -44,9 +44,7 @@ Those are the only two targets. There are no JVM, JS, desktop, or watchOS artifa Your shared Kotlin code calls one API. Underneath, each platform resolves to its own native SDK: - **Android** wraps `superwall-android` directly. One Gradle dependency pulls it in, and an `androidx.startup` initializer captures the `Application` for you. -- **iOS** forwards through **SuperwallKMPBridge**, an `@objc` Swift facade over SuperwallKit that flattens Swift-only constructs (enum associated values, structs, `async`) into something Kotlin can consume via cinterop. Your app supplies that bridge as a Swift package. - -That second point is the one that catches people, and it is covered in [Install the SDK](/kmp/quickstart/install). +- **iOS** forwards through **SuperwallKMPBridge**, an `@objc` Swift bridging layer over SuperwallKit that flattens Swift-only constructs (enum associated values, structs, `async`) into something Kotlin can consume via cinterop. Your app supplies that bridge as a Swift package. ## Quick Links From 6d4effb9878190bcc7344c83c2a1eec2312f78e6 Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Thu, 13 Aug 2026 11:58:50 -0500 Subject: [PATCH 6/9] Good bye em dashes --- .../docs/kmp/guides/3rd-party-analytics.mdx | 12 ++++----- .../kmp/guides/advanced-configuration.mdx | 10 +++---- .../docs/kmp/guides/handling-deep-links.mdx | 14 +++++----- .../docs/kmp/guides/platform-differences.mdx | 26 +++++++++---------- .../kmp/guides/using-superwall-delegate.mdx | 10 +++---- content/docs/kmp/index.mdx | 2 +- content/docs/kmp/quickstart/configure.mdx | 18 ++++++------- .../docs/kmp/quickstart/feature-gating.mdx | 14 +++++----- content/docs/kmp/quickstart/install.mdx | 16 ++++++------ .../kmp/quickstart/present-first-paywall.mdx | 8 +++--- .../tracking-subscription-state.mdx | 18 ++++++------- .../docs/kmp/quickstart/user-management.mdx | 6 ++--- 12 files changed, 77 insertions(+), 77 deletions(-) diff --git a/content/docs/kmp/guides/3rd-party-analytics.mdx b/content/docs/kmp/guides/3rd-party-analytics.mdx index 9903a017..1a571073 100644 --- a/content/docs/kmp/guides/3rd-party-analytics.mdx +++ b/content/docs/kmp/guides/3rd-party-analytics.mdx @@ -11,7 +11,7 @@ The KMP SDK is in beta and its API may change between releases. -Superwall tracks events internally — paywalls opening, transactions completing, placements firing. You can forward all of them to your own analytics provider through `SuperwallDelegate`. +Superwall tracks events internally: paywalls opening, transactions completing, placements firing. You can forward all of them to your own analytics provider through `SuperwallDelegate`. ## Forwarding events @@ -35,9 +35,9 @@ Superwall.delegate = AnalyticsDelegate() -On Android, `handleSuperwallEvent` has **no guaranteed thread** — it adds no dispatcher hop, so it runs wherever the SDK tracked the event from. Usually that is a background thread. On iOS it is always main. +On Android, `handleSuperwallEvent` has **no guaranteed thread**. It adds no dispatcher hop, so it runs wherever the SDK tracked the event from. Usually that is a background thread. On iOS it is always main. -Two consequences: do not touch UI from it without hopping to main yourself, and do not assume it is off the main thread either — keep the body cheap and non-blocking. See [Platform differences](/kmp/guides/platform-differences#delegate-threading). +Two consequences: do not touch UI from it without hopping to main yourself, and do not assume it is off the main thread either. Keep the body cheap and non-blocking. See [Platform differences](/kmp/guides/platform-differences#delegate-threading). @@ -104,7 +104,7 @@ Commonly useful fields on the envelope: ## Sending your identifiers to Superwall -The reverse direction matters too — Superwall can attribute better if it knows your analytics identifiers: +The reverse direction matters too, since Superwall can attribute better if it knows your analytics identifiers: ```kotlin import com.superwall.sdk.kmp.models.events.IntegrationAttribute @@ -121,7 +121,7 @@ Superwall.setIntegrationAttributes( Supported providers include Adjust, Amplitude, AppsFlyer, Braze, OneSignal, Meta, Firebase, Singular, Iterable, Mixpanel, mParticle, CleverTap, Airship, Kochava, Tenjin, PostHog, Customer.io, and Appstack. Passing `null` for a value removes it. - `IntegrationAttribute.FIREBASE_INSTALLATION_ID` is **iOS only** — setting it on Android is skipped + `IntegrationAttribute.FIREBASE_INSTALLATION_ID` is **iOS only**. Setting it on Android is skipped and logs a warning. Every other attribute works on both platforms. @@ -144,7 +144,7 @@ override fun handleLog( ``` - `handleLog` fires for **every** internal log line, regardless of the configured log level — that is + `handleLog` fires for **every** internal log line, regardless of the configured log level, which is hundreds of calls for a single `register`. Filter early, keep the body cheap, and never block in it. diff --git a/content/docs/kmp/guides/advanced-configuration.mdx b/content/docs/kmp/guides/advanced-configuration.mdx index dd47b542..e7aca9e4 100644 --- a/content/docs/kmp/guides/advanced-configuration.mdx +++ b/content/docs/kmp/guides/advanced-configuration.mdx @@ -11,7 +11,7 @@ The KMP SDK is in beta and its API may change between releases. -By default Superwall handles purchases and subscription status for you, and most apps should leave it that way. If you already have purchase logic — your own billing stack, or a provider like RevenueCat — you can take it over with a `PurchaseController`. +By default Superwall handles purchases and subscription status for you, and most apps should leave it that way. If you already have purchase logic (your own billing stack, or a provider like RevenueCat), you can take it over with a `PurchaseController`. Passing a `PurchaseController` means **you** own subscription status. Superwall will not set it for @@ -61,7 +61,7 @@ All three are `suspend` functions, so you can do the real asynchronous work inli ## Handling every case -`PurchaseResult` is a sealed interface — handle all four: +`PurchaseResult` is a sealed interface, so handle all four: | Result | When | | --- | --- | @@ -90,7 +90,7 @@ There are convenience factories if you prefer them: `PurchaseResult.purchased()` `RestorationResult` has two cases, `Restored` and `Failed(error)`. - `RestorationResult.Restored` means the restore completed **without errors** — not that the user has + `RestorationResult.Restored` means the restore completed **without errors**, not that the user has an active subscription. Set subscription status from the entitlements you actually resolved, not from the fact that restore succeeded. @@ -107,7 +107,7 @@ Superwall.configure( ``` - A second `configure` call will **not** install a different purchase controller — repeat calls are + A second `configure` call will **not** install a different purchase controller, because repeat calls are a no-op. Set it on the first call. @@ -158,7 +158,7 @@ when (val result = Superwall.restorePurchases()) { } ``` -Failure stays in the return type — it does not throw. +Failure stays in the return type and does not throw. ## Observing purchases you did not make diff --git a/content/docs/kmp/guides/handling-deep-links.mdx b/content/docs/kmp/guides/handling-deep-links.mdx index 91f1aa75..2f9443c1 100644 --- a/content/docs/kmp/guides/handling-deep-links.mdx +++ b/content/docs/kmp/guides/handling-deep-links.mdx @@ -30,7 +30,7 @@ fun onDeepLink(url: String) { -`handleDeepLink` is **guard-exempt** — you can call it before `Superwall.configure` without hitting `SuperwallError.NotConfigured`. That is deliberate: cold-starting from a deep link is its primary use, and it would be useless if you had to sequence it behind configuration. +`handleDeepLink` is **guard-exempt**, so you can call it before `Superwall.configure` without hitting `SuperwallError.NotConfigured`. That is deliberate: cold-starting from a deep link is its primary use, and it would be useless if you had to sequence it behind configuration. It takes a `String`, not a platform URL type, so it is callable from `commonMain`. @@ -40,7 +40,7 @@ It takes a `String`, not a platform URL type, so it is callable from `commonMain The SDK takes a plain `String`, so the only platform-specific part is getting the URL from the OS to your shared code. -**Android** — from the activity that receives the intent: +**Android**, from the activity that receives the intent: ```kotlin // androidMain @@ -57,7 +57,7 @@ override fun onNewIntent(intent: Intent) { Declare your intent filter in `AndroidManifest.xml` as you would for any deep link. -**iOS** — from your `App` or `AppDelegate`: +**iOS**, from your `App` or `AppDelegate`: ```swift // SwiftUI @@ -67,7 +67,7 @@ Declare your intent filter in `AndroidManifest.xml` as you would for any deep li ``` - Register your URL scheme with the OS as usual — an `intent-filter` on Android, a URL type in your + Register your URL scheme with the OS as usual: an `intent-filter` on Android, a URL type in your Xcode target on iOS. Superwall does not do that part for you. @@ -100,7 +100,7 @@ Every case carries the `code` that was redeemed. -`willRedeemLink` and `didRedeemLink` are analytics-shaped hooks: they arrive on a **background thread on Android**. The spinner calls above need a main-thread hop on Android — see [Platform differences](/kmp/guides/platform-differences#delegate-threading). +`willRedeemLink` and `didRedeemLink` are analytics hooks: they arrive on a **background thread on Android**. The spinner calls above need a main-thread hop on Android. See [Platform differences](/kmp/guides/platform-differences#delegate-threading). @@ -122,7 +122,7 @@ override fun handleSuperwallDeepLink( **This hook is iOS only.** `superwall-android` has no equivalent delegate method, so it is never invoked on Android. -`Superwall.handleDeepLink(url)` itself works on **both** platforms — it is only this structured callback that is missing. On Android, parse the URL yourself in the activity that receives it. +`Superwall.handleDeepLink(url)` itself works on **both** platforms. Only this structured callback is missing. On Android, parse the URL yourself in the activity that receives it. @@ -132,6 +132,6 @@ Deep links are also how you preview a paywall on a real device from the dashboar -On **Android**, previews need the SDK's debug activities declared in your own manifest — the KMP library declares the paywall activity but not the debug ones. See [Platform differences](/kmp/guides/platform-differences#in-app-paywall-previews-on-android) for the snippet. This path is not yet verified end-to-end on KMP. +On **Android**, previews need the SDK's debug activities declared in your own manifest. The KMP library declares the paywall activity but not the debug ones. See [Platform differences](/kmp/guides/platform-differences#in-app-paywall-previews-on-android) for the snippet. This path is not yet verified end-to-end on KMP. diff --git a/content/docs/kmp/guides/platform-differences.mdx b/content/docs/kmp/guides/platform-differences.mdx index b1b6e085..41c1f0f9 100644 --- a/content/docs/kmp/guides/platform-differences.mdx +++ b/content/docs/kmp/guides/platform-differences.mdx @@ -11,7 +11,7 @@ The KMP SDK is in beta and its API may change between releases. -The KMP SDK's public API is identical on both platforms — one signature, no platform types, no `expect`/`actual` of your own. But it wraps two different native SDKs, and in a handful of places they do not offer the same thing. +The KMP SDK's public API is identical on both platforms: one signature, no platform types, no `expect`/`actual` of your own. But it wraps two different native SDKs, and in a handful of places they do not offer the same thing. This page is the complete list. Everything not mentioned here behaves the same on Android and iOS. @@ -23,11 +23,11 @@ This page is the complete list. Everything not mentioned here behaves the same o | `Superwall.consume(purchaseToken)` | **Android.** Consumes a Play Billing purchase so it can be bought again. On iOS it echoes the token back unchanged. | | `IntegrationAttribute.FIREBASE_INSTALLATION_ID` | **iOS only.** `superwall-android` has no counterpart; setting it on Android is skipped and logs a warning. Every other `IntegrationAttribute` works on both. | -That is the whole list of behavioral gaps. Notably, customer info is **not** on it — see [below](#what-is-not-a-difference). +That is the whole list of behavioral gaps. Notably, customer info is **not** on it. See [below](#what-is-not-a-difference). ## Options that only apply to one platform -Setting one of these on the other platform is harmless — it is simply ignored. +Setting one of these on the other platform is harmless. It is ignored. **Android only** @@ -49,13 +49,13 @@ Setting one of these on the other platform is harmless — it is simply ignored. `PaywallOptions.transactionBackgroundView` works on **both** platforms, despite its KDoc saying - "iOS only". `superwall-android` has the same option, and the KMP mapper wires it — `SPINNER` maps + "iOS only". `superwall-android` has the same option, and the KMP mapper wires it. `SPINNER` maps to the native spinner and `NONE` maps to the native `null` ("show nothing"). ## Delegate threading -This is the difference most likely to bite you, because it is a runtime behavior rather than a missing method. +This is the difference most likely to cause problems, because it is a runtime behavior rather than a missing method. `SuperwallDelegate` callbacks are **not** forced onto the main thread. They arrive on whatever thread the native SDK called from, which splits cleanly: @@ -69,16 +69,16 @@ So the paywall lifecycle hooks are safe for UI work everywhere. The rest are not -`handleSuperwallEvent` and `handleLog` deserve their own row because they are the least predictable. Neither adds a dispatcher hop on Android — they run on whatever thread the SDK happened to call from. `handleLog` is invoked inline wherever a log statement executes, which includes the main thread; `handleSuperwallEvent` inherits the context of the code that tracked the event. Usually that is a background thread, but do not rely on it in either direction: assume neither "safe for UI" nor "off the frame budget." +`handleSuperwallEvent` and `handleLog` have their own row because they are the least predictable. Neither adds a dispatcher hop on Android, so they run on whatever thread the SDK called from. `handleLog` is invoked inline wherever a log statement executes, which includes the main thread. `handleSuperwallEvent` inherits the context of the code that tracked the event. Usually that is a background thread, but do not rely on it in either direction: do not assume it is safe for UI, and do not assume it is off the main thread. ```kotlin override fun handleSuperwallEvent(eventInfo: SuperwallEventInfo) { - // Fine — forwarding to an analytics SDK. + // Fine: forwarding to an analytics SDK. analytics.track(eventInfo.eventType.name) - // NOT fine on Android — this is a background thread. + // NOT fine on Android: this is a background thread. // updateMyUi() } ``` @@ -91,12 +91,12 @@ scope.launch(Dispatchers.Main) { updateMyUi() } Collecting `Superwall.subscriptionStatusFlow` is usually the easier path when you want subscription - changes to drive UI — but it is a plain `StateFlow`, so it delivers on *your* collector's context, + changes to drive UI, but it is a plain `StateFlow`, so it delivers on *your* collector's context, not on main. Collect it from a main-dispatched scope (`collectAsState`, `viewModelScope`, `lifecycleScope`) and you are safe; collect it on `Dispatchers.IO` and you are not. -Two more consequences worth designing for: delegate implementations should be **thread-safe** (the analytics hooks are not serialized against each other), and they run **synchronously on an SDK thread** — blocking in one slows the SDK, so keep them short. +Two more things to plan for: delegate implementations should be **thread-safe** (the analytics hooks are not serialized against each other), and they run **synchronously on an SDK thread**, so blocking in one slows the SDK. Keep them short. `PaywallPresentationHandler` closures and the `register` `feature` closure are a different story: @@ -110,7 +110,7 @@ The two platforms do not take the same amount of setup. See [Install the SDK](/k | | Android | iOS | | --- | --- | --- | | Steps | One Gradle dependency | Gradle dependency **plus** the `SuperwallKMPBridge` Swift package | -| Manifest / project edits | None — the library manifest declares the paywall activity and the startup initializer | Kotlin framework must be exported with `isStatic = true` | +| Manifest / project edits | None. The library manifest declares the paywall activity and the startup initializer | Kotlin framework must be exported with `isStatic = true` | | Native SDK | `superwall-android` 2.8.0, transitively | SuperwallKit 4.16.1, pinned exactly by the bridge | | Minimum | `minSdk` 26 | iOS 14 | @@ -128,7 +128,7 @@ If you need previews on Android, declare them in your own `AndroidManifest.xml`: ``` -This path is not yet verified end-to-end on KMP. If you try it, we would like to hear how it goes — [open an issue](https://github.com/superwall/Superwall-KMP/issues). +This path is not yet verified end-to-end on KMP. If you try it, we would like to hear how it goes, so please [open an issue](https://github.com/superwall/Superwall-KMP/issues). @@ -151,4 +151,4 @@ We have flagged this for the SDK team. Trust this page over the inline docs unti ## Getting the right API key -Android and iOS have separate Public API Keys in the dashboard. The SDK does not need `expect`/`actual`, but your key does — supply the right one per platform via an `expect val`, a build-time constant, or whatever your project already uses for platform config. +Android and iOS have separate Public API Keys in the dashboard. The SDK does not need `expect`/`actual`, but your key does. Supply the right one per platform via an `expect val`, a build-time constant, or whatever your project already uses for platform config. diff --git a/content/docs/kmp/guides/using-superwall-delegate.mdx b/content/docs/kmp/guides/using-superwall-delegate.mdx index 286fdfec..37171f26 100644 --- a/content/docs/kmp/guides/using-superwall-delegate.mdx +++ b/content/docs/kmp/guides/using-superwall-delegate.mdx @@ -11,7 +11,7 @@ The KMP SDK is in beta and its API may change between releases. -`SuperwallDelegate` is how you observe what the SDK is doing — paywalls opening and closing, subscription status changing, events being tracked, links being redeemed. +`SuperwallDelegate` is how you observe what the SDK is doing: paywalls opening and closing, subscription status changing, events being tracked, links being redeemed. Every method has a default no-op implementation, so override only the ones you need. @@ -89,7 +89,7 @@ override fun willRedeemLink() {} override fun didRedeemLink(result: RedemptionResult) {} ``` -## Threading — read this before you touch UI +## Threading @@ -97,7 +97,7 @@ Delegate callbacks are **not** forced onto the main thread. They arrive on whate - **Paywall lifecycle hooks** arrive on the **main thread** on Android and iOS. Update UI from these directly. - **State-change hooks** (`subscriptionStatusDidChange`, `customerInfoDidChange`, `userAttributesDidChange`, `willRedeemLink`, `didRedeemLink`) arrive on a **background thread on Android**, and on the main thread on iOS. -- **`handleSuperwallEvent` and `handleLog`** are **not guaranteed** either way on Android. Neither adds a dispatcher hop, so they run on whatever thread the SDK called from — `handleLog` is invoked inline wherever a log statement executes, which includes the main thread. On iOS both are on main. +- **`handleSuperwallEvent` and `handleLog`** are **not guaranteed** either way on Android. Neither adds a dispatcher hop, so they run on whatever thread the SDK called from. `handleLog` is invoked inline wherever a log statement executes, which includes the main thread. On iOS both are on main. @@ -106,7 +106,7 @@ Two things this asks of your implementation: 1. **Be thread-safe.** The analytics hooks are not serialized against each other. 2. **Be quick.** They run synchronously on an SDK thread, so blocking in one slows the SDK. -If you need UI work from an analytics-shaped hook, hop yourself: +If you need UI work from an analytics hook, hop yourself: ```kotlin override fun subscriptionStatusDidChange(from: SubscriptionStatus, to: SubscriptionStatus) { @@ -120,7 +120,7 @@ Or skip the delegate for that case entirely and collect [`subscriptionStatusFlow ## Platform gap -`handleSuperwallDeepLink` is **iOS only** — `superwall-android` has no equivalent delegate hook, so it is never invoked on Android. See [Platform differences](/kmp/guides/platform-differences). +`handleSuperwallDeepLink` is **iOS only**. `superwall-android` has no equivalent delegate hook, so it is never invoked on Android. See [Platform differences](/kmp/guides/platform-differences). ```kotlin // iOS only diff --git a/content/docs/kmp/index.mdx b/content/docs/kmp/index.mdx index 04e8aa5c..70dd0edc 100644 --- a/content/docs/kmp/index.mdx +++ b/content/docs/kmp/index.mdx @@ -11,7 +11,7 @@ The KMP SDK is in beta. The API may change between releases, and these docs desc -The Superwall KMP SDK brings paywalls, placements, and entitlements to Kotlin Multiplatform. It wraps the native Superwall SDKs — `superwall-android` on Android, SuperwallKit on iOS — behind a single API that lives entirely in `commonMain`. +The Superwall KMP SDK brings paywalls, placements, and entitlements to Kotlin Multiplatform. It wraps the native Superwall SDKs (`superwall-android` on Android, SuperwallKit on iOS) behind a single API that lives entirely in `commonMain`. This means there's no `expect`/`actual` of your own, no platform types in your shared code, and an identical `configure` signature on both platforms. There is no `Context` parameter on Android. diff --git a/content/docs/kmp/quickstart/configure.mdx b/content/docs/kmp/quickstart/configure.mdx index 6316f8b8..50020df4 100644 --- a/content/docs/kmp/quickstart/configure.mdx +++ b/content/docs/kmp/quickstart/configure.mdx @@ -45,14 +45,14 @@ The signature is identical on both platforms: }, completion: { description: - "Invoked on the main thread with the configuration outcome — success, or failure with SuperwallError.ConfigurationFailed.", + "Invoked on the main thread with the configuration outcome: success, or failure with SuperwallError.ConfigurationFailed.", type: "((Result) -> Unit)?", default: "null", }, }} /> -The call is fire-and-forget. `completion` reports the real outcome — an invalid API key surfaces there, not as a thrown exception. +The call is fire-and-forget. `completion` reports the real outcome. An invalid API key surfaces there, not as a thrown exception. Calling `configure` a second time is a no-op. The repeat call logs a warning through the delegate's @@ -62,7 +62,7 @@ The call is fire-and-forget. `completion` reports the real outcome — an invali ## There is no pre-configure call queue -This is the thing to internalize before you write anything else. +This is important to understand before you write anything else. @@ -70,14 +70,14 @@ Calls made before `configure` are **not** buffered and replayed. Almost every me The deliberate exemptions, which are safe to touch at any time: -- `handleDeepLink` — deep-link cold start is its whole purpose -- `subscriptionStatusFlow` and `customerInfoFlow` — pre-seeded, common-owned flows -- `delegate` — stored immediately, installed natively at configure +- `handleDeepLink`: deep-link cold start is its whole purpose +- `subscriptionStatusFlow` and `customerInfoFlow`: pre-seeded, common-owned flows +- `delegate`: stored immediately, installed natively at configure - `isConfigured`, `isInitialized`, and `configurationStatus` -Everything else — `register`, `identify`, `setUserAttributes`, `entitlements`, and the rest — needs configuration to have happened first. +Everything else (`register`, `identify`, `setUserAttributes`, `entitlements`, and the rest) needs configuration to have happened first. ## Ordering your calls @@ -102,7 +102,7 @@ if (Superwall.isConfigured) { } ``` -`Superwall.configurationStatus` gives you the fuller picture — `PENDING`, `CONFIGURED`, or `FAILED`. +`Superwall.configurationStatus` gives you the fuller picture: `PENDING`, `CONFIGURED`, or `FAILED`. ## Options @@ -165,7 +165,7 @@ Frequently used `SuperwallOptions` fields: }} /> -Some options only apply to one platform. `passIdentifiersToPlayStore` and `useMockReviews` are Android-only; `shouldBypassAppTransactionCheck` and `maxConfigRetryCount` are iOS-only. Setting one on the other platform is harmless — it is ignored. See [Platform differences](/kmp/guides/platform-differences). +Some options only apply to one platform. `passIdentifiersToPlayStore` and `useMockReviews` are Android-only; `shouldBypassAppTransactionCheck` and `maxConfigRetryCount` are iOS-only. Setting one on the other platform is harmless. It is ignored. See [Platform differences](/kmp/guides/platform-differences). Leave `networkEnvironment` alone unless the Superwall team has explicitly told you otherwise. diff --git a/content/docs/kmp/quickstart/feature-gating.mdx b/content/docs/kmp/quickstart/feature-gating.mdx index 4ffa9279..9ab04785 100644 --- a/content/docs/kmp/quickstart/feature-gating.mdx +++ b/content/docs/kmp/quickstart/feature-gating.mdx @@ -25,9 +25,9 @@ fun pressedWorkoutButton() { } ``` -Given how cheap `register` is, we strongly recommend registering **all core functionality** — that is what lets you change what is gated without shipping an app update. +Given how cheap `register` is, we strongly recommend registering **all core functionality**. That is what lets you change what is gated without shipping an app update. -## What actually happens +## What happens when you register When you register a placement: @@ -35,8 +35,8 @@ When you register a placement: 2. If one matches and the user is not in a holdout, the assigned paywall is presented. 3. Once a user is assigned a paywall for an audience, they keep seeing that paywall until you remove it from the audience or reset assignments. 4. After the paywall closes, the SDK looks at the paywall's **Feature Gating** value, set in the paywall editor under **General → Feature Gating**: - - **Non Gated** — the `feature` closure runs when the paywall is dismissed, whether they paid or not. - - **Gated** — the `feature` closure runs only if the user is already paying, or begins paying. + - **Non Gated**: the `feature` closure runs when the paywall is dismissed, whether they paid or not. + - **Gated**: the `feature` closure runs only if the user is already paying, or begins paying. 5. If no paywall is configured for the placement, the feature runs immediately with no extra network calls. ## Gating with entitlements directly @@ -53,7 +53,7 @@ if (Superwall.subscriptionStatus.isActive) { } ``` -Or collect the flow to keep UI in sync — see [Tracking subscription state](/kmp/quickstart/tracking-subscription-state). +Or collect the flow to keep UI in sync. See [Tracking subscription state](/kmp/quickstart/tracking-subscription-state). Prefer `register` with a `feature` closure over hand-rolled `if` checks where you can. The closure @@ -70,7 +70,7 @@ val entitlements = Superwall.entitlements entitlements.active // Set entitlements.inactive // Set entitlements.all // Set -entitlements.web // Set — granted via web checkout +entitlements.web // Set, granted via web checkout ``` Each `Entitlement` carries its `id`, `productIds`, `store`, expiry and renewal dates, and whether it is a lifetime purchase. @@ -83,7 +83,7 @@ val granted = Superwall.getEntitlementsByProductIds(setOf("pro_monthly", "pro_an ## Previewing the outcome -To adjust UI *before* a placement fires — hiding an upgrade button for users who would never see a paywall, say — ask what registering would do: +To adjust UI *before* a placement fires (hiding an upgrade button for users who would never see a paywall, for example), ask what registering would do: ```kotlin val result = Superwall.getPresentationResult(placement = "StartWorkout") diff --git a/content/docs/kmp/quickstart/install.mdx b/content/docs/kmp/quickstart/install.mdx index b9ae6c1c..22f59854 100644 --- a/content/docs/kmp/quickstart/install.mdx +++ b/content/docs/kmp/quickstart/install.mdx @@ -50,7 +50,7 @@ superwall-kmp = { module = "com.superwall.sdk:superwall-kmp", version.ref = "sup -`superwall-android` comes along transitively — do not add it yourself. +`superwall-android` comes along transitively, so do not add it yourself. @@ -66,10 +66,10 @@ The KMP library manifest already declares `SuperwallPaywallActivity`, and `super `Superwall.configure` takes no `Context` on Android. An `androidx.startup` initializer in the library manifest captures the `Application` before any of your code runs, which is what lets the `commonMain` signature stay platform-free. -If your app strips the startup provider — some apps remove `InitializationProvider` deliberately, and some shrinkers remove it by accident — that capture never happens and `configure()` fails with `SuperwallError.NotInitialized`. The escape hatch is an Android-only extension function: +If your app strips the startup provider (some apps remove `InitializationProvider` deliberately, and some shrinkers remove it by accident), that capture never happens and `configure()` fails with `SuperwallError.NotInitialized`. The fallback is an Android-only extension function: ```kotlin -// androidMain — only needed if the androidx.startup provider was removed +// androidMain: only needed if the androidx.startup provider was removed import com.superwall.sdk.kmp.androidSetup class MyApplication : Application() { @@ -104,7 +104,7 @@ kotlin { -`isStatic = true` is not a preference. The Kotlin framework compiles against the bridge's Objective-C headers only (compile-only cinterop) and never embeds the bridge binary, so a dynamic framework has nothing to resolve those symbols against at link time. +`isStatic = true` is required, not optional. The Kotlin framework compiles against the bridge's Objective-C headers only (compile-only cinterop) and never embeds the bridge binary, so a dynamic framework has nothing to resolve those symbols against at link time. @@ -122,7 +122,7 @@ Add the **`SuperwallKMPBridge`** product to your app target. Xcode defaults the Dependency Rule to **Up to Next Major Version**, as shown. While the SDK is in - beta, pin **Exact Version** instead — the bridge binary and the Kotlin klib ship from the same tag + beta, pin **Exact Version** instead. The bridge binary and the Kotlin klib ship from the same tag and are one release unit, so letting SPM drift ahead of the version your shared module was built against is what breaks the link step. @@ -131,13 +131,13 @@ Add the **`SuperwallKMPBridge`** product to your app target. **Do not add SuperwallKit separately.** -The bridge package pins SuperwallKit iOS to exactly `4.16.1` and pulls it in transitively. The pinned binary and the headers the Kotlin side was compiled against are one release unit — adding SuperwallKit yourself invites a version conflict that SPM cannot resolve. +The bridge package pins SuperwallKit iOS to exactly `4.16.1` and pulls it in transitively. The pinned binary and the headers the Kotlin side was compiled against are one release unit. Adding SuperwallKit yourself invites a version conflict that SPM cannot resolve. -**A missing bridge is a build-time failure, not a runtime one.** Because the Kotlin side uses compile-only cinterop, forgetting this step surfaces as undefined-symbol link errors when Xcode builds your app — not as a crash on launch or a paywall that silently fails to present. If you see linker errors mentioning bridge symbols, this step is what is missing. +**A missing bridge is a build-time failure, not a runtime one.** Because the Kotlin side uses compile-only cinterop, forgetting this step surfaces as undefined-symbol link errors when Xcode builds your app, not as a crash on launch or a paywall that silently fails to present. If you see linker errors mentioning bridge symbols, this step is what is missing. @@ -145,7 +145,7 @@ The bridge package pins SuperwallKit iOS to exactly `4.16.1` and pulls it in tra You need your **Public API Key** from the Superwall dashboard, under your app's settings. It is safe to ship in client code. -Android and iOS have separate keys in the dashboard. In a KMP app your `configure` call usually lives in shared code, so if you want one call site you will need to supply the right key per platform — an `expect`/`actual` value or a build-time constant both work. +Android and iOS have separate keys in the dashboard. In a KMP app your `configure` call usually lives in shared code, so if you want one call site you will need to supply the right key per platform. An `expect`/`actual` value or a build-time constant both work. The SDK itself needs no `expect`/`actual`. This is only about which API key string you hand it. diff --git a/content/docs/kmp/quickstart/present-first-paywall.mdx b/content/docs/kmp/quickstart/present-first-paywall.mdx index 4f8ffbc9..d0f74906 100644 --- a/content/docs/kmp/quickstart/present-first-paywall.mdx +++ b/content/docs/kmp/quickstart/present-first-paywall.mdx @@ -13,7 +13,7 @@ The KMP SDK is in beta and its API may change between releases. ## Register a placement -Paywalls are presented by registering a **placement**. You do not tell the SDK to show a paywall — you tell it a placement occurred, and your campaign on the dashboard decides what happens. +Paywalls are presented by registering a **placement**. You do not tell the SDK to show a paywall. You tell it a placement occurred, and your campaign on the dashboard decides what happens. ```kotlin Superwall.register(placement = "campaign_trigger") @@ -37,7 +37,7 @@ Superwall.register(placement = "campaign_trigger") { } ``` -When the closure runs depends on the paywall's feature-gating behavior — immediately when no paywall shows, or after a purchase or restore when the placement is gated. [Feature gating](/kmp/quickstart/feature-gating) covers the rules. +When the closure runs depends on the paywall's feature-gating behavior: immediately when no paywall shows, or after a purchase or restore when the placement is gated. [Feature gating](/kmp/quickstart/feature-gating) covers the rules. ## Pass parameters @@ -100,7 +100,7 @@ Superwall.register( `onSkip` is not a failure path. A holdout or an unmatched audience filter means your campaign - worked as configured — the user simply was not meant to see a paywall. + worked as configured. The user was not meant to see a paywall. All handler closures and the `feature` closure are delivered on the **main thread**, on both platforms. You can touch UI from them directly. @@ -131,7 +131,7 @@ It is a `suspend` closure, so you can do real work in it. When it is unset, the ## Check before you register -`getPresentationResult` previews what registering *would* do without presenting anything — useful for adjusting UI ahead of time, like hiding an upgrade button for users who would not see a paywall: +`getPresentationResult` previews what registering *would* do without presenting anything, which is useful for adjusting UI ahead of time, like hiding an upgrade button for users who would not see a paywall: ```kotlin val result = Superwall.getPresentationResult(placement = "campaign_trigger") diff --git a/content/docs/kmp/quickstart/tracking-subscription-state.mdx b/content/docs/kmp/quickstart/tracking-subscription-state.mdx index 623f16f9..15ad9321 100644 --- a/content/docs/kmp/quickstart/tracking-subscription-state.mdx +++ b/content/docs/kmp/quickstart/tracking-subscription-state.mdx @@ -11,7 +11,7 @@ The KMP SDK is in beta and its API may change between releases. -Superwall tracks subscription state for you. But there are times you need to know directly whether a user is on a paid plan — to show different UI, or to unlock something without a placement. +Superwall tracks subscription state for you. But there are times you need to know directly whether a user is on a paid plan, either to show different UI or to unlock something without a placement. ## Read it synchronously @@ -29,7 +29,7 @@ when (val status = Superwall.subscriptionStatus) { | State | Meaning | | --- | --- | -| `Unknown` | Not yet determined — typically before configuration completes | +| `Unknown` | Not yet determined, typically before configuration completes | | `Active(Set)` | The user has one or more active entitlements | | `Inactive` | The user has no active entitlements | @@ -64,9 +64,9 @@ scope.launch { -**Two naming details worth catching, if you are coming from the Android SDK.** +**Two naming details to watch for if you are coming from the Android SDK.** -The flow is `Superwall.subscriptionStatusFlow`. The plain `Superwall.subscriptionStatus` is a synchronous property, not a flow — on the Android SDK, `subscriptionStatus` *is* the flow. +The flow is `Superwall.subscriptionStatusFlow`. The plain `Superwall.subscriptionStatus` is a synchronous property, not a flow. On the Android SDK, `subscriptionStatus` *is* the flow. And this flow is **guard-exempt**: you can collect it before `configure`, where it is seeded with `SubscriptionStatus.Unknown` and attached to the native source once configuration completes. You do not have to sequence collection behind configuration. @@ -74,7 +74,7 @@ And this flow is **guard-exempt**: you can collect it before `configure`, where -This is a plain `StateFlow`, which means it delivers on **your collector's context** — it does not force emissions onto the main thread. Collect it from a main-dispatched scope (`collectAsState`, `viewModelScope`, `lifecycleScope`) and updating UI from the collector is safe. Collect it on `Dispatchers.IO` and it is not. +This is a plain `StateFlow`, which means it delivers on **your collector's context** and does not force emissions onto the main thread. Collect it from a main-dispatched scope (`collectAsState`, `viewModelScope`, `lifecycleScope`) and updating UI from the collector is safe. Collect it on `Dispatchers.IO` and it is not. The SDK's own KDoc says emissions arrive on the main thread; that is true of the common case, not a guarantee the flow enforces. @@ -110,7 +110,7 @@ Superwall.subscriptionStatus = SubscriptionStatus.Active(entitlements) ## Detailed purchase history -`CustomerInfo` carries more than `SubscriptionStatus` does — full transaction history, merging device and web purchases: +`CustomerInfo` carries more than `SubscriptionStatus` does, including full transaction history that merges device and web purchases: ```kotlin val info = Superwall.getCustomerInfo() @@ -136,7 +136,7 @@ scope.launch { Customer info works on **both** platforms. If you are reading the SDK's own KDoc, note that the -`@platform iOS` annotations on `customerInfoFlow` and `getCustomerInfo` are out of date — they +`@platform iOS` annotations on `customerInfoFlow` and `getCustomerInfo` are out of date. They describe a limitation that no longer applies. On Android the flow is fed by the native `customerInfoDidChange` delegate hook, and `getCustomerInfo()` calls straight through to `superwall-android` 2.8.0. @@ -144,7 +144,7 @@ describe a limitation that no longer applies. On Android the flow is fed by the - `customerInfoFlow` has no replay — a new collector gets nothing until the next change. Use + `customerInfoFlow` has no replay, so a new collector gets nothing until the next change. Use `getCustomerInfo()` for the current value. @@ -159,4 +159,4 @@ when (val result = Superwall.restorePurchases()) { } ``` -Restoration failure stays in the return type — it does not throw. And `Restored` means the restore completed without errors, not that the user necessarily has an active subscription. +Restoration failure stays in the return type and does not throw. `Restored` means the restore completed without errors, not that the user necessarily has an active subscription. diff --git a/content/docs/kmp/quickstart/user-management.mdx b/content/docs/kmp/quickstart/user-management.mdx index 4a6df37a..6f6246f0 100644 --- a/content/docs/kmp/quickstart/user-management.mdx +++ b/content/docs/kmp/quickstart/user-management.mdx @@ -24,7 +24,7 @@ Superwall.isLoggedIn // false until identify() is called ## Identified users -If you have your own user management system, call `identify` as soon as you have an ID — right after log in or sign up. This aliases your ID with the anonymous Superwall ID, which is what lets us load that user's assigned paywalls. +If you have your own user management system, call `identify` as soon as you have an ID, right after log in or sign up. This aliases your ID with the anonymous Superwall ID, which is what lets us load that user's assigned paywalls. ```kotlin // After retrieving a user's ID, e.g. from logging in or creating an account @@ -72,7 +72,7 @@ Values may be `String`, `Boolean`, `Long`, `Double`, `List`, `Map`, or `Set`. An -**`setUserAttributes` merges — it does not replace.** Keys you pass are merged into the existing attributes, a `null` value **removes** that key, and keys you leave out are untouched. +**`setUserAttributes` merges rather than replaces.** Keys you pass are merged into the existing attributes, a `null` value **removes** that key, and keys you leave out are untouched. That asymmetry is deliberate, and it is why this is a method rather than a settable property: reading `Superwall.userAttributes` after setting will not give you back only what you set. @@ -129,7 +129,7 @@ Superwall.configure( ) ``` -This option is **Android only** and is ignored on iOS. Make sure the value complies with [Google's policies](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.Builder#setObfuscatedAccountId) — it must not contain personally identifiable information. +This option is **Android only** and is ignored on iOS. Make sure the value complies with [Google's policies](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.Builder#setObfuscatedAccountId), and note that it must not contain personally identifiable information. From 121fb0007c6d74e2f3085320761643413fece4e4 Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Thu, 13 Aug 2026 12:11:07 -0500 Subject: [PATCH 7/9] Added temp icon --- content/docs/kmp/meta.json | 1 + src/lib/grid-icons.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/content/docs/kmp/meta.json b/content/docs/kmp/meta.json index 44a9a4b0..afa95270 100644 --- a/content/docs/kmp/meta.json +++ b/content/docs/kmp/meta.json @@ -1,5 +1,6 @@ { "title": "KMP SDK", + "icon": "Layers", "root": true, "pages": [ "index", diff --git a/src/lib/grid-icons.ts b/src/lib/grid-icons.ts index a3d86845..6b5b385e 100644 --- a/src/lib/grid-icons.ts +++ b/src/lib/grid-icons.ts @@ -154,6 +154,10 @@ const NAME_TO_GRID: Record = { // Ideas / tips lightbulb: "lightbulb", Lightbulb: "lightbulb", + // KMP has no brand mark of its own; layers reads as "multiplatform" and is + // not already used elsewhere in the top nav. + Layers: "layers", + layers: "layers", // Checkboxes / install-method cards "box-check": "box_checked", coconut: "box_checked", // "Use CocoaPods" card — matches its sibling install cards From ace2c0e38b35224a0fd6c0ac348924df3ae64949 Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Fri, 14 Aug 2026 14:41:07 -0500 Subject: [PATCH 8/9] docs(kmp): explain per-platform API keys with a concrete example The 'Getting the right API key' section assumed the reader knew what expect/actual meant and named mechanisms instead of showing one. Rewritten to state the actual situation (two dashboard apps, two keys, one shared call site) and show the expect/actual pattern as code. The install page's version of the same advice now links there instead of repeating it. Co-Authored-By: Claude Opus 5 --- .../docs/kmp/guides/platform-differences.mdx | 27 ++++++++++--------- content/docs/kmp/quickstart/install.mdx | 6 +---- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/content/docs/kmp/guides/platform-differences.mdx b/content/docs/kmp/guides/platform-differences.mdx index 41c1f0f9..faa2f15b 100644 --- a/content/docs/kmp/guides/platform-differences.mdx +++ b/content/docs/kmp/guides/platform-differences.mdx @@ -132,23 +132,24 @@ This path is not yet verified end-to-end on KMP. If you try it, we would like to -## What is *not* a difference +## Getting the right API key -Some things look like platform gaps if you read the SDK's inline documentation, but are not: +Your Android app and your iOS app are separate apps in the Superwall dashboard, and each one has its own Public API Key. In a KMP project, though, `Superwall.configure` is usually called once, from shared code. That single call site needs to end up with the Android key when the app runs on Android and the iOS key when it runs on iOS. - +One way to do that is Kotlin's `expect`/`actual`: -`Superwall.customerInfoFlow`, `Superwall.getCustomerInfo()`, -`SuperwallDelegate.customerInfoDidChange`, and -`Superwall.getEntitlementsByProductIds()` carry `@platform iOS` annotations or -"pending upstream support" notes in the SDK's KDoc. **Those annotations are stale.** All four are -wired on Android against `superwall-android` 2.8.0, which added the native APIs they were waiting -on. +```kotlin +// commonMain +expect val superwallApiKey: String -We have flagged this for the SDK team. Trust this page over the inline docs until the KDoc catches up. +// androidMain +actual val superwallApiKey: String = "pk_your_android_key" - +// iosMain +actual val superwallApiKey: String = "pk_your_ios_key" -## Getting the right API key +// commonMain: one call site, correct key on each platform +Superwall.configure(apiKey = superwallApiKey) +``` -Android and iOS have separate Public API Keys in the dashboard. The SDK does not need `expect`/`actual`, but your key does. Supply the right one per platform via an `expect val`, a build-time constant, or whatever your project already uses for platform config. +Passing the key in from each platform's entry point works just as well. Use whatever your project already does for per-platform values. diff --git a/content/docs/kmp/quickstart/install.mdx b/content/docs/kmp/quickstart/install.mdx index 22f59854..9dd532af 100644 --- a/content/docs/kmp/quickstart/install.mdx +++ b/content/docs/kmp/quickstart/install.mdx @@ -145,11 +145,7 @@ The bridge package pins SuperwallKit iOS to exactly `4.16.1` and pulls it in tra You need your **Public API Key** from the Superwall dashboard, under your app's settings. It is safe to ship in client code. -Android and iOS have separate keys in the dashboard. In a KMP app your `configure` call usually lives in shared code, so if you want one call site you will need to supply the right key per platform. An `expect`/`actual` value or a build-time constant both work. - - - The SDK itself needs no `expect`/`actual`. This is only about which API key string you hand it. - +Your Android and iOS apps are separate apps in the dashboard, and each has its own key. Since your `configure` call lives in shared code, it needs to receive the Android key on Android and the iOS key on iOS. [Getting the right API key](/kmp/guides/platform-differences#getting-the-right-api-key) shows a pattern for this. ## Verify the install From e84a03900c1a9f062e4bdaef80a7c48435ed2c7e Mon Sep 17 00:00:00 2001 From: Jordan Morgan Date: Fri, 14 Aug 2026 14:45:05 -0500 Subject: [PATCH 9/9] docs(kmp): cite the sample app for the expect/actual key pattern Co-Authored-By: Claude Opus 5 --- content/docs/kmp/guides/platform-differences.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/kmp/guides/platform-differences.mdx b/content/docs/kmp/guides/platform-differences.mdx index faa2f15b..5ee9c490 100644 --- a/content/docs/kmp/guides/platform-differences.mdx +++ b/content/docs/kmp/guides/platform-differences.mdx @@ -152,4 +152,4 @@ actual val superwallApiKey: String = "pk_your_ios_key" Superwall.configure(apiKey = superwallApiKey) ``` -Passing the key in from each platform's entry point works just as well. Use whatever your project already does for per-platform values. +This is the same pattern the [sample app](https://github.com/superwall/Superwall-KMP/blob/main/sample/shared/src/commonMain/kotlin/com/superwall/sdk/kmp/sample/ApiKey.kt) uses. Passing the key in from each platform's entry point works just as well; use whatever your project already does for per-platform values.