SKAN integration guide for ad networks

At a glance: Ad networks integrate with AppsFlyer SKAdNetworks (SKAN), enabling them to optimize campaigns and to be attributed to the traffic they generate.

SKAdPartnerBadges.png

Learn more about the AppsFlyer SKAN solution for advertisers:

SKAN solution guide | SKAN dashboard 

AppsFlyer offering for ad networks 

  • Be attributed for campaign conversions:
    • Integration with AppsFlyer ensures that the ad network is attributed for all installs, in-app events, and revenue resulting from campaigns run on advertisers' behalf.
    • Without integration in place, installs, in-app events, and revenue are attributed as organic and not to the ad network. 
  • Campaign optimization:
    • The conversion value in the postback is encoded.
    • AppsFlyer enables ad networks to translate the conversion value of each postback, ensuring ad networks can optimize their campaigns based on the decoded value per app.
  • No need for direct integration with each advertiser:
    SKAN postbacks are sent only to the ad network. Advertisers can consume the data by either: 
    • Individual integration with each ad network. A solution that is not scalable, neither for ad networks nor for advertisers. 
    • A single integration with AppsFlyer. Scalable for both the advertiser and the ad network.
  • Increase your prominence in AppsFlyer: 
    • Ad networks having SKAN integration are certified and identified as such in the AppsFlyer dashboard. 
    • This assures advertisers that they are working with ad networks that can be measured deterministically via this attribution model.

SKAN data flow

PostbackProcess_us-en.png

The full SKAN postback flow is as follows:

  1. iOS sends the SKAN postback to the attributed ad network.
  2. The ad network does one of the following:
    • Enrich and forward: Enrich the SKAN postback with the ad network campaign ID (to overcome the SKAN limitation of 100 campaign IDs), campaign name, and the iOS device IP address. 
    • Redirect: The network requests the iOS device to redirect the postback directly to AppsFlyer. In this case, campaign data enrichment will be performed via a separate API between AppsFlyer and the ad network.
  3. AppsFlyer validates and decodes the postback. Then, it sends the decoded and enriched postback to the ad network (in parallel to sharing it with the advertiser).

Main integration parts

SKAN integration between AppsFlyer and ad networks consists of the following main parts as described in this article:

  • Ad networks send SKAN data to AppsFlyer
  • Ad networks receive enriched and decoded data from AppsFlyer via postbacks

Send data to AppsFlyer

After the ad network receives the SKAN postback from the device, the ad network forwards it to AppsFlyer using one of the following methods:

  • Enrich and forward (POST)
  • Redirect (HTTP 307 redirect method)

Upon receipt of a SKAN postback, AppsFlyer performs the following:

  • Postback validation: Ensure that it is unique.
  • Conversion value decode: Generate attribution install/in-app event records.
  • Send decoded postbacks to the ad network.
  • Make attribution data available to advertisers via dashboards and reports.

Enrich and forward

Using this method, ad networks forward each postback received from the device to AppsFlyer.

The ad network:

  • Receives the postback from the iOS device
  • [Mandatory] Enriches the postback with:
    • Ad network campaign ID and campaign name
    • IP address received from the device, required mainly for geo resolution purposes. 
    • The timestamp of the postback sent from the iOS device
  • [Optional] Enrich the postback with:
    • Adset ID and name
    • Ad ID and name
  • Sends the postback to AppsFlyer.
  • Note! Before sending the postback to AppsFlyer, validate the Apple attribution signature using the content of the outgoing postback to ensure that you didn't inadvertently corrupt the data. 
SKAN enriched postback protocol
앤드 포인트

https://skadpostbacks.appsflyer.com

HTTP 메서드 POST
허용된 콘텐츠 유형 application/json
Return codes

200 OK: Postback received has a valid format. 

400: Bad request: Malformed JSON, empty, JSON, missing mandatory fields.

SKAN enriched postback JSON parameters

파라미터

형식

설명

미디어 소스

version 문자열

SKAdNetwork version

Example: "version":"2.0"

SKAN postback
ad-network-id 문자열

Ad network ID

Example: "ad-network-id":" abc123defg.SKAdnetwork"

SKAN postback
campaign-id 정수

SKAdNetwork campaign ID

Example: "campaign-id":23

SKAN postback
transaction-id 문자열

SKAdNetwork postback transaction ID

SKAN postback
app-id 정수 Target app ID SKAN postback
attribution-signature 문자열 Attribution signature SKAN postback 
redownload Boolean When redownload = true, it means the user downloaded the app from the app store again. SKAN postback
source-app-id 정수

Source App ID (publisher)

SKAN postback
conversion-value 정수

AppsFlyer SDK sets the conversion value according to advertiser settings.

Notes!

  • iOS due to iOS privacy-preserving thresholds may not populate the parameter in the postback and the value will be null.
  • Null and 0 have different meanings:
    • Null: iOS withheld the conversion value
    • 0: The user installed the app but didn't perform any measured actions.  
SKAN postback 
ad-network-campaign-id 문자열

To enable a common language between ad networks, advertisers, and AppsFlyer, you must provide your campaign-id.

애드 네트워크
ad-network-campaign-name 문자열 Ad network campaign name associated with the ad network campaign ID. This name displays in dashboards and reports.  애드 네트워크
ad-network-adset-id 문자열

Ad network adset ID

애드 네트워크
ad-network-adset-name 문자열

Ad network adset name

애드 네트워크
ad-network-ad-name 문자열

Ad network ad name

애드 네트워크
ad-network-ad-id 문자열

Ad network ad ID

애드 네트워크
ip 문자열

The IP address of the device sending the postback.

iPv4 and IPv6 addresses supported.

Example: "ip":"198.51.100.1"

애드 네트워크
타임 스탬프 문자열

Time the ad network received the SKAN postback. A 10-digit epoch UNIX timestamp. [Optional] 13-digit epoch timestamp permitted.

예:

August 4, 2020, 07:25 UTC translates to "timestamp": "1596525944"

애드 네트워크
fidelity-type 정수

Differentiate between ad presentation options that affect attribution. Indicated using the values 0 and1 as follows: 

  • 뷰-쓰루 광고(0)
  • Storekit-rendered ads (1)

Mandatory field starting SKAN V2.2

SKAN postback (V2.2+)
did-win Boolean

Used to distinguish between campaigns contributing or attributed with the install. 

  • true인 경우 인스톨을 가져오기 위해 캠페인이 어트리뷰트됩니다.
  • false이면 캠페인은 인스톨을 기여하는 것으로 인식됩니다.
SKAN postback (V3.0+)
ad-network-source-app-id 문자열

Populate with the publisher ID that you associate with the app publishing the ad. This is usually the ID you allocated to the publisher, and not the ID generated by Apple. 

애드 네트워크
ad-network-country-code 문자열

The user location (geo) as derived by the ad network.

Populate using ISO 3166 (alpha-2) codes.

Example: CN, ZA

Ad networks often derive geo according to a given campaign's target region.  

AppsFlyer uses the country code to populate geo-related fields in reports and dashboards. 

애드 네트워크

 Ad network optional parameters sent via query params

파라미터

형식

설명

미디어 소스

ad_network_name

문자열

Name of the ad network

Example: ad_network_name=your_network

애드 네트워크

app_id

문자열

The app id as it appears in AppsFlyer. Always has the prefix id.

Example:app_id=id123456789

애드 네트워크

ad-network-country-code 문자열

The user location (geo) as derived by the ad network.

Populate using ISO 3166 (alpha-2) codes.

Example: CN, ZA

Ad networks often derive geo according to a given campaign's target region.  

AppsFlyer uses the country code to populate geo-related fields in reports and dashboards. 

애드 네트워크

Curl example—enriched SKAN postback with optional query params

curl --location --request POST 'https://skadpostbacks.appsflyer.com/api/postbacks?app_id=id888707074' \
  --header 'Content-type: application/json' \
  --data-raw '{
      "version":"2.0",
      "app-id": 888707086,
      "ip": "192.0.2.0",
      "ad-network-campaign-name": "skadnetwork_abc_campaign",
      "source-app-id": 888707074,
      "ad-network-id": "abcabcabc.skadnetwork",
      "transaction-id": "68eb3d91-15f5-44ee-9267-25c7655c20b6",
      "redownload": false,
      "attribution-signature": "MDYCGQCsQ4y8d4BlYU9b8Qb9BPWPi+ixk/OiRysCGQDZZ8fpJnuqs9my8iSQVbJO/oU1AXUROYU=",
      "timestamp": "1596525944",
      "ad-network-campaign-id": "222222",
      "conversion-value": 63,
      "campaign-id": 99
  }'

리다이렉트

Redirect_us-en__2_.png

Using this method, the ad network responds to the device with an HTTP redirect command (307), requesting the device to send the postback directly to AppsFlyer. 

The redirect method has the following advantages:

  • Increased advertiser trust: The MMP acts on behalf of an advertiser. By providing AppsFlyer access to the postback firsthand, advertisers are confident that postbacks are not manipulated in transit.
  • No processing required by the ad network: Ad networks respond with the redirect command (to the device), thus eliminating the need to process postbacks. In comparison, the enrich and forward method requires that ad networks consume the postback, enrich it with additional parameters, and finally forward it to AppsFlyer.

구현하기

  1. Configure your server to respond with an HTTP 307 response redirecting the postback to https://skadnetworkredirect.appsflyer.com/api/redirects
  2. Append query params that contain campaign details using the query params listed in the table that follows. Regard the sending of your campaign details as mandatory. Campaign details enable us to enrich SKAN data with cost and other campaign data and enable advertisers to effectively optimize campaigns.

Example redirect URL

https://skadnetworkredirect.appsflyer.com/api/redirects?
  &ad-network-campaign-id=243232&ad-network-campaign-name=yarg_campaign_name
  &ad-network-adset-name=dsdsa

Query param

설명

ad-network-campaign-id 캠페인 ID
ad-network-campaign-name Campaign name
ad-network-adset-id 광고세트 ID
ad-network-adset-name 광고 세트 이름
ad-network-ad-id 광고 아이디
ad-network-ad-name 광고 이름
ad-network-country-code

The user location (geo) derived by the ad network.

Populate using ISO 3166 (alpha-2) codes.

Example: CN, ZA

Ad networks often derive geo according to a given campaign's target region.  

AppsFlyer uses the country code to populate geo-related fields in reports and dashboards. 

Query params for campaign details (not mandatory)

 

Receive data from AppsFlyer

Prior to receiving your first postback, take into consideration the following: 

  • Ad networks must define the postback end-point and template (reach out to your AppsFlyer Partner Development Manager or to integrations@appsflyer.com to ensure this is in place).
  • AppsFlyer sends SKAN postbacks using the same mechanism as with the existing postbacks sent to you.

원리

  • For each postback sent from the ad network to AppsFlyer, AppsFlyer sends:
    • One install postback. Redownloads are signaled by the redownload parameter. 
    • Zero to several in-app event postbacks. The exact number depends on the translation of the conversion value. See simulated postbacks.
  • When you consume postbacks, the same install or event can be attributed by more than one AppsFlyer attribution solution. Use the attribution_source parameter to differentiate between postback types. 

Postback macros

포스트백 매크로(이름)

설명

Format and example Relevant to in-app events only

benefit_score

(PredictSK) A normalized weighted average of 3 KPI scores (engagement, monetization, retention). The score is from 1 to 9 (1 being the lowest, 9 the highest, and 0 is for users with insufficient data). 

정수

 

engagement_score

(PredictSK) A score that estimates the quantity and quality of user interaction with the app. The score is from 1 to 9 (1 being the lowest, 9 the highest, and 0 is for users with insufficient data).  

정수

 

monetization_score

(PredictSK) A score that estimates how much revenue the user is expected to generate (including in-app purchases and ad revenue). The score is from 1 to 9 (1 being the lowest, 9 the highest, and 0 is for users with insufficient data).

정수

 

retention_score

(PredictSK) A score that estimates how long a user is expected to continue using the app. The score is from 1 to 9 (1 being the lowest, 9 the highest, and 0 is for users with insufficient data). 

정수

 

site_id

The app publishing the ad (source app ID)

String: 876534

 

install_time

Estimated by AppsFlyer based on the updateConversion window. Provided as a 10-digit UNIX epoch timestamp or as a human-readable timestamp

  • String: 1596119460 
  • Translates to July 30, 2020, 14:31 UTC.
 

skadnetwork_ad_network_time

Time the postback was received by the ad network from the iOS device. Reported by the ad network. Provided as a 10-digit UNIX epoch timestamp or as a human-readable timestamp

  • String: 1596119460 
  • Translates to July 30, 2020, 14:31 UTC



 


skadnetwork_received_time

Time AppsFlyer received the postback from the ad network. Provided as a 10-digit UNIX epoch timestamp or as a human-readable timestamp

 

  • String: 1596119460 
  • Translates to July 30, 2020, 14:31 UTC

 

event_name

Event name 

  • af_skadnetwork_revenue
  • af_login
  • af_skadnetwork_revenue
  • or as set by the advertiser 

String: af_skadnetwork_revenue, abc123

 

수익

Revenue amount using the specified currency code

Number: 5, 20, 0.4

currency

Currency code being the app-specific currency set by the advertiser

String: EUR, USD, ZAR

attribution_source

The source of the attribution data:

SKAdNetwork: SKAdNetwork

String: SKAdNetwork

 

app_id

App ID (advertiser app)

String: ID123456790

 

국가

Install geo (country) determined by the ad network

String: US, UK, ZA 

 

campaign

Campaign name populated using ad-network-campaign-name sent in the postback from the ad network

String: UA_US_23+

 

campaign_id

Ad network Campaign ID populated using ad network-campaign-id sent in the postback from the ad network

String: 3456745

 

redownload

Possible values: true, false

When redownload = true, it means the user downloaded the app from the app store again

Boolean: true, false

 

skadnetwork_ambiguous_event

Events received during the first 72-hours after an advertiser changes the SKAN settings in the dashboard. Due to the various timers employed by SKAN AppsFlyer can't map the event accurately.

Boolean: true, false

 

skadnetwork_campaign_id

SKAN campaign ID as provided by the original SKAN postback

56, 23

 

af_skadnetwork_nonce

파트너가 중복 포스트백을 식별할 수 있게 하는 고유한 랜덤 식별자

 

 

event_id

Name/ID of the corresponding event in the ad network platform

 

transaction_id

SKAN postback transaction ID

Note: The advertiser must explicitly allow us to share the transaction_id with you. Ask the advertiser to do so in the Integration tab.

 

 

 

ad_network_adset_id Added to the iOS postback by the ad network 문자열  
ad_network_adset_name Added to the iOS postback by the ad network 문자열  
ad_network_ad_name Added to the iOS postback by the ad network 문자열  
ad_network_ad_id Added to the iOS postback by the ad network 문자열  
SKAN_min_event_counter See note (1)

정수

SKAN_max_event_counter See note (1)

정수

SKAN_min_time_post-install See note (2)

정수

SKAN_max_time_post-install See note (2)

정수

SKAN_min_event_revenue 일러두기 (3)을 참조하십시오. 실제 번호
SKAN_max_event_revenue 일러두기 (3)을 참조하십시오.

Real number 

fidelity-type

Differentiate between ad presentation options that affect attribution. Indicated using the values 0 and1 as follows: 

  • 뷰-쓰루 광고(0)
  • Storekit-rendered ads (1)
정수  
skad_af_attribution_flag

Used to indicate if the user was attributed by AppsFlyer using the Single Source of Truth mechanism

Boolean  

일러두기:

  1. Event occurrences: The number of event occurrences is calculated using the following formula:
    [round up (SKAN_min_event_counter+SKAN_max_event_counter) / 2]
    Note! The value must be rounded up to the nearest integer.
    • 예:
      • A. If min=0 and max=1 the number of events is 1.
      • B. If min=0 and max =10 the number of events is 5.
  2. Determine install time: For advertisers implementing custom conversion, AppsFlyer calculates install time as the postback arrival time - 48h - average (min_time_post_install + max_time_post_install). Ad networks don't need to make use of these macros.  
  3. Determine revenue: AppsFlyer uses these values to determine the revenue of an event by calculating the average of min and max. Ad networks don't need to make use of these macros. 
Macros available in the postback to Ad network partners

SKAN postback examples

Example of an install SKAN postback sent by AppsFlyer

http://YourCompanyDomain.com/event?site_id=(publisher-id)&install_time=(timestamp)
  &skan_ad_network_time=(timestamp)
  &skan_af_received_time=(timestamp)
  &attribution_source=skadnetwork
  &app_id=(id123456789)&country=(ZA)&campaign=(campaign-name)
  &campaign_id=(campaign-id)&SKAN_ambiguous_event=(boolean)
&redownload=(boolean)
&af_SKAN_nonce=(uuid)

Example of an in-app SKAN postback sent by AppsFlyer

http://YourCompanyDomain.com/event?site_id=(publisher-id)&install_time=(timestamp)
  &skan_ad_network_time=(timestamp)
  &skan_af_received_time=(timestamp)&revenue=(value)
  &currency=(code)&event_name=(event-name)&attribution_source=skadnetwork
  &app_id=(id123456789)&country=(ZA)&campaign=(campaign-name)
  &campaign_id=(campaign-id)&SKAN_ambiguous_event=(boolean)
&redownload=(boolean)
&af_SKAN_nonce=(uuid)

Integration testing

To validate the integration with AppsFlyer, use either or both of the following methods. 

  • Real SKAN postbacks: based on actual SKAN traffic received by the network
  • Simulated postbacks: based on AppsFlyer test apps

To receive real SKAN postbacks from iOS devices, the ad network completes the following:

To receive simulated postbacks:

Real environment

Using this method, the ad network sends AppsFlyer actual SKAN postbacks from live apps. 

담당자 액션
애드 네트워크 Notify AppsFlyer via your partner development manager (or email to integations@appsflyer.com) as to your SKAN network ID, provided by Apple.
Ad network and AppsFlyer Agree on a mutual customer (having integrated the most recent AppsFlyer SDK) to use for postback integration verification.
애드 네트워크 Send app SKAN postbacks to AppsFlyer, using one of the methods described in this article.
앱스플라이어 Send decoded postbacks to the ad network in accordance with the conversion value mapping set by the advertiser.
Testing integration
담당자 액션
애드 네트워크 Notify AppsFlyer as to the quantity of SKAN postbacks sent during a specified period for the agreed mutual customer.
앱스플라이어 Verify the count of postbacks received versus the count sent by the ad network.
앱스플라이어

Share with the ad network the count of postbacks sent to the network for a given app broken down by type:

  • Install/redownload postbacks
  • In-app postbacks.
Note: If you use the same endpoint for probabilistic postbacks, ensure that you filter using attribution_source=skadnetwork to distinguish SKAN Network postbacks from other postbacks.
Test criteria

Simulated postbacks

  • Using this method, the ad network sends AppsFlyer preprepared postbacks to AppsFlyer test apps, as detailed in the table below. AppsFlyer replies with decoded postbacks to the ad network.
  • Each test app has a different conversion value mapping, as detailed in the table.
앱 ID Conversion mode 어트리뷰션 구현 가이드
id888707085

Revenue, in $1 units

Expected results: 

  1. In the Integration tab, enable in-app events postbacks
  2. Select event name af_SKAN_revenue and map to your event identifier.
  3. Save configuration.
  4. In a postback, send conversion value = 7.
  5. AppsFlyer responds with:
    • 인스톨 포스트백
    • af_SKAN_revenue postback with value of $7
id888707086 Conversion, including the in-app events:
  • af_level_complete
  • af_login
  • af_SKAN_revenue
  • af_register
  • af_subscription
  • af_custom_event
  1. In the Integration tab, enable in-app events postbacks
  2. Select each of the in-app events listed and map it to your event identifier. 
  3. Save configuration.
  4. In a postback, send conversion value = 63.
  5. AppsFlyer responds with:
    • 인스톨 포스트백
    • af_level_complete postback
    • af_login postback
    • af_SKAN_revenue postback
    • af_register postback
    • af_subscription postback
    • af_custom_event postback
id888707087 Engagement, measured using af_SKAN_revenue event
  1. In the Integration tab, enable in-app events postbacks
  2. Map the event name af_SKAN_revenue and to your event identifier.
  3. Save configuration.
  4. In a postback, send conversion value = 3.
  5. AppsFlyer responds with:
    • 인스톨 포스트백
    • 3 postbacks of af_SKAN_revenue event
담당자 액션
애드 네트워크 Configure your SKAN network ID (provided by Apple) and SKAN postback template on the postback management platform. For queries and assistance, contact integrations@appsflyer.com.
애드 네트워크
  1. Activate the test apps.
  2. For each app complete the instructions column in the previous table. 
  3. Send simulated postbacks, using the test apps listed in the preceding table. Considerations when sending simulated postbacks:
    • Set the app_id and conversion value as listed in the preceding table. 
    • Since Ad networks can't generate Apple compatible signatures, the simulated postbacks don't have to include the signature fields. AppsFlyer will not verify them for simulated postbacks.
    • Ad networks send the postback using either the POST or REDIRECT approach.
앱스플라이어 Responds with the decoded postbacks to the endpoint designated by the ad network during integration
Integration steps
담당자 액션
앱스플라이어 Process the postback and sends postbacks to the ad network.
애드 네트워크
  • Ad network receives and decodes the translated postbacks.
  • In-app postbacks sent by AppsFlyer match the expected flows. For example, conversion value 3 for app ID888707087, the ad network receives 3 postbacks of af_SKAN_revenue event. 
Test criteria

Clarifications

Clarifications relating to mandatory fields, enrichment, certification, and more.

자주 하는 질문

Questions and answers about postbacks

Are the enrichment fields mandatory? 

For the present, we will process the postback even if it is missing one or more of the following enrichment parameters. Consider that the information is required for the following reasons: 

  • Ad network campaign ID: If we have cost integration with you then this is reported using your campaign ID. 
  • Ad network campaign name: Many advertisers relate to the campaign name and not the campaign number. 
  • IP address: Required for geo resolution. 
  • Timestamp: Assists us to attribute the install to the correct date. 

Can we send either our campaign ID, or our campaign name, but not both?

See the previous answer. Consider populating both ID and name with the same value. 

We are using Enrich and Forward. Can we add key-value pairs that are not in the AppsFlyer specification? 

Yes, you can. We will process the postback and disregard the extra information provided that the attribution signature is valid

Are the SKAN postback templates distinct from the existing postback templates?

Yes. The flow and structure differ.

Will we receive a SKAN postback and a probabilistic/deterministic modeling postback related to the same install, meaning duplicate reporting of the same install?

Yes. For each case, we record an install attributed to you, irrespective of method, we will send you a postback.

Use attribution_source to differentiate SKAN postbacks.

 

Are we required to process the postback from AppsFlyer?

No. Consider, that best practice is to optimize campaigns according to user-quality reported via the postback. 

Are we expected to call AppsFlyer attribution links or is it sufficient to send the postback with the SKAN payload and enriched data?

It is sufficient to send us the SKAN payload and enriched data.

What is required for us to be certified in the AppsFlyer dashboard as a SKAN integrated partner?

  • Complete integration using one of the methods listed in this article
  • Send us postbacks of apps using AppsFlyer as their attribution partner

How does the limit of 100 SKAN campaign IDs impact me

The 1-100 limit relates to the way you sign and number your campaigns in Apple. It means that at any time, you can have 100 simultaneous unique campaigns. We allow you to enrich the postback with your actual campaign name and ID. Meaning you map the SKAN campaign ID to your actual campaign IDs in use at the time the postback is received. Doing so means that the 100 ID limit does not restrict the number of campaigns that you measure in AppsFlyer provided of course that you don't have more than 100 simultaneous campaigns for a given app.