Call order in Kotlin Multiplatform SDK

Adapty.activate() must finish before you call any other Adapty SDK method. Until it completes, the SDK has no state. Any call issued before or in parallel with activate() fails with an activation error. See Handle errors in Kotlin Multiplatform SDK.

If your app authenticates users and you collect a customer user ID after launch, call Adapty.identify() at that point. Don’t call user-action methods until identify completes. Calls that race against it either return an error, or land on the anonymous profile created at activation. When this happens, attribution, MMP IDs like appsflyer_id, and install ownership don’t always transfer to the identified profile. If your app doesn’t authenticate users, skip identify and keep working with the anonymous profile.

MMP and analytics SDKs (AppsFlyer, Adjust, Branch, PostHog) follow the same rule. Initialize them first and wait for their UID callbacks before calling Adapty.activate. Otherwise the MMP ID lands on a brief anonymous profile and isn’t always transferred to the identified one. For AppsFlyer specifics, see AppsFlyer.

The correct order

Your path depends on two things: when you know the customer user ID, and whether you use an MMP or analytics SDK.

  • Steps 2 and 5: Mandatory for every app. Activate the SDK, then call SDK methods.
  • Steps 1 and 3: Required only if you integrate an MMP or analytics SDK (AppsFlyer, Adjust, Branch, PostHog).
  • Step 4: Required only if your app authenticates users and collects the customer user ID after launch.

If you have the customer user ID at app launch, pass it into the AdaptyConfig.Builder before calling activate() (step 2a). This path never creates an anonymous profile, so step 4 is unnecessary.

StepCallWhenNotes
1Initialize your MMP or analytics SDK (AppsFlyer, Adjust, PostHog, Branch)App launch, firstWait for the MMP’s UID callback, for example getAppsFlyerUID.
2aAdapty.activate(configuration = AdaptyConfig.Builder("KEY").withCustomerUserId(...).build())App launch, after step 1, if you have the customer user IDRecommended. No anonymous profile is ever created.
2bAdapty.activate(configuration = AdaptyConfig.Builder("KEY").build()) without withCustomerUserIdApp launch, after step 1, if you don’t have the customer user ID (or never collect one)Adapty creates an anonymous profile.
3Adapty.setIntegrationIdentifier("appsflyer_id", uid) for each MMPAfter step 2, before any user-action callRequired so MMP IDs land on the correct profile.
4Adapty.identify("YOUR_USER_ID").onSuccess { ... }.onError { ... }After step 3 (or step 2 if no MMP), before step 5 — only on path 2b with authenticationWait for onSuccess before any user-action call. Concurrent calls during identify may land on the anonymous profile.
5getPaywall, getPaywallProducts, restorePurchases, makePurchase, updateAttribution, updateProfileAfter step 4 if you call identify; otherwise after step 3 (or step 2 if no MMP)These calls need a stable profile.

Skipping these steps causes lost premium access for returning users, missing appsflyer_id on profiles, and paywalls returned against the wrong audience.

Web2app and web-funnel installs

If users buy on a web checkout (Stripe, Paddle) and later install the native app, the device’s first activate() creates a new anonymous profile. This profile isn’t linked to the web profile. If you can resolve the customer user ID before app launch (from your auth flow or install referrer), pass it into the AdaptyConfig.Builder directly. Otherwise the web purchase is invisible on the device until you call identify("YOUR_USER_ID") and then restorePurchases.

For the metadata to send with each web checkout, see: