At a glance: Learn how to create measurement data sources, and how to provide access to them in a way that can be digested by the attribution job.
Overview
The first step in setting up the measurement process is to prepare the three inputs that feed it: conversions, engagements, and campaign mapping. These inputs must be prepared based on the predefined schema or event structure, depending on the data provision mode: in-app events or custom source files.
When the provision mode is custom source files, the attribution job is triggered automatically when the required conversion and engagement record folders are uploaded to the cloud. For in-app event mode, the job is triggered when relevant in-app events are selected.
Prepare in-app events
You can send conversion and engagement data via in-app events sent by the AppsFlyer SDK integrated into your app.
Note
If you are already passing AppsFlyer in-app events through SDK or via server-to-server requests, this option might be easier to implement than the custom source file option.
Prepare conversion in-app events
The conversion in-app event should include the SKU information. In the following example, the af_order_info
key identifies the SKU information:
"event_value": { "event_id": "<event_id>", "af_currency": "EUR", "af_content": "retail", "af_order_id": "637f7c400f0e3fddd9e5bcbc", "af_order_info": [ { "sku": "a", "revenue": 1.1, "qty": 2 }, { "sku": "b", "revenue": 100.5, "qty": 1 } ] }
For information about how to prepare in-app events, see the Create in-app events section below.
Prepare engagement in-app events
On-site campaigns can receive engagements via in-app events. The engagement in-app event should include the attribution data in the event_value
key. See, as an example, the following event_value
JSON structure:
"event_value": { "ad_name": "Spring_Sale_Ad_01", "ad_id": "ad_123456", "ad_type": "video", "adset_name": "Spring_Sale_Set_A", "adset_id": "adset_7890", "campaign_name": "Spring_2025_Promo", "campaign_id": "camp_456123", "channel": "facebook", "media_source": "meta_ads", "engagement_type": "click", "event_id": "evt_20250410_001" }
You can use the fields below in your evant_value
JSON key:
Field | Description | Required | Available within in-app event schema | Type |
---|---|---|---|---|
campaign_id |
Campaign ID | Yes | No | string |
campaign_name |
Campaign name | No | No | string |
engagement_type |
Differentiates between clicks and impressions | Yes | No | string |
media_source |
Media source attributed to an event or restricted (see more) | Yes | No | string |
ad_id |
Ad ID | No | No | string |
ad_name |
Ad name | No | No | string |
ad_type |
Example: banner, footer | No | No | string |
adset_id |
Adset ID, identifying a group that contains one or more ads | No | No | string |
adset_name |
Adset name, identifying a group that contains one or more ads | No | No | string |
channel |
Media source channel. Example: YouTube for Google, Instagram for Meta ads | No | No | string |
For more information, about how to prepare in-app events, see the Create in-app events section below.
Create in-app events
To provide conversion and engagement data through in-app events configure the AppsFlyer SDK integrated into your app. For more information about creating in-app events, see:
Prepare custom source files
If you are running an on-site campaign you can use custom source files as the source of your conversions and engagements with the schema outlined in the tables below.
Prepare the conversion custom source
Use the scheme in the table below to create a conversion custom source file:
Field | Description | Required in custom data source | Expected value type | Data validations |
---|---|---|---|---|
appsflyer_id |
A unique ID generated by the SDK when the app is installed. It is used to attribute in-app events, fetch conversion data, and affiliate in-app events. A new ID is generated if the app is deleted and reinstalled. Restoring the app from an iCloud backup is not considered an install. For CTV, this field is populated with the custom_device_id managed by the advertiser. |
Optional PII field. One of the PII fields is required. | string | None |
advertising_id |
User-resettable device ID, also known as GAID. For CTV, this is the CTV ID, for example, RIDA or VIDA. | Optional PII field. One of the PII fields is required. | string | None |
cuid |
A unique app user ID set by the app owner. | Optional PII field. One of the PII fields is required. | string | None |
android_id |
Permanent device ID | Optional PII field. One of the PII fields is required. | string | None |
idfa |
User-resettable advertising ID on iOS devices. If idfa is unavailable, it is typically populated with zeros. |
Optional PII field. One of the PII fields is required. | string | None |
idfv |
Vendor ID provided by iOS | Optional PII field. One of the PII fields is required. | string | None |
event_name |
The attribution event type or in-app event name sent by the app. Example event types: install, re-engagement, etc. For Data Locker in retargeting reports: retargeting means re-engagement, and install means re-attribution. For SKAN, the in-app event name is as configured in AppsFlyer or Meta ads. | Mandatory | string | None |
event_time |
Event time, rounded down to the nearest hour. | Mandatory | datetime | None |
sku |
The stock-keeping unit (SKU) ID for one of the items included in the conversion event. | Mandatory | string | None |
sku_quantity |
Number of SKU units included in the conversion event. | Mandatory | integer | None |
app_id |
Unique app identifier in AppsFlyer. Example: iOS: id123456789, Android: com.appsflyer.referrersender | Optional | string | None |
app_name |
Set by the advertiser | Optional | string | None |
app_version |
Set by the advertiser | Optional | string | None |
city |
The most granular location of the user based on the device IP. Usually holds a city name, but may also include districts or boroughs. | Optional | string | None |
country_code |
Country code using ISO 3166 (alpha-2). Example: US, CN. Note: The United Kingdom is coded as UK, not GB. | Optional | string | None |
device_category |
Possible values include: phone, tablet, or other. | Optional | string | None |
event_currency |
The event revenue currency code reported to the SDK. | Optional | string | datetime structure according to DCR format requirements |
event_revenue |
Revenue value using the event revenue currency. Amounts outside the range $-10,000 to $+10,000 (or equivalent) appear in raw data but not in aggregate reports. | Optional | decimal | None |
platform |
Device platform: iOS, Android, or Windows Mobile | Optional | string | None |
region |
Based on the device IP address reported by the SDK. For SKAN, determined according to the country_code . |
Optional | string | None |
sku_revenue |
Revenue associated with the SKU in the currency provided in the event_revenue_currency field. |
Optional | decimal | None |
state |
Based on the device IP address reported by the SDK. | Optional | string | None |
Prepare the engagement custom source
Use the schema below to create the engagement data source.
Note
The Personally identifiable information (PII) fields mapped in the engagement source scheme should have a non-empty intersection with the PIIs mapped in the conversion source scheme above
Field | Description | Required | Expected value type |
---|---|---|---|
appsflyer_id |
Unique ID generated by the SDK when the app is installed | Optional PII field. One of the PII fields is required. | string |
cuid |
Unique app user ID set by the app owner | Optional PII field. One of the PII fields is required. | string |
idfa |
User-resettable advertising ID for iOS devices. If unavailable, it is populated with zeros | Optional PII field. One of the PII fields is required. | string |
idfv |
Vendor ID provided by iOS | Optional PII field. One of the PII fields is required. | string |
app_id |
Unique app identifier in AppsFlyer. Example: iOS: id123456789 , Android: com.appsflyer.referrersender
|
Optional | string |
campaign_id |
Campaign ID | Mandatory | string |
campaign_name |
Campaign name | Optional | string |
media_source |
Media source attributed to an event or restricted (see more) | Mandatory | string |
engagement_type |
Differentiates between clicks and impressions | Mandatory | string |
event_name |
Set by the advertiser | Mandatory | string |
event_time |
Event time, rounded down to the nearest hour | Mandatory | datetime |
app_name |
Set by the advertiser | Optional | string |
app_version |
Set by the advertiser | Optional | string |
ad_id |
Ad ID | Optional | string |
ad_name |
Ad name | Optional | string |
ad_type |
Example: banner, footer | Optional | string |
adset_id |
Adset ID, identifying a group that contains one or more ads | Optional | string |
adset_name |
Adset name, identifying a group that contains one or more ads | Optional | string |
channel |
Media source channel. Example: YouTube for Google, Instagram for Meta ads | Optional | string |
platform |
Device platform: iOS, Android, or Windows Mobile | Optional | string |
For more information about how to prepare sources and upload them to your cloud service, see the Create and connect custom data sources section of this document.
Prepare campaign mapping source
The source of your campaign mapping data is a custom data source file with the schema outlined in the table below.
Note
We recommend using a single mapping file for all collaborations, as it is easier to maintain and update.
The campaign mapping scheme
Use the schema below to create the campaign mapping source.
Field type | Required? | Expected Value | Description |
---|---|---|---|
collaborator_name | Yes | string | The name of the collaborator you work with. |
collaborator_id | Yes | string | A unique identifier for the collaborator. |
campaign_id | Yes | string | The unique identifier for the campaign. |
conversion_targets | Yes | string array | A parameter that expects a comma-separated list of the campaign target SKUs, for example, sku1, sku2, etc. |
For more information about how to create source files and upload them to your cloud service, see the Create and connect custom data sources section of this document.
Attribution job ingestion flow
Each attribution job is dedicated to a single day and runs after the day ends. At the beginning of this process, the job ingests the relevant conversions, engagements, and campaign mapping data from the cloud service or from in-app events.
Campaign mapping source ingestion
Before each attribution run, DCP loads campaign mapping records from the custom sources. You can choose between two modes for loading these records:
-
Latest Strategy: DCP takes the most recent records based on the record upload date.
For example, if the source contains records with upload dates of Jan 18, Jan 17, or Dec 29, the system will select the records with the Jan 18 date.
- Daily Strategy: DCP only takes records whose upload date matches the day of the attribution run. For example, if the run occurs at midnight on Jan 19, the system will only select campaign records with the Jan 19 upload date.
Conversion source ingestion
At the end of each day, DCP runs the attribution job for that day only if it can access the folder dedicated to that day and the conversion records within it. However, you can upload the folder for a certain day at a later date. For example, you can upload the Jan 17 folder on Jan 22.
- At the end of each day, DCP runs the attribution job for that day. The job will run only if DCP can find the folder for that day. The folder name is identical to the day name.
- The day folder can include records for events dating back 30 days from the day of the folder. For example, in the Jan 17 folder, the job processes records from December 18 to January 17.
- If you skip uploading the folder for a certain day, you have 30 days to upload it. For example, if you skipped uploading the Jan 17 folder, you can upload it until Feb 17. However, we recommend uploading it as close as possible to the folder date.
- If DCP does not find the current day’s folder, it will continue searching for the folder every 10 minutes for the next 7 days.
Engagement source ingestion
For each conversion record, DCP searches for the engagement events that triggered it.
- The engagement records are included in dated folders. However, you don’t have to upload an engagement folder for each day. For example, you can upload a Jan 13 and Jan 15 folder without uploading the Jan 14 folder. In this example, the records from Jan 14 will be taken from the Jan 15 folder.
- The attribution job for a given conversion folder will start only if an engagement folder with the same date as the conversion folder or a later date exists. For example, the attribution job for the Jan 17 conversion folder will start only if the Jan 17 engagement folder or folders with later dates, such as Jan 18, exist.
- The attribution job collects all engagement events that fall within the engagement lookback window.
In-app data ingestion
Conversion and engagement data can come from in-app events, custom sources, or a combination of both. DCP lets you choose whether to use a single mode or mix them, allowing conversions to come from in-app events while engagements are sourced from custom files, or vice versa.
When configuring in-app events for conversions, engagements, or both, you must specify the app ID and the conversion or engagement event name. At the end of the day, the attribution job selects all events with the specified name and app ID that have the same event date as the conversion day.
Create and connect custom data sources
To connect data through custom sources customer will first need to follow the instructions in the following DCP knowledge base articles: