Handling Deep Links
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
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:
fun onDeepLink(url: String) {
if (Superwall.handleDeepLink(url)) return
myRouter.navigate(url)
}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.
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:
// 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:
// 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:
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 hooks: they arrive on a background thread on Android. The spinner calls above need a main-thread hop on Android. See Platform differences.
Superwall app links
SuperwallDelegate.handleSuperwallDeepLink reports links of the form yoursubdomain.superwall.app/app-link/..., broken into path components and query parameters:
override fun handleSuperwallDeepLink(
fullURL: String,
pathComponents: List<String>,
queryParameters: Map<String, String>,
) {
// 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. Only this structured callback 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 for the snippet. This path is not yet verified end-to-end on KMP.
How is this guide?