Skip to main content

When to use CTV impressions

A TV ad has no click, and a TV’s advertising ID never equals the phone’s GAID or IDFA. The signal a TV and a phone share is the household’s public IP address. Use this endpoint when your ads play on connected TVs (smart TVs, streaming sticks, set-top boxes, game consoles) and the app installs happen on a phone in the same home. Your server reports each CTV impression to Linkrunner with the device IP and user agent. If a phone on the same IP address installs the app within the view-through window and nothing else can be credited, Linkrunner credits the install to your impression. This is CTV view-through attribution. It accepts AppsFlyer’s CTV parameter names. If your impressions carry the phone’s GAID or IDFA, use S2S impressions instead. They are matched on the device ID and rank above CTV impressions.
CTV is off by default. Three things must be on for your partner account on each app, and the advertiser turns on all three. In Integrations → Affiliate Partners → Configure, they turn on S2S traffic and then the Connected TV (CTV) impressions switch under it (see these steps). In Settings → Attribution Windows, they turn on view-through and set its window (see View-through attribution). Until then, requests are rejected with partner_not_enabled, view_through_disabled or ctv_not_enabled.

How it works

A CTV match is probabilistic: the same IP address suggests the same household, but does not prove the same person saw the ad. Linkrunner credits a CTV impression only when all of these hold: Postbacks work as for clicks. Your postback templates, event mapping and postback logs apply unchanged, and {touch_type} is impression for CTV installs. In the campaign table, CTV installs count as installs and as View Through Attribution installs. Accepted impressions appear in the Impressions column. See See your results.

Set it up

1

Get your S2S token

If you already send S2S clicks or S2S impressions, use the same token and skip this step.Otherwise, in your affiliate dashboard, open Settings → S2S Credentials and click Generate token. Copy the token (it starts with lrs2s_) and store it as a secret on your server. It is shown only once. One token covers every app you work with.S2S Credentials with the Generate token button
2

Open the advertiser's app

Pick the advertiser’s app in the switcher at the top left. Campaigns, and the CTV setting, are per app.The app switcher open, with the advertiser's app under Projects and your partner account below it
3

Create the campaign link

In All Campaigns, click Create Link, name the CTV campaign and click Create Campaign. See Create a campaign link for the other options.Create Campaign with a CTV campaign name filled inCopy the Template URL from the confirmation.Campaign Created with the Template URL and its copy buttonIt is a tracking link like this:
4

Turn it into the CTV impression URL

Keep your parameters, and send them to https://s2s.linkrunner.io/v1/ctv/impression/<app_id>. <app_id> is the app’s Android package name (com.example.app) or App Store ID (id1234567890). Either one finds the same app, and its Android and iOS installs are both matched.Then add the TV’s IP address (ip) and user agent (ua), both required, and the time of the impression. Your token goes in the X-Linkrunner-Token header:
ip must be the TV’s public IP address, not your ad server’s. With server-side ad insertion, send the value of the X-Device-IP header your ad server received. Do the same for ua with X-Device-User-Agent.tid is your ID for this impression. Use a value that is unique per impression.
You can name the advertiser by the tracking link’s domain instead: https://s2s.linkrunner.io/v1/ctv/impression?d=app.example.com&c=.... Use d if the advertiser’s test and live apps share an app ID and the same campaign code.
5

Fire it from your server when the ad plays

Replace your macros and call the URL with GET and the token header when the impression happens. A 200 with "status":"accepted" means the impression is recorded. See retries for the other responses.
6

Test it end to end

Send one impression with the public IP address of a test home network. On a phone connected to that Wi-Fi, without tapping any ad, install and open the app within the window. The install postback arrives with your tid and {touch_type} = impression. Check it in Postback logs.
Send each impression as it happens. An impression that arrives after the install can’t be credited, and impressions older than 24 hours are rejected.

See your results

The Impressions column is off by default. Turn it on once for each app and it stays on.
1

Open Edit Columns

In your affiliate dashboard, open All Campaigns and click the columns icon at the right of the toolbar, below Create Link.The Edit Columns icon at the right of the campaign toolbar, below Create Link
2

Turn on Impressions

Tick Impressions and click Save. Keep View Through Attribution ticked as well.Edit Columns with Impressions ticked and the Save button at the top
3

Read your CTV campaigns

Each CTV campaign shows its accepted impressions, and the installs credited to them under Installs and View Through Attribution. A TV-only campaign has no clicks.Campaign table with Impressions, Installs and View Through Attribution for two CTV campaigns and one click campaignA new campaign can show impressions before its first install. Installs count on the day they happen, so a household that saw the ad late at night can install the next day.A TV impression belongs to neither Android nor iOS, so a view filtered to one platform leaves CTV impressions out and still shows that platform’s credited installs. Clear the platform filter to see a campaign’s impressions.

Authenticate your requests

CTV impressions use the same partner token as S2S impressions. Send it in the X-Linkrunner-Token header, or as the lr_token query parameter if your ad server can only fire a URL. A request without a valid token is rejected with 401 and missing_token or invalid_token.

Coming from AppsFlyer

If you already send cross-platform CTV impressions to AppsFlyer, you can reuse that template. You change the host and c, add a unique tid, and add your token. An AppsFlyer template like this:
becomes:

Retries

Retrying is safe. The same tid for the same campaign always returns the same impression_id and is stored once.
  • Retry 429 and 503, after the Retry-After delay.
  • Don’t retry other 4xx responses. Fix the request instead. The reason tells you what’s wrong.
See the CTV Impression API reference for every parameter, response and rejection reason.

Troubleshooting

Requests return missing_ip or invalid_ip. Every CTV impression needs the TV’s public IP address in ip. Private addresses (192.168.x.x, 10.x.x.x), carrier-grade NAT addresses (100.64.0.0/10) and loopback addresses are rejected. Requests return datacenter_ip. The ip belongs to a cloud or hosting provider, which usually means your ad server sent its own address. Send the device IP your ad server received, for example from X-Device-IP. Requests return missing_ua. Send the TV’s user agent in ua. Requests return partner_not_enabled, view_through_disabled or ctv_not_enabled. S2S traffic, view-through or CTV is not on for your partner account on this app. Ask the advertiser to turn it on. They turn on S2S traffic and CTV in Integrations → Affiliate Partners → Configure (these steps), and view-through in Settings → Attribution Windows (how). Changes take up to 5 minutes to apply. Impressions are accepted but installs aren’t credited to them. Check that the impression carries the TV’s real public IP address and arrives before the install, and that the phone installed over the same home Wi-Fi. A click from any source, a device-ID impression, or a more recent impression takes priority. The install must also fall inside the view-through window the advertiser set for you. Need help? Contact support@linkrunner.io