Migrate from Superwall
Map Superwall concepts and SDK calls to Voidhash, and move your paywalls and purchases over.
This page maps Superwall's concepts and SDK calls to their Voidhash equivalents, then lists the steps specific to moving from Superwall. Voidhash covers paywalls and purchases in one SDK, so the migration may also replace the billing code your Superwall setup relied on. The overall plan is in Migrate to Voidhash.
Concepts
| Superwall | Voidhash | Notes |
|---|---|---|
| Placement | Paywall location | A stable slug in your app, such as onboarding. |
| Campaign | A location's placement, optionally with an A/B test | Studio decides which paywall a location shows. |
| Audience | — | A location shows one paywall to everyone; see No targeting rules. |
| Paywall | Paywall | Designed and deployed in Studio. |
| Entitlement | Perk | Checked by slug, such as premium. |
| Subscription status | Active perks | Read from the person; see Subscription lifecycle. |
| Products | Products mapped to store products | |
| User ID | Distinct ID | Your user ID, passed to identify. |
| User attributes | Person attributes | Set with setPersonAttributes. |
| Purchase controller | Voidhash owns purchases, or observer mode | No adapter code needed when Voidhash owns them. |
SDK calls
Superwall names below are the Swift ones; the other Superwall SDKs use close equivalents.
| Superwall | Swift | Kotlin | React Native |
|---|---|---|---|
Superwall.configure(apiKey:) | Voidhash.configure(publishableKey:options:) | Voidhash.configure(context, publishableKey, options) | createVoidhashClient(publishableKey) |
identify(userId:) | identify(externalUserId:) | identify(externalUserId) | client.identify(userId) |
reset() | signOut() | signOut() | client.signOut() |
register(placement:) | presentFlow(placement: "onboarding") | presentFlow(activity, "onboarding") | client.presentFlow("onboarding") |
register(placement:feature:) | presentFlow, then check the perk and run the feature | The same | The same |
subscriptionStatus | getCurrentPerson()?.hasActivePerk("premium") | getCurrentPerson()?.hasActivePerk("premium") | client.hasPerk("premium") or useHasPerk |
setUserAttributes(_:) | setPersonAttributes(_:) | setPersonAttributes(...) | client.setPersonAttributes(...) |
A gated feature becomes two calls: present the location, then run the feature if the person has the perk afterwards.
import Voidhash
func openExport() async {
guard let voidhash = Voidhash.shared else { return }
var person = try? await voidhash.getCurrentPerson()
if person?.hasActivePerk("premium") != true {
_ = await voidhash.presentFlow(placement: "export")
person = try? await voidhash.getCurrentPerson()
}
if person?.hasActivePerk("premium") == true { showExport() }
}Steps specific to Superwall
Decide who owns purchases
If Superwall, a purchase controller or another billing SDK finishes your transactions today, start
Voidhash in observer mode with readOnly on, and call reportTransaction after each purchase. See
Observer mode. If you're replacing all of it at once, test the full purchase
path in the sandbox before you ship.
Rebuild the catalog
Create a perk for each entitlement and a product for each store product, map them, and attach perks. Import products on the Products page lists the store products that aren't mapped yet. See Products and perks.
Recreate placements and paywalls
Create a location for each placement, with the same name as its slug if you can, so app code changes little. Paywalls don't import: rebuild them in the designer, deploy, and assign each to its location. A location shows the same paywall to everyone, so split audiences you relied on into separate locations chosen by your app. Paywalls are in early access.
Connect the stores
Connect the App Store and Google Play (Help center), including store notifications. If another system already receives them, use Voidhash's notification forwarding or add a second Pub/Sub subscription; see Store notifications.
Use the same user IDs, then switch
Call identify with the same user ID you pass to Superwall. Compare access for a sample of people,
then move paywalls and purchase ownership to Voidhash behind one flag with setReadOnly(false).
Remove Superwall once the flag is at 100%.
Exactly one SDK must finish or acknowledge each transaction. Decide which from one flag, read before either SDK starts a purchase, and never let both, or neither, own purchases.
Next steps
- Migrate to Voidhash: the phased plan and timeline.
- Paywalls in your app
- Paywall locations
Something wrong or missing on this page? Tell us by email or on Discord.