Attribution API

Overview

The Branch Mobile SDK uses a RESTful API (v1/open) for deep linking and session attribution. The instructions below cover how to supply a payload of attribution properties to this API server-side. Every time the API is called, it will track an INSTALL, REINSTALL, or OPEN event in Branch and return deep link data in the response if the session is attributed.

By bypassing the SDK, developers will be responsible for session management (when & where the v1/open API is called), handling poor or no connectivity, persisting data locally, retrieving values like IP address, tracking downstream conversions, creating shareable deep links, etc. To achieve feature parity with the SDK, one would need to duplicate the code in the SDK.

It is highly recommended that all apps use the Branch Mobile SDK when possible.

📘

API Access is restricted

The ability to directly call the v1/open API is restricted to select enterprise accounts. Please contact your Branch Account Manager to confirm if your account is eligible for enablement.

Prerequisites

  • App is setup in the Branch dashboard with default link redirects, your app.link domains, a URI scheme, Universal Links, and you have access to your API & Secret keys
  • Account has been enabled to access the v1/open API

📘

Dashboard & In-App setup required

Successful use of the v1/open API will require setup steps in the Branch dashboard and in your mobile app

API Setup

The network request to v1/open should occur when you are successfully notified the app was brought to the foreground. Branch defines an app lifecycle as a session of when your application is launched (cold start, or if it was present in the iOS or Android task manager), and comes to the device’s foreground.

Endpoint Specifications

  • Endpoint: https://api2.branch.io/v1/open
  • Method: POST
  • Payload Format: JSON
  • Required Header: The device's public IP address must be set using -H "X-IP-Override: xx.xx.xx.xx" (it is critical this uses the device's IP, and not your server's IP)
  • Required Header: -H 'content-type: application/json'

POST body parameters

Property Data Type Description Example
branch_key String REQUIRED Your production API key, retrieved from Account Settings of your dashboard's Live environment key_live_example
branch_secret String REQUIRED Your production API Secret, retrieved from Account Settings of your dashboard's Live environment secret_live_example
server_to_server Boolean REQUIRED Always set to true true
app_version String REQUIRED Your app's version "1.12.4"
os String REQUIRED Only accepts Android or iOS “Android”
os_version String REQUIRED The version of the device's OS (e.g. “23” for Android or “9.1.2” for iOS respectively. Will accept any value, preferred default to “NA”. This cannot be blank.) "13.2.2"
user_agent String REQUIRED The user agent of the device "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 6 Build/MOB31E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.81 Mobile Safari/537.36"
hardware_id String REQUIRED In iOS, populate with the IDFA if it's available, otherwise fallback to IDFV. On Android, populate with the ANDROID_ID (hardware id). If no device ID is available, do not include in request.

iOS: "D5B89252-FCF8-4065-88FC-B70F49186988"

Android: "fae098e4605e79c3"

hardware_id_type String REQUIRED - iOS ONLY Value confirms whether the iOS ID in the hardware_id property is an "idfa" or "vendor_id" (do not include in request, if hardware_id is not populated) "idfa" or "vendor_id"
ios_vendor_id String REQUIRED - iOS ONLY The IDFV if it's available, otherwise do not include in request "0C381C08-B808-4C25-BE51-B00BC165B5F8"
google_advertising_id String REQUIRED - ANDROID ONLY The Google Advertising ID if it's available, otherwise do not include in request "ea31e5e0-1aa5-4181-91d7-0b56524e0274"
advertising_ids Object ANDROID ONLY The set of Advertising IDs if it's available, otherwise do not include in request. Can include identifiers like OAID "advertising_ids": { "oaid": "02ab41d3-7886-4f29-a606-fba4372e9fdc" }
is_hardware_id_real Boolean REQUIRED Set to false if the hardware_id property cannot be populated, otherwise default to true true
ad_tracking_enabled Boolean REQUIRED A value used to determine whether the IDFA or GAID can be used for advertising purposes. If Limit Ad Tracking should be enabled, do not include in the request. true
local_ip String This is the device's local IP address, if one is available. This is incremental to the required IP header. An optional but highly recommended data metadata that improves attribution accuracy. "192.168.1.153"
screen_height Int Height of the device’s screen. An optional but useful data metadata that improves attribution accuracy. 2208
screen_width Int Width of the device’s screen. An optional but useful data metadata that improves attribution accuracy. 1242
link_identifier String a URI opens the app, check for a link_click_id query, and populate with that value (if missing, do not include in request)
link_click_id may also be sourced by the Google Install Referrer
“823569794275788167”
universal_link_url String Populate with a Branch or non-Branch web url that opened the app (if missing, do not include in request) "https://branch.app.link/example?utm_medium=test"
android_app_link_url String Populate with a Branch or non-Branch web url that opened the app (if missing, do not include in request) "https://branch.app.link/example?utm_medium=test"
facebook_app_link_checked Boolean Set to false to ensure we retrieve deep links from Facebook's deferred deep linking API (requires adding your Facebook App Secret to the Branch dashboard) true
install_referrer_extras String ANDROID ONLY Populate it with the value of the full Android PlayStore Install Referrer URL. Only include in the app's first session, if it's available. "utm_source=some_source&utm_medium=preload&utm_campaign=null&gclid=Cj0KCQiA7IDiBRCLARIsABIPohhqdEU00f-Obte_OIVTbjPo-iLDBjkhj8ov="
google_search_install_referrer String ANDROID ONLY The value of the google_search_install_referrer query parameter on the referrerUrl from the Google Install Referrer. Only include in the app's first session, if it's available. "7AXhuEQs1U"
clicked_referrer_ts Long ANDROID ONLY The referrer click timestamp collected from the Play Install Referrer library.
Only include in the app's first session, if it's available.
1573098834
install_begin_ts Long ANDROID ONLY The install begin timestamp collected from the Play Install Referrer library. Only include in the app's first session, if it's available. 1573098843
apple_attribution_token String iOS ONLY Attribution Token used for Apple Search Ads . used to call the Apple Search Ads Attribution API. The token has a 24 hr TTL, so send to Branch within that time in order to use it for attribution. "c7ya5fQsXrqhCiG0eQTvpS8+tNpBom1RwlDmWEXGNqIj1AOn/VDlqgKq9CaJzzFeR8G3dEeMQBJc60R4CxIx..."
search_ad_encoded String ⚠ DEPRECATED ⚠ iOS ONLY Base64 encoded string of the entire response from the Apple Search Ads API. Only include in the app's first session, if it's available. "eyJWZXJzaW9uMy4xIjp7ImlhZC1wdXJjaGFzZS1kYXRlIjoiMjAyMC0wNi0yOVQxODo1MDoxNloiLCJpYWQta2V5d29yZCI6IktleXdvcmQiLCJpYWQtYWRncm91cC..."
first_session Boolean Identifies if this is the first time the user opened the app. If true, Branch will check if we saw the user download the app before, and mark the session as a reinstall if yes, and an install if no. If this value was set to false, Branch will count the session as an open. true
server_to_server_identity Boolean Setting to true enables the ability to set an randomized_bundle_token property in v1/open requests and returns a value in the response. Do not set this property in the request, if this feature will not be used. false
randomized_bundle_token Boolean If server_to_server_identity is true, Branch returns a new identity value in any request that does not set randomized_bundle_token. After the first request, this property must be hardcoded with the randomized_bundle_token received in the first network response. Failure to return this value in subsequent requests severely limits the ability to connect different events for that user. "791040498773585647"
identity String If server_to_server_identity is true, this property can be used to associate a custom user ID with Branch's anonymous identity. You should never use personal user information here, and all values should be encrypted before being passed to Branch. "U1923847128356"
tracking_disabled Boolean If set to true, Branch will not store any data from this app session. The network response can still return deep link data for processing, but no information will be stored afterwards. false
disable_ad_network_callouts Boolean If set to true, you can use the Branch dashboard to selectively remove sessions with this flag from being sent to ad networks false
local_url String (Optional, for NativeLink) Populate with a Branch web url that is present on the clipboard on the very first open (if missing, do not include in request) "https://branch.app.link/example?utm_medium=test"
referrer_gclid String ANDROID ONLY (Optional, for Google AdWord Campaigns) Extract the value of gclid from Android PlayStore Install Referrer URL. Utilized for tracking downstream events on Google Adwords when user opts out on Android 12+ devices (if missing, do not include in request) "CjwKCAiA3L6PBhBvEiwAINlJ9Chixm216y8kYYJ1K94dm4FEkOgFfhIdKQdjWsYB7FqE7rf_zkGNEhoCuIEQAvD_BwE"
gbraid String IOS ONLY (Optional, for Google AdWord Campaigns) Extract the value of gbraid from the referring url/uri for the app session. Utilized for tracking downstream events on Google Adwords when users are opted out of ATT (if missing, do not include in request) "CjwKCAiA3L6PBhBvEiwAINlJ9Chixm216y8kYYJ1K94dm4FEkOgFfhIdKQdjWsYB7FqE7rf_zkGNEhoCuIEQAvD_BwE"
custom_param_1 String A customized parameter attached to your OPEN, INSTALL, or Event metadata to be used for visualizing/analyzing Branch aggregate data in both the Branch Dashboard reports and exports. "PARAMETER 1"
custom_param_2 String A customized parameter attached to your OPEN, INSTALL, or Event metadata to be used for visualizing/analyzing Branch aggregate data in both the Branch Dashboard reports and exports. "PARAMETER 2"
custom_param_3 String A customized parameter attached to your OPEN, INSTALL, or Event metadata to be used for visualizing/analyzing Branch aggregate data in both the Branch Dashboard reports and exports. "PARAMETER 3"

Example Requests

iOS

curl -v -d '{
 "branch_key": "TODO",
 "branch_secret": "TODO",
 "server_to_server": true,
 "app_version": "1.12.4",
 "os": "iOS",
 "os_version": "10.0",
 "model": "iPhone",
 "screen_height": 2208,
 "screen_width": 1242,
 "facebook_app_link_checked": false,
 "user_agent": "{FULL_USER_AGENT_HERE}",
 "hardware_id": "D5B89252-FCF8-4065-88FC-B70F49186988",
 "hardware_id_type": "idfa",
 "ios_vendor_id": "0C381C08-B808-4C25-BE51-B00BC165B5F8",
 "is_hardware_id_real": true,
 "ad_tracking_enabled": true,
 "custom_param_1": "Parameter 1",
 "custom_param_2": "Parameter 2",
 "custom_param_3": "Parameter 3"
}' "https://api2.branch.io/v1/open" -H "X-IP-Override: 1.2.3.4"

Android

curl -v -d '{
 "branch_key": "TODO",
 "branch_secret": "TODO",
 "server_to_server": true,
 "app_version": "1.12.4",
 "os": "Android",
 "os_version": 26,
 "model": "SM-G960U1",
 "screen_height": 2076,
 "screen_width": 1080,
 "facebook_app_link_checked": false,
 "user_agent": "{FULL_USER_AGENT_HERE}",
 "hardware_id": "fae098e4605e79c3",
 "google_advertising_id": "ea31e5e0-1aa5-4181-91d7-0b56524e0274",
 "advertising_ids": {
    "oaid": "02ab41d3-7886-4f29-a606-fba4372e9fdc"
 },
 "google_search_install_referrer": "referrer_value_here",
 "clicked_referrer_ts": 1574699946,
 "install_begin_ts": 1574699955,
 "is_hardware_id_real": true,
 "ad_tracking_enabled": true,
 "custom_param_1": "Parameter 1",
 "custom_param_2": "Parameter 2",
 "custom_param_3": "Parameter 3"
}' "https://api2.branch.io/v1/open" -H "X-IP-Override: 1.2.3.4"

📘

Rate limits on non-referred OPENs

Branch by default will rate limit non-referred OPEN events (app sessions not sourced by a link) per IP address, to once every 4 hours (contact your Branch Account Manager to confirm the exact limit for your account). Rate limited sessions will still return deep link data in the network request, but their data will not appear in the dashboard nor in your exports.

📘

Rate limits on high-frequency pings

Because the v1/open API is intended to measure a user's app session, we will return 429 responses if the app starts sending requests for the same user in rapid succession. Because normal user behavior is not to open & close an app in rapid succession, this scenario will likely only occur during testing. If you run into this, please wait a few minutes before resuming testing (or try changing the device metadata in your request).

📘

NativeLink

In order to implement NativeLink (learn more) and benefit from a guaranteed mechanism for deep linking, you will need to check the pasteboard on the first install. If it contains a URL, then examine the contents of the pasteboard. If it contains a Branch link, please send the full URL in the request body for key local_url.

For an example of checking the pasteboard on iOS, see this code snippet in our open-source iOS SDK.

Handling deep link data

When the v1/open request is made, the app session can be attributed to a deep link click. Regardless if the session is attributed, the API will always return a 200 response with some contextual data included in the JSON response payload. If the session was attributed to a Branch link, this payload will include the link's deep link data for your in-app logic to use to execute your deep link UX.

Samples responses are listed below, but a few key parameters to be aware:

  • randomized_bundle_token - If you set server_to_server_identity to TRUE in the v1/open request, you must ensure the value returned here is used in the randomized_bundle_token property of all v1/open requests moving forward for that device
  • +clicked_branch_link - This will tell you if the current app session was sourced via Branch deep link. This can be used as a conditional trigger that dictates if you use Branch-specific or other deep link routing logic.
  • +non_branch_link - If a non-Branch deep link opened your app (i.e., a Universal Link), you can retrieve that link from this key
  • +is_first_session - This will be TRUE if Branch has never seen this user's device install the app before
  • +match_guaranteed - This will be TRUE if Branch was able to match the app session to the browser click with 100% certainty. This can be used as a conditional trigger for use cases where you have zero risk threshold for a false positive (this should NOT be used in most instances)[Not applicable to SAN attributed Install].
  • $canonical_url - This will contain a web url that you can use for deep link routing. If your app was already setup to route off Universal Links or Android App Links, you can pass this value into that pre-existing routing logic.
  • $deeplink_path - This will contain a URI relative path that you can use for deep link routing. If your app was already setup to route off URI schemes, you can pass this value into that pre-existing routing logic.

Example organic response

{
   "session_id": "xxxx",
   "randomized_device_token": "xxxx",
   "link": "https://bnc.lt/j/adsf",
   "data": "{\"+clicked_branch_link\":false,\"+is_first_session\":false}"
}

Example organic response, with server_to_server_identity enabled

{
   "session_id": "xxxx",
   "randomized_bundle_token": "xxxx",
   "identity": "xxxx",
   "randomized_device_tokenrandomized_device_token": "xxxx",
   "link": "https://bnc.lt/j/adsf",
   "data": "{\"+clicked_branch_link\":false,\"+is_first_session\":false}"
}

Example response when session started by a non-Branch Deep Link

{
   "session_id": "823602214081710808",
   "data": "{\"+non_branch_link\":\"https://branch.io/\",\"+clicked_branch_link\":false,\"+is_first_session\":false}",
  "randomized_device_token": "823601870295755491"
}

Example response when session started by a Branch Deep Link

{
   "randomized_device_token": "823600311503935224",
   "link": "https://example.app.link/X7OsnWv9TF",
   "session_id": "429691081177874743",
   "data": "{
            "$canonical_url": "https://example.com/home?utm_campaign=test",
            "$desktop_url": "http://example.com/home",
            "$og_description": "My Content Description",
            "$og_image_url": "http://lorempixel.com/200/200/",
            "$og_title": "46D6D28E-0390-40E4-A856-BD74F34D24C8",
            "+click_timestamp": 1503684563,
            "+clicked_branch_link": true,
            "+is_first_session": false,
            "+match_guaranteed": true,
            "custom": "blue",
            "~campaign": "new launch",
            "~channel": "facebook",
            "~creation_source": 3,
            "~feature": "sharing",
            "~id": 429691043152332059,
            "~referring_link": "https://example.app.link/X7OsnWv9TF",
            "~stage": "new person",
            "~tags": ["one","two"]
   }"
}

In-App Setup

iOS

Configuration Updates

App launch data needed for API request

  • Retrieve the device ID (IDFA or IDFV) when available
  • Retrieve the device’s public IP
  • Retrieve the device’s User-Agent
  • Examine the AppDelegate's openURL: function for a URI. If a URI containing a query parameter link_click_id is present, store the query parameter's value for use in the session's API network request (i.e., if the URI example://open?link_click_id=1234 opens the app, you will retrieve the “1234” value)
  • Examine the AppDelegate's continueUserActivity: function for a webpageURL in the NSUserActivity parameter. If a URL is found (regardless if it's a Branch link), store the entire URL value for use in the session's API network request.

[OPTIONAL] To support Apple Search Ads

NEW FRAMEWORK:

  • For S2S integrations, you will need to retrieve the new token and send to Branch on the install as apple_attribution_token

Please refer to the new AdServices developer documentation on how to retrieve the token.

  1. Import AdServices.framework
  2. Request attribution token (see sample code). This should be available from Apple within 50ms.
  3. The token has a 24 hr TTL, so send to Branch within that time in order to use it for attribution.

See sample code for obtaining the Apple Attribution token:

func appleAttributionToken() -> String? {
        if #available(iOS 14.3, *) {
            return try? AAAttribution.attributionToken()
        }
        return nil
    }
+ (NSString *)appleAttributionToken {
#if !TARGET_OS_TV
    if (@available(iOS 14.3, *)) {
        NSError *error;
        NSString *appleAttributionToken = [AAAttribution attributionTokenWithError:&error];
        if (!error) {
            return appleAttributionToken;
        }
    }
#endif
    return nil;
}

OLD FRAMEWORK: All steps below should only occur for the INSTALL session:

  • Upon app launch, do not call v1/open, and first query the Apple Search Ads API. Apple's API is know to have high latency and operates at a race condition with its ad click (i.e., it must process the search click before it can respond to its attribution API), so give a 2 second buffer before calling Apple's Attribution API.
  • Implement retry logic (Branch's SDK uses 2 second delays between retries) if your request times out after 5 seconds, or if the response returns as False or Error Code [0,2,3]
  • If a successful response is received, base64 encode the entire API response, and add it to the search_ad_encoded property of the v1/open. Do not populate this in v1/open if apple did not attribute the session, and do not repeat this process during subsequent app sessions.

Android

Configuration Updates

App launch data needed for API request

  • Retrieve the device ID (GAID or Android_ID when available
  • Retrieve the device’s public IP
  • Retrieve the device’s User-Agent
  • Examine the intent that opened your MainActivity for a URI. If a URI containing a query parameter link_click_id is present, store the query parameter's value for use in the session's API network request (i.e., if the URI example://open?link_click_id=1234 opens the app, you will retrieve the “1234” value)
  • Examine the intent that opened your MainActivity for a web URL. If a URL is found (regardless if it's a Branch link), store the entire URL value for use in the session's API network request.

[OPTIONAL] To support Google Play Install Referrer

All steps below should only occur during the INSTALL session:

  • Upon app launch, query the Google Play Install Referrer library for the referrer Url, click timestamp, and install timestamp
  • Examine the referrer Url for a “link_click_id” query parameter, and if present, retrieve its value for use in the v1/open link_identifier property. This may appear in the referrer Url as &link_click_id=<value> or &link_click_id-<value>, but in either scenario you're only extracting the <value> part.
  • Examine the referrer Url for a “google_search_install_referrer” query parameter, and if present, retrieve its value for use in the v1/open google_search_install_referrer property. This may appear in the referrer Url as &google_search_install_referrer=<value> or &google_search_install_referrer-<value>, but in either scenario you're only extracting the <value> part.

Tracking Downstream Events

Every time the v1/open API is called it will track an INSTALL, REINSTALL, or OPEN event in Branch. To track additional downstream conversion events (i.e., PURCHASE), you will need to use the HTTP API instructions for our Commerce, Content, Lifecycle, and Custom events.

When tracking downstream conversion events, please address the following items:

  • If the request is made from the device, we will automatically retrieve the IP address from the request. If the request is made from a server, the user's IP address must be set via the following header: -H "X-IP-Override: xx.xx.xx.xx"
  • Set the device’s user agent in the request body’s user_data.user_agent
  • For events occurring in app, populate a device ID with IDFA (and fallback to IDFV) in iOS, or GAID (fallback to android_id) in Android
  • For events occurring on web, retrieve a Browser fingerprint via the Branch web SDK, to be included in the event call
  • Populate the developer_identity property whenever a persistent user ID is available (Best Practices for user IDs)

Server-to-Server Integrations with the TUNE API

All clients scoping a net new integration, should only consider the Branch SDK or server-to-server integration, and should NOT integrate with the TUNE API server-to-server. Any apps that originally integrated TUNE server-to-server, before TUNE was acquired by Branch, can find the API specs below for troubleshooting purposes:

For existing TUNE server-to-server integrations, it is good to confirm the following metadata properties are accounted for, to ensure TUNE integrations can leverage Branch's latest attribution methodologies:

Key

Description

ios_ifa

REQUIRED - iOS The IDFA if it's available

ios_ad_tracking_disabled

REQUIRED - iOS If the ios_ifa parameter is going to be used, then the ios_ad_tracking_disabled parameter must be specified to indicate whether the end user has enabled limited ad tracking (with 1 being enabled/limited).

ios_ifv

REQUIRED - iOS Populate with the IDFV

google_aid

REQUIRED - Android The Google Advertising ID if it's available. Formatted as uppercase with hyphens. AAAAAA-BBBB-CCCC-11111-2222222222222

google_ad_tracking_disabled

REQUIRED - Android If the google_aid parameter is going to be used, then the google_ad_tracking_disabled parameter must be specified to indicate whether the end user has enabled limited ad tracking (with 1 being enabled/limited).

os_id

REQUIRED - Android Populate with the ANDROID_ID (hardware id), if google_aid cannot be populated

device_id

REQUIRED - Windows The Windows Hardware ID

windows_aid

REQUIRED - Windows The Windows advertising identifier (AID) is a unique, user and device-specific, and resettable ID for advertising represented as an alphanumeric string formatted as upper case without colons (for example, "AAAAAABBBBCCCC111122222222222"). When the advertising ID feature is disabled, this value is an empty string.

referral_url

REQUIRED For Android and its first app open, include the Google Play install referrer.

For all other opens on Android and iOS, include the URL that caused the open (deep link).

device_ip

REQUIRED IP address of the user device recorded on conversion. This must be set via API query parameter, as the TUNE API cannot ingest an X-IP-Override Header

device_brand

REQUIRED Brand or maker of the user device (such as "Apple" or "Samsung")

device_model

REQUIRED Model of the user device recorded on conversion (such as "iPhone5,2" or "GT-i9300")

user_agent

REQUIRED The device's user agent. This can also be set in a network request header.

os_version

OPTIONAL Version of the operating system (such as iOS or Android) on the user device

device_carrier

OPTIONAL Carrier of the device if supports cellular (such as AT&T)

language

OPTIONAL Language of the device from local settings

country_code

OPTIONAL The ISO ALPHA-2 or ISO ALPHA-3 value of the country

app_version

OPTIONAL Version of the app on the user device (this parameter helps TUNE distinguish between new app installs and existing app updates)

user_id

OPTIONAL The ID of the user defined by the advertiser

📘

local_ip is not supported on TUNE API calls

local_ip is leveraged for Branch's Predictive Modeling capabilities, but this cannot be set in TUNE API calls. This will not prevent attribution on the TUNE API endpoint.


Did this page help you?