> For the complete documentation index, see [llms.txt](https://help.branch.io/llms.txt).

# Desktop and Over the Top (OTT) Attribution

## Overview

Branch supports server-to-server (S2S) measurement for desktop and all of the popular over-the-top (OTT) platforms.

This document outlines how to send sessions and conversion events. These are separate because sessions are fundamentally different from conversion events. The response from a request to Branch to log a session may include deep link data. You can use this to deep link the user to content, including the “deferred deep linking” scenario where a user clicked a link, then installed the app and opened it.

We use Roku as the basis for this guide, but the guide applies to other OTT solutions. We provide an example request (curl), then we discuss each parameter in the request. For specific parameters, we provide tables showing how to change the request based on the platform (for example, Amazon Fire TV, Apple TV, and Samsung Smart TV).

## Before you begin

- Your app is set up in [Branch](https://help.branch.io/account-hub/basic-link-configuration.md) with default link redirects, your app.link domains, a URI scheme, and Universal Links.
- Make sure you have access to your Branch Key and Branch Secret.
- Complete the [in-app setup](https://help.branch.io/apidocs/attribution/overview.md#in-app-setup) steps.

## Session measurement

A session measurement request should be made to the `/v1/open` endpoint every time the app is opened. The response should be parsed and a few of the values should be used on subsequent requests (that is, `randomized_device_token` and `randomized_bundle_token`).

## Session request parameters

| Parameter | Type | Definition |
| --- | --- | --- |
| branch_key | String | Your Branch Key, provided at the time of dashboard creation. |
| branch_secret | String | Your Branch Secret, provided at the time of dashboard creation. |
| server_to_server | Boolean | Hardcode this into the request as true. |
| app_version | String | Your app's semantic version ID. |
| os | String | See [platform specific key-value section](https://help.branch.io/apidocs/attribution/desktop-over-the-top-ott-attribution.md#session-platform-specific-key-values-examples). |
| os_version | String | OS semantic version ID. |
| retryNumber | Integer | Default to 0. If retrying a request, set this to 1 (first retry) or 2 (second retry). |
| brand | String | Brand of the device. |
| model | String | Model of the device. |
| screen_height | Integer | Height of the screen. |
| screen_width | Integer | Width of the screen. |
| ad_tracking_enabled | Boolean | Make sure you pass this so that Branch can use this flag. |
| advertising_ids | Map of String → String | Should include the appropriate key for the device, and then the value of that advertising ID. See [platform specific key-value section](#session-platform-specific-key-values-examples). |
| launch_options |  | **Roku only**<br>Map of query parameters on the launch or input request, as well as other metadata that may be passed to the Roku app as part of these commands.<br>Example: The following command is issued to your app:<br>`curl -d '' 'http://192.168.0.1:8060/launch/dev?contentId=1234&mediaType=movie'` |
| randomized_device_token | String | On the initial request (that is, install), omit this key. It is returned in the first response (for example, "randomized_device_token": "123456789123456789"). Then send it on subsequent requests. |
| server_to_server_identity | Boolean | Hardcode this into the request as true. This generates the randomized_bundle_token for the S2S requests and returns it in the response. This needs to be accompanied by identity below. |
| identity | String | **Only works with the server_to_server_identity.** This is mapped and set as the developer_id when making the S2S call. Example: `"test_user_01”` |
| link_identifier | String | When a URI opens the app, check for a link_click_id<br> query and populate with that value (if missing, do not include in request)<br> Example: yourapp://open?link_click_id=823569794275788167 |

### Session platform-specific key values examples

**MAC_OS**

- os: MAC_OS
- id: MAC address (Media Access Control)

  - example: `"mac_address" : "88:66:5a:2f:81:fa"`

**WINDOWS**

- os: WINDOWS
- advertising_ids: windows_advertising_id

  - example: `"windows_advertising_id": "ea31e5e0"`
- id: MAC address (Media Access Control)

  - example: `"mac_address" : "00:1A:C2:7B:00:47"`

**tv_OS**

- os: TV_OS
- advertising_ids: idfa

  - example: `"idfa": "ea31e5e0-1aa5-4181-91d7-0b56524e0274"`

**ROKU**

- os: ROKU
- advertising_ids: roku_rida

  - example: `"roku_rida": "ea31e5e0-1aa5-4181-91d7-0b56524e0274"`

**SAMSUNG**

- os: TIZEN
- advertising_ids: samsung_ifa

  - example: `"samsung_ifa": "ea31e5e0-1aa5-4181-91d7-0b56524e0274"`

**LG**

- os: WEBOS
- advertising_ids: lg_ifa

  - example: `"lg_ifa": "ea31e5e0-1aa5-4181-91d7-0b56524e0274"`

**XBOX**

- os: XBOX
- advertising_ids: xbox_msai

  - example: `"xbox_msai": "ea31e5e0-1aa5-4181-91d7-0b56524e0274"`

## Example request

```curl
curl -d '{
  "branch_key": "key_live_YOUR_KEY_HERE",
  "app_version": "1.0.1",
  "os": "ROKU",
  "os_version": "10.0",
  "retryNumber": 0,
  "brand": "Roku",
  "model": "4200X",
  "sdk": "roku",
  "sdk_version": "1.0.0",
  "screen_height": 1334,
  "screen_width": 750,
  "ad_tracking_enabled": true,
  "advertising_ids": {
    "roku_rida": "00000000-0000-0000-0000-000000000123"
  },
  "launch_options": {
    "contentID": "1234",
    "instant_on_run_mode": "foreground",
    "lastExitOrTerminationReason": "EXIT_UNKNOWN",
    "mediaType": "movie",
    "source": "external-control",
    "splashTime": "1500"
  },
  "randomized_device_token": "123456789123456789",
  "randomized_bundle_token": "987654321987654321"
}' "https://api2.branch.io/v1/open"
```

## Example response

```json
{
  "data": "{\"+clicked_branch_link\":true,\"+is_first_session\":false,\"contentID\":\"1234\",\"mediaType\":\"movie\"}",
  "randomized_device_token": "123456789123456789",
  "randomized_bundle_token": "987654321987654321",
  "session_id": "685187705776489500"
}
```

**Note**: The deep link data is located inside the `data` object. It includes +clicked_branch_link: true as well as the link data.

## Conversion event measurement

Conversion events include anything beyond sessions. They include sign-ups, content views, purchases, and the like.

For Standard Events, make requests to `/v2/event/standard`.

If you want to track an event not on this list, you can track a Custom Event. These will not be nicely mapped to 3rd-party event names, so this should be a fallback if there is no good Standard Event available.

> **Branch Standard Events**
>
> For a full list of Branch Standard Events, see [this document](https://help.branch.io/developer-hub/track-branch-events.md).

For Custom Events, make requests to `/v2/event/custom`.

## Conversion event request parameters

| Parameter | Type | Definition |
| --- | --- | --- |
| name | String | Should be a Standard Event name if using /v2/event/standard. Otherwise can be a custom event name (any string) if using /v2/event/custom. |
| customer_event_alias | String | Can be any string. |
| branch_key | String | Your Branch Key, provided at the time of dashboard creation.<br><br>**Required** |
| user_data.developer_identity | String | Your ID for a user. |
| user_data.app_version | String | Your app's semantic version ID. |
| user_data.os | String | See [platform specific key-value section](https://help.branch.io/apidocs/attribution/desktop-over-the-top-ott-attribution.md#conversion-event-platform-specific-key-values-examples). |
| user_data.os_version | String | OS semantic version ID. |
| user_data.brand | String | Brand of the device. |
| user_data.model | String | Model of the device. |
| user_data.screen_height | Integer | Height of the screen. |
| user_data.screen_width | Integer | Width of the screen. |
| user_data.environment | String | See [platform specific key-value section](https://help.branch.io/apidocs/attribution/desktop-over-the-top-ott-attribution.md#conversion-event-platform-specific-key-values-examples). |
| user_data.limit_ad_tracking | Boolean | Make sure you pass this so that Branch can use this flag. Inverse of /v1/open -> ad_tracking_enabled |
| user_data.advertising_ids | Map of String → String | Should include the appropriate key for the device, and then the value of that advertising ID. See [platform specific key-value section](https://help.branch.io/apidocs/attribution/desktop-over-the-top-ott-attribution.md#conversion-event-platform-specific-key-values-examples). |
| user_data.randomized_device_token | String | On the initial request (that is, install), omit this key. It is returned in the first response (for example, "randomized_device_token": "123456789123456789"). Then send it on subsequent requests. |
| event_data.transaction_id | String | Your ID for the event's transaction. |
| event_data.currency | String (enum) | [ISO-4217](https://en.wikipedia.org/wiki/ISO_4217) currency codes only |
| event_data.revenue | Double / float | The revenue amount of the transaction. |
| retryNumber | Integer | Default to 0. If retrying a request, set this to 1 (first retry) or 2 (second retry). |

### Conversion event platform-specific key values examples

**MAC_OS**

- user_data.os: MAC_OS
- user_data.environment: DESKTOP_APP
- id: MAC address (Media Access Control)

  - example: `"mac_address" : "88:66:5a:2f:81:fa"`

**WINDOWS**

- user_data.os: WINDOWS
- user_data.environment: DESKTOP_APP
- user_data.advertising_ids: windows_advertising_id

  - example: `"windows_advertising_id": "ea31e5e0-1aa5-4181-91d7-0b56524e0274"`
- id: MAC address (Media Access Control)

  - example: `"mac_address" : "00:1A:C2:7B:00:47"`

**ROKU**

- user_data.os: ROKU
- user_data.environment: TV_APP
- user_data.advertising_ids: roku_rida

  - example: `"roku_rida": "ea31e5e0-1aa5-4181-91d7-0b56524e0274"`

**SAMSUNG**

- user_data.os: TIZEN
- user_data.environment: TV_APP
- user_data.advertising_ids: samsung_ifa

  - example: `"samsung_ifa": "ea31e5e0-1aa5-4181-91d7-0b56524e0274"`

**LG**

- user_data.os: WEBOS
- user_data.environment: TV_APP
- user_data.advertising_ids: lg_ifa

  - example: `"lg_ifa": "ea31e5e0-1aa5-4181-91d7-0b56524e0274"`

**XBOX**

- user_data.os: XBOX
- user_data.environment: TV_APP
- user_data.advertising_ids: xbox_msai

  - example: `"xbox_msai": "ea31e5e0-1aa5-4181-91d7-0b56524e0274"`

## Sample request

```curl
curl -d '{
  "name": "PURCHASE",
  "customer_event_alias": "purchase 5 tokens",
  "branch_key": "key_live_00000000000000",
  "user_data": {
    "developer_identity": "user123",
    "app_version": "1.0.1",
    "os": "ROKU",
    "os_version": "10.0",
    "brand": "Roku",
    "model": "4200X",
    "sdk": "roku",
    "sdk_version": "1.0.0",
    "screen_height": 1334,
    "screen_width": 750,
    "environment": "TV_APP",
    "limit_ad_tracking": false,
    "advertising_ids": {
      "roku_rida": "00000000-0000-0000-0000-000000000123"
    },
    "randomized_device_token": "123456789123456789"
  },
  "event_data": {
    "transaction_id": "foobar",
    "currency": "USD",
    "revenue": 100
  },
  "retryNumber": 0
}' "https://api2.branch.io/v2/event/standard"
```

## Example response

You do not need to examine the response body. Look for a 200 HTTP status code. Non-2xx status codes indicate an error.
