Attribution integration
Adapty allows easy integration with the popular attribution services: AppsFlyer, Adjust, Branch, Apple Search Ads, and Facebook Ads. Adapty will send subscription events to these services so you can accurately measure the performance of ad campaigns. You can also filter charts data using attribution data.
You can also integrate with Adapty's User Acquisition to connect ad spend with subscription revenue, giving you a complete view of your app's economy in one place.
Important
Send subscription events with correct user properties and ID's to attributions services you use.
-
Avoid event duplication: Be sure to disable subscription event forwarding from both devices and your server to prevent duplicates. If you're using direct integration with Facebook, remember to turn off event forwarding from AppsFlyer, Adjust, or Branch.
-
Properly set up attribution integration: Ensure that attribution is set up in both your mobile app code and the Adapty Dashboard. Without both in place, Adapty won't be able to send subscription events.
-
Set a single attribution source: Adapty can use attribution data in analytics from only one source at a time. If multiple attribution sources are enabled, the system will decide which attribution to use for each device based on the source that provides more fields. For iOS devices, this means non-organic Apple Search Ads attribution will always take priority if it's enabled. You can disable Apple Search Ads attribution collection by toggling off the Receive Apple Search Ads attribution in Adapty in the App Settings -> Apple Search Ads tab.
-
Attribution data is never overwritten in analytics: Attribution data is saved once after the user profile is created and won't be overwritten in analytics once stored.
Follow our detailed guidance on configuring the following 3d-part attribution integrations:
Don't see your attribution provider?
Let us know! Write to the Adapty support and we'll consider adding it.
Setting attribution data
To set attribution data for the profile, use .updateAttribution()
method:
- Swift
- Kotlin
- Java
- Flutter
- Unity
- React Native (TS)
Adapty.updateAttribution("<attribution>", source: "<source>", networkUserId: "<networkUserId>") { error in
if error == nil {
// succesfull attribution update
}
}
Adapty.updateAttribution(
mapOf("source" to "appsflyer", "campaign" to "summer_sale_2024"),
"appsflyer",
"networkUserId"
) { error ->
if (error == null) {
// succesfull attribution update
}
}
Adapty.updateAttribution("<attribution>", "<source>", "<networkUserId>", error -> {
if (error == null) {
// succesfull attribution update
}
});
try {
await Adapty().updateAttribution("<attribution>", source: "<source>", networkUserId: "<networkUserId>");
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
}
Adapty.UpdateAttribution("<attributions>", source, "<networkUserId>", (error) => {
if (error != null) {
// handle the error
}
// succesfull attribution update
});
// Optionally import enum to JavaScript
import { AttributionSource } from 'react-native-adapty';
const attribution = { /* ... */ };
try {
await adapty.updateAttribution(
attribution,
AttributionSource.Branch, // or just 'branch'
'networkUserId'
);
// succesfull attribution update
} catch (error) {
// handle `AdaptyError`
}
Request parameteres:
-
Attribution (required): a dictionary containing attribution (conversion) data.
-
Source (required): a source of attribution. The allowed values are:
.appsflyer
.adjust
.branch
.custom
-
Network user Id (optional): a string profile's identifier from the attribution service.
AppsFlyer
iOS SDK
To set attribution from AppsFlyer, pass the attribution you receive from the delegate method of AppsFlyer iOS SDK. Don't forget to set networkUserId
. You should also configure AppsFlyer integration in Adapty Dashboard.
In this case, it is mandatory to pass the networkUserId
parameter.
- Swift
- Kotlin
- Java
- Flutter
// Find your implementation of AppsFlyerLibDelegate
// and update onConversionDataSuccess method:
func onConversionDataSuccess(_ installData: [AnyHashable : Any]) {
// It's important to include the network user ID
Adapty.updateAttribution(installData, source: .appsflyer, networkUserId: AppsFlyerLib.shared().getAppsFlyerUID())
}
val conversionListener: AppsFlyerConversionListener = object : AppsFlyerConversionListener {
override fun onConversionDataSuccess(conversionData: Map<String, Any>) {
// It's important to include the network user ID
Adapty.updateAttribution(
conversionData,
"appsflyer",
AppsFlyerLib.getInstance().getAppsFlyerUID(context)
) { error ->
if (error != null) {
//handle error
}
}
}
}
AppsFlyerConversionListener conversionListener = new AppsFlyerConversionListener() {
@Override
public void onConversionDataSuccess(Map<String, Object> conversionData) {
// It's important to include the network user ID
Adapty.updateAttribution(
conversionData,
AdaptyAttributionSource.APPSFLYER,
AppsFlyerLib.getInstance().getAppsFlyerUID(context),
error -> {
if (error != null) {
//handle error
}
}
);
}
};
@override
Future<bool> initialize() async {
appsflyerSdk.onInstallConversionData((data) {
try {
await Adapty().updateAttribution(data,
source: AdaptyAttributionSource.appsflyer,
networkUserId: await appsflyerSdk.getAppsFlyerUID());
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
}
});
await appsflyerSdk.initSdk(
registerConversionDataCallback: true,
registerOnAppOpenAttributionCallback: true,
registerOnDeepLinkingCallback: true
);
return Future<bool>.value(true);
}
Adjust
iOS SDK
To set attribution from Adjust, pass the attribution you receive from the delegate method of Adjust iOS SDK. You should also configure Adjust integration in Adapty Dashboard.
- Swift
- Kotlin
- Java
// Find your implementation of AdjustDelegate
// and update adjustAttributionChanged method:
func adjustAttributionChanged(_ attribution: ADJAttribution?) {
if let attribution = attribution?.dictionary() {
Adapty.updateAttribution(attribution, source: .adjust)
}
}
adjustConfig.setOnAttributionChangedListener { attribution ->
attribution?.let { attribution ->
Adapty.updateAttribution(attribution, "adjust") { error ->
if (error != null) {
//handle error
}
}
}
}
adjustConfig.setOnAttributionChangedListener(attribution -> {
if (attribution != null) {
Adapty.updateAttribution(attribution, AdaptyAttributionSource.ADJUST, error -> {
if (error != null) {
//handle error
}
});
}
});
Branch
iOS SDK
To connect Branch user and Adapty user, make sure you set your customerUserId
as Branch Identity Id. If you prefer to not use customerUserId
in Branch, set networkUserId
param in .updateAttribution()
method to specify the Branch user Id.
- Swift
- Kotlin
- Java
// Pass the attribution you receive from the initializing method of Branch iOS SDK to Adapty.
Branch.getInstance().initSession(launchOptions: launchOptions) { (data, error) in
if let data = data {
Adapty.updateAttribution(data, source: .branch)
}
}
object branchListener : Branch.BranchReferralInitListener {
override fun onInitFinished(referringParams: JSONObject?, error: BranchError?) {
referringParams?.let { data ->
Adapty.updateAttribution(data, "branch") { error ->
if (error != null) {
//handle error
}
}
}
}
}
Branch.BranchReferralInitListener branchListener = (data, e) -> {
if (data != null) {
Adapty.updateAttribution(data, AdaptyAttributionSource.BRANCH, error -> {
if (error != null) {
//handle error
}
});
}
};
You should also configure Branch integration in Adapty Dashboard.
Apple Search Ads
Adapty can automatically collect Apple Search Ad attribution data. All you need is to add AdaptyAppleSearchAdsAttributionCollectionEnabled
to the app's Info.plist
file and set it to YES
(boolean value).
Facebook Ads
Because of iOS IDFA changes in iOS 14.5, if you use Facebook integration, make sure you send facebookAnonymousId
to Adapty by following the instructions for setting user attributes in your app . It allows Facebook to handle events if IDFA is not available. You should also configure Facebook Ads in Adapty Dashboard.
- Swift
- Kotlin
- Java
let builder = ProfileParameterBuilder()
.with(facebookAnonymousId: FBSDKCoreKit.AppEvents.anonymousID)
Adapty.updateProfile(parameters: builder.build()) { error in
if error == nil {
// successful update
}
}
val builder = AdaptyProfileParameters.Builder()
.withFacebookAnonymousId(AppEventsLogger.getAnonymousAppDeviceGUID(context))
Adapty.updateProfile(builder.build()) { error ->
if (error == null) {
// successful update
}
}
AdaptyProfileParameters.Builder builder = new AdaptyProfileParameters.Builder()
.withFacebookAnonymousId(AppEventsLogger.getAnonymousAppDeviceGUID(context));
Adapty.updateProfile(builder.build(), error -> {
if (error == null) {
// successful update
}
});
Custom
If you use another attribution system, you can pass the attribution data to Adapty. You can then segment users based on this data.
To set attributes, use only the keys from the example below (all keys are optional). The system supports max 30 available attributes, where the keys are limited to 30 characters. Every value in the map should be no longer than 50 characters. status
can only be organic
, non-organic
or unknown
. Any additional keys will be omitted.
let attribution = [
"status": "non_organic|organic|unknown",
"channel": "Google Ads",
"campaign": "Christmas Sale",
"ad_group": "ad group",
"ad_set": "ad set",
"creative": "creative id"
]
Adapty.updateAttribution(attribution, source: "custom")