Filters

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

PropertyData TypeDescriptionExample
branch_keyStringREQUIRED Your production API key, retrieved from Account Settings of your dashboard's Live environmentkey_live_example
branch_secretStringREQUIRED Your production API Secret, retrieved from Account Settings of your dashboard's Live environmentsecret_live_example
server_to_serverBooleanREQUIRED Always set to truetrue
app_versionStringREQUIRED Your app's version"1.12.4"
osStringREQUIRED Only accepts Android oriOS“Android”
os_versionStringREQUIRED 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_agentStringREQUIRED 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_idStringREQUIRED 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_typeStringREQUIRED - iOS ONLY Value confirms whether the iOS ID in the hardware_id property is an "idfa" or "vendorid" (_do not include in request, if hardware_id is not populated)"idfa" or "vendor_id"
ios_vendor_idStringREQUIRED - iOS ONLY The IDFV if it's available, otherwise do not include in request."0C381C08-B808-4C25-BE51-B00BC165B5F8"
google_advertising_idStringREQUIRED - ANDROID ONLY The Google Advertising ID if it's available, otherwise do not include in request"ea31e5e0-1aa5-4181-91d7-0b56524e0274"
advertising_idsObjectANDROID 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_realBooleanREQUIRED Set to false if the hardware_id property cannot be populated, otherwise default to truetrue
ad_tracking_enabledBooleanREQUIRED 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_ipStringThis 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_heightIntHeight of the device’s screen. An optional but useful data metadata that improves attribution accuracy.2208
screen_widthIntWidth of the device’s screen. An optional but useful data metadata that improves attribution accuracy. 1242
link_identifierStringa 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_urlStringPopulate 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_urlStringPopulate 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_checkedBooleanSet 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](https://help.branch.io/using-branch/docs/facebook-app-install-ads#section-setup)) true
install_referrer_extrasStringANDROID 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_referrerStringANDROID 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_tsLongANDROID 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_tsLongANDROID 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_tokenStringiOS 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_encodedStringDEPRECATED ⚠ 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_sessionBooleanIdentifies 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_identityBooleanSetting 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_tokenBooleanIf 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"
identityStringIf 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_disabledBooleanIf 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_calloutsBooleanIf set to true, you can use the Branch dashboard to selectively remove sessions with this flag from being sent to ad networks false
local_urlString(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_gclidStringANDROID 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"
gbraidStringIOS 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_1StringA 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_2StringA 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_3StringA 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:

ParameterDescription
randomized_bundle_tokenIf 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_linkThis 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_linkIf a non-Branch deep link opened your app (i.e., a Universal Link), you can retrieve that link from this key.
+is_first_sessionThis will be TRUE if Branch has never seen this user's device install the app before
+match_guaranteedThis 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_urlThis 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_pathThis 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_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

  1. Add your URI scheme to the info.plist
  2. Add your Branch app.link and alternate.app.link domains to the Associated Domains

App launch data needed for API request

  1. Retrieve the device ID (IDFA or IDFV) when available
  2. Retrieve the device’s public IP
  3. Retrieve the device’s User-Agent
  4. 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)
  5. 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:

  1. 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.
  2. 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]
  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

  1. Add your URI scheme to the Android Manifest
  2. Add your Branch app.link and alternate.app.link domains to the Android Manifest

App launch data needed for API request

  1. Retrieve the device ID (GAID or Android_ID when available
  2. Retrieve the device’s public IP
  3. Retrieve the device’s User-Agent
  4. 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)
  5. 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:

  1. Upon app launch, query the Google Play Install Referrer library for the referrer Url, click timestamp, and install timestamp
  2. 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.
  3. 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)