diff --git a/ad-networks/dsps.mdx b/ad-networks/dsps.mdx
new file mode 100644
index 0000000..72832c3
--- /dev/null
+++ b/ad-networks/dsps.mdx
@@ -0,0 +1,345 @@
+---
+title: "DSP Sources"
+sidebarTitle: "DSPs"
+description: "Count the impressions of your Samsung Ads, The Trade Desk and Google DV360 line items in Linkrunner, count Samsung Ads clicks, and credit installs where the DSP shares a device ID or a household IP"
+icon: "rectangle-ad"
+keywords: ["dsp", "dsp sources", "samsung ads", "samsung dsp", "the trade desk", "ttd", "google dv360", "display and video 360", "impression tracking", "third party impression tag", "click tracking", "third party click tag", "samsung ads click tag", "view-through attribution", "ctv attribution", "connected tv", "programmatic"]
+---
+
+## Overview
+
+If you buy ads through a demand-side platform (DSP), you paste one Linkrunner impression tag into the DSP. Each time the DSP shows an ad, it calls the tag, and Linkrunner:
+
+- **Counts the impression** under that DSP. The DSP appears as its own channel, and each line item you run creates its own campaign the first time it reports an impression.
+- **Credits installs, where the DSP shares enough to match.** If the DSP passes a device ID or the viewer's household IP address, Linkrunner can credit a later install to the impression with [view-through attribution](/features/attribution-windows#view-through-attribution). If it passes neither, the impressions are only counted.
+
+For Samsung Ads you can also paste a [click tag](#samsung-ads-click-tag). Linkrunner then records each click on the same campaign and matches installs to it by device ID, like any other click.
+
+
+ This integration brings in impressions, Samsung Ads clicks and, where possible, installs. It does not sync your spend from the DSP and does not send postbacks to the DSP.
+
+
+
+ Amazon DSP is not supported. Amazon only accepts measurement tags from its certified partners, so a Linkrunner tag cannot be added to an Amazon DSP campaign. Other DSPs cannot be set up yet.
+
+
+## What you need
+
+- The **Admin** or **Manager** role in your Linkrunner project to set up, change, rotate or remove a DSP. Members can view the page.
+- Access to the DSP account where you can edit the creatives of the line items you want to measure.
+- [View-through attribution](/features/attribution-windows#view-through-attribution) turned on, if you want installs credited. Counting impressions does not need it.
+
+## Set up a DSP
+
+
+
+ Go to [Integrations → DSPs](https://dashboard.linkrunner.io/dashboard/integrations/dsps), find the card for your DSP and click **Set up**. Linkrunner creates a key for that DSP in this project and shows the ready-to-paste tag.
+
+
+ Click the copy button next to the tag. The tag already contains your key and your DSP's macros. Paste it exactly as copied, because the DSP replaces the macros when it fires the tag.
+
+
+ Add the tag to your creatives as an impression tracker. The exact field is different in each DSP, see [Samsung Ads](#samsung-ads), [The Trade Desk](#the-trade-desk) and [Google DV360](#google-dv360).
+
+
+ On the card, turn on view-through and choose a window from 1 to 24 hours. For Samsung Ads, also turn on the CTV switch. See [View-through, CTV and Clicks switches](#view-through-ctv-and-clicks-switches).
+
+
+ If you want to send Samsung Ads clicks, turn on the **Clicks** switch on the card, copy the click tag that appears and paste it into your creatives. See [Samsung Ads click tag](#samsung-ads-click-tag). Clicks are off by default.
+
+
+ After the DSP serves its first impression for a line item, a campaign for it appears in the [Campaigns table](https://dashboard.linkrunner.io/dashboard/campaigns) and the DSP appears in Channels. The card shows how many campaigns were created and when the last one appeared, with a link to the Campaigns table filtered to that DSP.
+
+
+
+The **Impressions** column in the Campaigns table is off by default. Turn it on with **Edit Columns**, as described in [CTV attribution](/features/ctv-attribution#see-your-results). Installs credited from an impression appear as **View Through Attribution** installs.
+
+## The impression tag
+
+Every DSP uses the same URL shape. Only the macros after each `=` sign change from DSP to DSP, and the dashboard fills them in for you. The tag is a plain `GET` request:
+
+```text wrap
+https://s2s.linkrunner.io/v1/impression?lr_key=&li=&li_name=&tid=&gaid=&idfa=&ip=&ua=&impression_time=
+```
+
+Use `/v1/impression` when the DSP can share a device ID or nothing at all. Use `/v1/ctv/impression` when the DSP shares the household IP of a connected TV. The dashboard picks the right one for each DSP. Only `lr_key` is required, and a DSP sends only the fields it has a macro for.
+
+| Parameter | What to send |
+| --- | --- |
+| `lr_key` | Your key for this DSP in this project. It starts with `lrdsp_`. It tells Linkrunner which project and which DSP the impression is for. Required. |
+| `li` | The DSP's line item or campaign ID, at the level shown in [How campaigns are created](#how-campaigns-are-created). Each distinct value becomes one Linkrunner campaign. If the tag sends none, or the DSP leaves the macro unfilled, all impressions go to a single campaign for that DSP. |
+| `li_name` | The DSP's name for the line item or campaign, used in the Linkrunner campaign name. Optional. |
+| `tid` | The DSP's unique ID for this impression. Linkrunner records the same `tid` for the same line item once, so a retried call is not counted twice. Optional, but without it every call is counted as a new impression. |
+| `gaid`, `idfa` | The device's Google Advertising ID (Android) or IDFA (iOS), as a UUID. Used to match installs. Read only on `/v1/impression`. Without a usable one, the impression is counted but cannot be matched. |
+| `ip` | The public IP address of the device or TV. On `/v1/ctv/impression` it is required and it is what installs are matched on. On `/v1/impression` it is not used for matching. |
+| `ua` | The user agent of the device or TV. Optional. Stored with the impression and not used for matching. |
+| `impression_time` | When the impression happened, as a Unix timestamp in seconds or milliseconds. Optional. Linkrunner uses the time of the call when it is missing or unusable. |
+
+Each value can be up to 256 characters. The [S2S Impression API](/api-reference/s2s-impressions) and [CTV Impression API](/api-reference/ctv-impressions) list the other parameters, such as `vt_lookback`, which shortens the view-through window for one impression.
+
+## How campaigns are created
+
+You do not create campaigns for a DSP. The first time a new `li` value reports an impression, Linkrunner creates a campaign for it under that DSP and keeps counting its later impressions there. Clicks from the [Samsung Ads click tag](#samsung-ads-click-tag) use the same rule, so the clicks and impressions of one line item are on one campaign.
+
+- **Name:** ` - `. When the tag sends no name, the line item ID takes its place. The Trade Desk and Google DV360 tags send no name, so their campaigns are named after the ID.
+- **One campaign per `li` value.** The tags use each DSP's own level: a Samsung Ads campaign, a Trade Desk campaign, or a DV360 line item. Linkrunner uses the `li` value as the identity. Characters other than letters, digits, `.`, `_`, `:` and `-` are replaced with `_`, and a value longer than 64 characters is shortened.
+- **Limits:** Linkrunner creates at most 100 new DSP campaigns per day, and at most 1000 campaigns per DSP in a project. When a new line item would go over a limit, no campaign is created and its impressions and clicks are not recorded. Impressions and clicks of campaigns that already exist keep counting.
+- **Timing:** the campaign is created when Linkrunner processes the first impression, not at the moment the DSP fires the tag, so it can appear a little after the first delivery.
+
+## Tags for each DSP
+
+The tags below are what the dashboard shows, with a placeholder for the key. Copy the tag from the dashboard so your own key is already in it.
+
+### Samsung Ads
+
+```text wrap
+https://s2s.linkrunner.io/v1/ctv/impression?lr_key=&li=__CAMPAIGN_ID__&li_name=__CAMPAIGN_NAME_ENCODED__&tid=__TXN_ID__&ip=__IP__&ua=__USER_AGENT__&impression_time=__TIMESTAMP__
+```
+
+**Where to paste it:** in Samsung DSP, add the tag to your creatives in the **Impression trackers** field. Samsung's [macro list](https://help.dsp.samsungads.com/docs/macros) says its macros work in third-party trackers and in impression tracker URLs. Do not use it as an ad server tag or a VAST URL, because Samsung only authorizes tags and VAST URLs from accredited third-party vendors there.
+
+**What it can do:** counts impressions and matches installs by household IP. Samsung does not share a device ID in this tag, so there is no device ID match. Linkrunner credits an install when the phone installs from the same public IP address as the TV, inside the view-through window. See [how much to trust household matching](/features/ctv-attribution#how-much-to-trust-it).
+
+| Parameter | Samsung macro |
+| --- | --- |
+| `li` | `__CAMPAIGN_ID__`, the Samsung campaign ID |
+| `li_name` | `__CAMPAIGN_NAME_ENCODED__`, the campaign name in the URL-encoded form Samsung documents for names |
+| `tid` | `__TXN_ID__`, Samsung's unique ID for the impression |
+| `ip` | `__IP__`, the IP address of the viewer's device |
+| `ua` | `__USER_AGENT__` |
+| `impression_time` | `__TIMESTAMP__`, in seconds |
+
+**Limits to know about:**
+
+- This tag needs both the **CTV switch** and **view-through** on. Otherwise Linkrunner rejects it and the impression is not counted.
+- Samsung documents that, in countries under the GDPR, `__IP__` "can only be added to trackers from Samsung certified vendors". Without the IP, Linkrunner rejects the impression with `missing_ip`, because there is nothing to match. If you deliver in GDPR countries, ask your Samsung Ads contact whether this tracker can receive `__IP__`.
+- `__USER_AGENT__` appears in Samsung's AppsFlyer integration guide, but Samsung does not list it in its macro table. It is optional here. If Samsung leaves it unfilled, Linkrunner ignores it and still accepts the impression.
+- Samsung does not document whether it fires a tracker from the TV or from its own servers. Linkrunner matches on the `ip` value from the macro only, never on the address of the connection that fired the tag.
+
+### Samsung Ads click tag
+
+Turn on the **Clicks** switch on the Samsung Ads card, then copy the click tag from the card. The tag is a plain `GET` request:
+
+```text wrap
+https://s2s.linkrunner.io/v1/click?lr_key=&li=__CAMPAIGN_ID__&li_name=__CAMPAIGN_NAME_ENCODED__&tid=__TXN_ID__&sha1_advertising_id=__GAID_ID_SHA1__&click_time=__TIMESTAMP__
+```
+
+**Where to paste it:** in Samsung DSP, add the tag to your creatives as a click tracker. Samsung's [macro list](https://help.dsp.samsungads.com/docs/macros) says its macros work in third-party trackers. Paste the tag exactly as copied, with the macros as they are, because Samsung replaces them when it fires the tag.
+
+**What it can do:** records each click on the same campaign as the impressions of that line item, and matches a later install to the click by device ID. The tag does not redirect anyone, so use it only as a tracker.
+
+| Parameter | Samsung macro |
+| --- | --- |
+| `li` | `__CAMPAIGN_ID__`, the Samsung campaign ID. Clicks and impressions with the same value go to the same campaign. |
+| `li_name` | `__CAMPAIGN_NAME_ENCODED__`, the campaign name in the URL-encoded form Samsung documents for names |
+| `tid` | `__TXN_ID__`, Samsung's unique ID for the click. Linkrunner records the same `tid` for the same line item once, so a retried call is not counted twice. Without it, every call is a new click. |
+| `sha1_advertising_id` | `__GAID_ID_SHA1__`, the SHA-1 hash of the device's advertising ID, as 40 hexadecimal characters |
+| `click_time` | `__TIMESTAMP__`, in seconds |
+
+The click endpoint also reads `gaid` and `idfa`, as UUIDs, if your DSP can send an unhashed advertising ID, and an optional `ua`. The Samsung tag uses none of them, because no Samsung click tracker in Samsung's guides carries a user agent. Each value can be up to 256 characters. The [S2S Click API](/api-reference/s2s-clicks#dsp-mode-lr_key) lists the response codes.
+
+**Rules to know about:**
+
+- **A click must carry a device ID.** At least one of `sha1_advertising_id`, `gaid` or `idfa` must be filled. A click with only an IP address is rejected with `missing_device_id`, and Linkrunner matches DSP clicks by device ID only.
+- **Unfilled macros are dropped.** A value that is empty or still a literal macro such as `__GAID_ID_SHA1__` is ignored. If that leaves no device ID, the click is rejected.
+- **The Clicks switch must be on.** It is off by default and is separate from the CTV switch and from view-through. With it off, Linkrunner rejects the tag with `clicks_disabled`. See [View-through, CTV and Clicks switches](#view-through-ctv-and-clicks-switches).
+- **Clicks and impressions share one campaign.** A click and an impression with the same `li` value are on the same campaign. The same [limits](#how-campaigns-are-created) apply to clicks, and a click for a line item that would go over a limit is not recorded.
+- **A click wins over an impression.** When an install could be credited to a click or to an impression, Linkrunner credits the click.
+
+**Samsung caveats:**
+
+- Samsung documents that in countries under the GDPR it fills device IDs only for trackers from Samsung certified vendors. If Samsung leaves the device ID macro unfilled, Linkrunner rejects the click with `missing_device_id`. If you deliver in GDPR countries, ask your Samsung Ads contact whether this tracker can receive device IDs.
+- `__GAID_ID_SHA1__` appears in the mobile click link of Samsung's [Adjust guide](https://help.dsp.samsungads.com/docs/mmp-configuration-with-adjust), but Samsung does not list it in its macro table. Confirm with your Samsung Ads contact that it is filled for your account.
+
+### The Trade Desk
+
+```text wrap
+https://s2s.linkrunner.io/v1/impression?lr_key=&li=%%TTD_CAMPAIGNID%%&tid=%%TTD_IMPRESSIONID%%&gaid=%%TTD_DEVICEID%%&idfa=%%TTD_DEVICEID%%
+```
+
+**Where to paste it:** on the creative, in its tracking settings. For display, HTML5 and native creatives, paste it as the **1x1 Pixel Impression Tracking URL**. For video and audio creatives, add it as a **Third-Party Tracking URL** with the event type **Impression**. These field names come from measurement partners' guides, so check them against your own Trade Desk account.
+
+**What it can do:** counts impressions and matches installs by device ID, on mobile in-app inventory. Linkrunner credits an install when the installing device has the same advertising ID as the impression, inside the view-through window.
+
+| Parameter | Trade Desk macro |
+| --- | --- |
+| `li` | `%%TTD_CAMPAIGNID%%`, the Trade Desk campaign ID |
+| `tid` | `%%TTD_IMPRESSIONID%%`, the Trade Desk impression ID |
+| `gaid`, `idfa` | `%%TTD_DEVICEID%%` in both, see below |
+
+**Limits to know about:**
+
+- The Trade Desk sends one device ID macro for both platforms and does not say which kind it holds, so the tag passes it as both `gaid` and `idfa`. Linkrunner checks that the value is a valid device ID and keeps it. An Android install looks up only a GAID and an iOS install only an IDFA, so the copy of the wrong platform never matches.
+- The Trade Desk does not publicly document a macro for IP address, user agent, time or connected TV device IDs. So connected TV impressions are counted but not matched to installs, and Linkrunner uses the time of the call as the impression time.
+- When the Trade Desk has no device ID for an impression, the macro is left unfilled and the impression is counted only.
+- There is no click tag for The Trade Desk. Its documents do not publish a click macro, so Linkrunner does not offer one yet.
+- The Trade Desk's own macro reference needs a Trade Desk login. The macros above are the ones its measurement partners document, for example [Kochava](https://support.kochava.com/articles/campaign-management/37531-create-the-trade-desk-campaign), so confirm them with your Trade Desk contact before launch.
+
+### Google DV360
+
+```text wrap
+https://s2s.linkrunner.io/v1/impression?lr_key=&li=${CAMPAIGN_ID}&tid=${IMPRESSION_ID}
+```
+
+**Where to paste it:** add it to your creatives as a third-party impression tracking URL, as described in Google's [macros help](https://support.google.com/displayvideo/answer/2789508).
+
+**What it can do:** counts impressions only. Display & Video 360 does not document a macro for a device ID, IP address, user agent or time, so Linkrunner cannot match an install to a DV360 impression.
+
+| Parameter | DV360 macro |
+| --- | --- |
+| `li` | `${CAMPAIGN_ID}`, which DV360 uses for the line item ID, so each DV360 line item becomes one Linkrunner campaign |
+| `tid` | `${IMPRESSION_ID}` |
+
+**Limits to know about:**
+
+- The URL must start with `https`. The Linkrunner tag does.
+- DV360 treats the tag as part of the creative, so it goes through creative review and must follow Google's, the exchange's and the publisher's policies.
+- You cannot use the tag in YouTube or VAST reservations. For those, Google allows only Display & Video 360 or Campaign Manager 360 tracking pixels. Google also says macros are not supported in YouTube ads or data-driven creatives.
+- Turning view-through on or off changes nothing for DV360, because there is nothing to match.
+- There is no click tag for DV360. Its documents do not publish a click macro, so Linkrunner does not offer one yet.
+
+## View-through, CTV and Clicks switches
+
+Linkrunner matches an install to a DSP impression only when view-through is on for that DSP. You set it on the DSP's card, with a window from 1 to 24 hours. Changes can take up to 5 minutes to apply.
+
+The **Clicks** switch is separate. It controls only the click tag, it is off by default, and it does not need the CTV switch or view-through. It appears on the cards of DSPs that have a click tag, which is Samsung Ads today.
+
+| Tag | Switches it needs | When one is off |
+| --- | --- | --- |
+| `/v1/impression` (The Trade Desk, Google DV360) | View-through, to credit installs | The impression is still counted. Its device IDs are dropped, so it cannot be matched. |
+| `/v1/ctv/impression` (Samsung Ads) | The **CTV switch** and view-through | Linkrunner rejects the impression, with `ctv_not_enabled` or `view_through_disabled`, and does not count it. |
+| `/v1/click` (Samsung Ads) | The **Clicks** switch | Linkrunner rejects the click with `clicks_disabled` and does not record it. |
+
+- **Impressions are counted either way** on `/v1/impression`. Turn view-through on to also credit installs.
+- **Device IDs are not kept while view-through is off.** Turning it on later does not credit impressions that arrived earlier.
+- **Clicks win.** A click, including a DSP click, beats an impression. The same rules as for affiliate impressions apply: an impression is credited only when no click from any source can be credited, the most recent impression inside the window wins, and each impression is credited to at most one install. See [View-through attribution](/features/attribution-windows#view-through-attribution).
+- **CTV matching is probabilistic.** It rests on the home's shared public IP address and skips shared networks. See [CTV attribution](/features/ctv-attribution#how-much-to-trust-it).
+
+## Count-only impressions and missing macros
+
+Ad servers fire impression tags and nobody reads the answer, so Linkrunner is lenient. A value that is empty, still a literal macro such as `%%TTD_DEVICEID%%` or `__IP__`, or not usable is ignored. The impression is still counted.
+
+| What the DSP sends | What Linkrunner does |
+| --- | --- |
+| No usable `gaid` or `idfa` | Counts the impression only. It is never stored as something an install can match. |
+| No `li`, or `li` unfilled | Uses one campaign for the DSP, with the reference `default`. |
+| `li_name` unfilled | Names the campaign after the line item ID. |
+| No `tid`, or `tid` unfilled | Counts every call as a new impression. |
+| `ua` or `impression_time` unfilled or unusable | Ignores the value. The time of the call is the impression time. |
+
+Linkrunner still rejects a call with a missing or unknown key, a value over 256 characters, and, on `/v1/ctv/impression`, a missing or non-public `ip`. A connected TV impression without its household IP cannot be matched, so it is not counted.
+
+The click tag is stricter. It drops unfilled macros the same way, but a click with no usable `sha1_advertising_id`, `gaid` or `idfa` is rejected with `missing_device_id`, because a click that cannot be matched to a device is never recorded.
+
+## Rotate or remove a key
+
+On the DSP's card:
+
+- **Rotate key:** Linkrunner creates a new key and revokes the old one. The old tag stops working within a minute and its impressions and clicks are rejected with `invalid_key`. Paste the new tag into the DSP right after you rotate, because impressions and clicks fired in between are not recorded. The new key keeps the Clicks switch setting of the old one.
+- **Remove:** Linkrunner revokes the key. The tag stops working within a minute. Campaigns and history stay in your reports. Setting the DSP up again creates a new key.
+
+Each DSP has one live key per project. Only Admins and Managers can rotate or remove it.
+
+### Security
+
+The key is part of the tag, so anyone who can read the tag can read the key. It is an identifier, not a password. It can only record impressions, and clicks while the Clicks switch is on, for that one DSP in that one project. It cannot read your data or change settings.
+
+Someone who has the key can still send impressions the DSP never served. They count in your reports and, with view-through on, can take credit for installs that would otherwise be organic. The same is true of clicks, which is why the Clicks switch is off by default and a click must carry a device ID: a click beats an impression, and a click with no device ID is never recorded. Turn the Clicks switch on only when you are ready to paste the click tag. If you see unexpected impressions or clicks, or the tag was shared more widely than you intended, rotate the key, and turn Clicks off if you no longer send click tags.
+
+## Responses and reasons
+
+The tag answers with JSON. You see the answer only when you call the tag yourself, or when your DSP logs tracker responses.
+
+```json
+{ "status": "accepted", "impression_id": "dfa5b5ed-54c2-5f5b-bc48-2385c336fed8" }
+```
+
+A click answers with `click_id` instead:
+
+```json
+{ "status": "accepted", "click_id": "42c0d258-11c3-5692-a85f-b87931249e82" }
+```
+
+```json
+{ "status": "rejected", "reason": "invalid_key" }
+```
+
+| Status | Reason | Meaning |
+| --- | --- | --- |
+| 200 | | Impression or click accepted. An impression may be count-only. |
+| 400 | `missing_device_id` | Click tag only. No usable `sha1_advertising_id`, `gaid` or `idfa` was sent, so the click is refused. |
+| 400 | `missing_ip`, `invalid_ip`, `datacenter_ip` | CTV tag only. The IP is missing, not public, or belongs to a cloud or hosting provider. |
+| 400 | `value_too_long` | A value is longer than 256 characters. |
+| 401 | `missing_key` | `lr_key` is in the URL but empty. Impression and click tags. |
+| 401 | `invalid_key` | The key is wrong, was rotated out, or was removed. Impression and click tags. |
+| 403 | `ctv_not_enabled` | CTV tag only. The CTV switch is off for this DSP. |
+| 403 | `view_through_disabled` | CTV tag only. View-through is off for this DSP. |
+| 403 | `clicks_disabled` | Click tag only. The Clicks switch is off for this DSP. |
+| 429 | `rate_limited` | The key sent too many impressions per second. Retry after a short delay. |
+| 429 | `rate_limited` | Click tag only. The key sent too many clicks per second. Clicks and impressions are limited separately. Retry after a short delay. |
+| 503 | `unavailable` | A temporary error. Retry after a short delay. |
+
+A request with no `lr_key` at all is not a DSP request. Linkrunner answers it as an affiliate partner request, with that flow's errors, such as `missing_token`. The [S2S Impression API](/api-reference/s2s-impressions), [CTV Impression API](/api-reference/ctv-impressions) and [S2S Click API](/api-reference/s2s-clicks) describe those.
+
+## Check the tag yourself
+
+To check the key before you launch, call the tag with a test line item:
+
+```bash
+curl "https://s2s.linkrunner.io/v1/impression?lr_key=&li=test-line-item&li_name=Test%20line%20item&tid=test-0001"
+```
+
+A response with `"status":"accepted"` means the key works. The call creates a campaign for `test-line-item`, which counts toward the [limits](#how-campaigns-are-created), so use a value you are happy to see in your Campaigns table.
+
+## Troubleshooting
+
+
+
+ Check, in order:
+
+ - The line item is serving. The DSP fires the tag only when it shows an ad, and your creatives must have passed the DSP's review.
+ - The tag in the creative matches the one on the card, with your key. A key set up in the last minute may not be active yet.
+ - The key was not rotated or removed. A tag with a stale key is rejected with `invalid_key`.
+ - For Samsung Ads, the CTV switch and view-through are both on, and `__IP__` is filled. Otherwise the impression is rejected and not counted. For the click tag, the Clicks switch is on and a device ID is filled.
+ - You have not reached a [limit](#how-campaigns-are-created) of 100 new campaigns per day or 1000 per DSP.
+ - For DV360, the creative is not in a YouTube or VAST reservation.
+
+ Then look in the Campaigns table. The campaign appears a little after the first impression, and the **Impressions** column is off by default.
+
+
+ Check, in order:
+
+ - The DSP can match. Google DV360 only counts. The Trade Desk matches mobile in-app impressions that carry a device ID. Samsung Ads matches on household IP.
+ - View-through was on when the impression arrived. Device IDs are not kept while it is off.
+ - The impression came before the install, and the install is inside the view-through window.
+ - No click from any source could be credited instead, because clicks always win. This includes clicks sent with the Samsung Ads click tag.
+ - For Samsung Ads, the phone installed on the same home Wi-Fi as the TV, and the home IP address did not trigger the shared-network limit. See [CTV attribution](/features/ctv-attribution#how-much-to-trust-it).
+ - For The Trade Desk, the macro was filled. An unfilled device ID makes the impression count-only.
+
+
+ `missing_key` means the URL has `lr_key=` with no value. `invalid_key` means the key is wrong, was rotated out, or was removed. Copy the current tag from the card. If you rotated the key, update every creative that still has the old tag.
+
+
+ This only happens on the Samsung Ads tag. Turn on the CTV switch and view-through on the DSP's card, wait up to 5 minutes and let the DSP fire the tag again.
+
+
+ Samsung did not fill `__IP__`. Samsung documents that in GDPR countries this macro can only be added to trackers from Samsung certified vendors, so ask your Samsung Ads contact whether this tracker can receive it. Samsung Ads impressions without an IP address cannot be matched, so Linkrunner does not count them.
+
+
+ The **Clicks** switch is off. Turn it on, on the Samsung Ads card, and let Samsung fire the tag again. Clicks are off by default and do not depend on the CTV switch or view-through.
+
+
+ The click had no usable device ID. Samsung did not fill `__GAID_ID_SHA1__`, or the macro reached Linkrunner as literal text. Samsung documents that in GDPR countries it fills device IDs only for trackers from Samsung certified vendors, so ask your Samsung Ads contact whether this tracker can receive them. A click with only an IP address is never recorded.
+
+
+ The tag only sends a name when the DSP has a name macro. Samsung Ads sends one. The Trade Desk and Google DV360 tags send none, so their campaigns are named after the line item ID.
+
+
+ Linkrunner counts the tag calls it received and accepted. Calls that were rejected are not counted, and retries with the same `tid` count once. A tag that was never fired, for example for a creative that did not pass review, cannot be counted either. Check the reasons in [Responses and reasons](#responses-and-reasons).
+
+
+ Not yet. Only Samsung Ads, The Trade Desk and Google DV360 can be set up. Amazon DSP only accepts measurement tags from its certified partners, so it cannot fire a Linkrunner tag. Contact support if you want another DSP.
+
+
+
+**Need help?** Contact [support@linkrunner.io](mailto:support@linkrunner.io)
diff --git a/ad-networks/google-tv-campaigns.mdx b/ad-networks/google-tv-campaigns.mdx
new file mode 100644
index 0000000..2bd2c0e
--- /dev/null
+++ b/ad-networks/google-tv-campaigns.mdx
@@ -0,0 +1,122 @@
+---
+title: "Run Google Ads on connected TV"
+sidebarTitle: "Google TV campaigns"
+description: "Create a Google Ads campaign that runs on TV screens, see its results in Linkrunner, and credit installs from viewers who scan the TV QR code."
+keywords: ["google tv", "google ads connected tv", "youtube ctv", "google ads tv screens", "demand gen ctv", "ctv qr code", "connected tv campaign"]
+icon: "tv"
+---
+
+Google Ads shows your video ads on TV screens through YouTube. What Linkrunner can do with those ads depends on the campaign type you pick.
+
+| Campaign type | Linkrunner shows | Installs credited | Postbacks |
+| --- | --- | --- | --- |
+| Video (reach or views) | Google's TV impressions, clicks and spend | No | No |
+| Demand Gen, with a Linkrunner link as the Final URL | Google's TV impressions, clicks and spend | Yes, when a scan of the TV QR code or a tap reaches your link with Google's click parameters | Yes, as for any Google click |
+
+A TV ad has no click of its own. Only the Demand Gen route gives a viewer something to open on their phone.
+
+## Before you start
+
+- Connect your Google Ads account in [Integrations → Google Ads](https://dashboard.linkrunner.io/dashboard/integrations/google-ads). Follow [Google Ads](/ad-networks/google-ads) if you have not.
+- You need a YouTube video to use as the ad.
+- For the Demand Gen route, you also need a Linkrunner link for your app.
+
+## Option 1: Video campaign (reporting only)
+
+These steps follow the **Video views** goal. Google changes its screens often, so labels can differ slightly in your account.
+
+
+
+ In Google Ads, click **New campaign** and choose **YouTube reach, views and engagements**. Pick a goal such as **Video views** or **Reach**, then pick the **Video** campaign type and click **Continue**.
+
+
+ Enter a campaign name, choose the ad formats and bid strategy, and enter a budget and dates. Set **Locations** and **Languages** for the audience you want.
+
+
+ Open **Additional settings**, then **Devices**. **Show on all eligible devices** already includes TV screens.
+
+ To run on TV only, choose **Set specific targeting for devices**, clear **Computers**, **Mobile Phones** and **Tablets**, and keep **TV screens** selected.
+
+
+ Leave **Third-party measurement** as **None**. Linkrunner is not one of the measurement vendors Google offers there.
+
+
+ Create the ad group, add your YouTube video ad, and publish the campaign.
+
+
+
+## Option 2: Demand Gen campaign with a Linkrunner link
+
+Google can show a QR code on connected TVs for Demand Gen and Performance Max ads. The QR code opens the ad's Final URL on the viewer's phone. Google creates the code for you from the Final URL. QR codes appear only on connected TV, and not on YouTube TV or Google TV inventory. See [About QR codes for Connected TV](https://support.google.com/google-ads/answer/16903036).
+
+
+
+ In Google Ads, open **Admin → Account settings**, expand **Auto-tagging**, and check that **Tag the URL that people click through from my ad** is on. Linkrunner reads the click parameters Google adds to your URL, so the link must receive them.
+
+
+ Click **New campaign**, choose an objective such as **Website traffic**, then choose the **Demand Gen** campaign type and click **Continue**. Choose a campaign goal and set your budget.
+
+
+ In the ad group, the **Devices** setting defaults to all eligible devices, which includes TV screens. QR codes need TV screens included, so do not turn them off.
+
+
+ In the ad, choose **Video ad**, add your YouTube video, and fill in the headlines, descriptions and business name. Under **Final URL**, enter your Linkrunner link. That is the page the QR code opens.
+
+
+ To see the ad group and ad in Linkrunner, open **URL and other options** in the ad, or **Ad group URL options** in the ad group, and set **Final URL suffix** to:
+
+ ```
+ adset_id={adgroupid}&ad_id={creative}
+ ```
+
+ You can also set a **Tracking template** or **Final URL suffix** for the whole account in **Admin → Account settings**, under **Tracking**.
+
+
+ Publish the campaign. When it serves on a TV, scan the code with a phone and check that the click shows up in your Linkrunner campaigns.
+
+
+
+
+Google's documentation does not say which click parameters it adds to a scan of the TV QR code. Linkrunner credits the install when the click reaches your Linkrunner link with Google's click parameters, so check the first scans before you rely on the numbers.
+
+
+## See the results in Linkrunner
+
+Open the [Connected TV page](https://dashboard.linkrunner.io/dashboard/connected-tv) and scroll to **Google TV**. You see **Impressions**, **Clicks** and **Spend** from Google Ads, a daily trend, and one row per campaign. The section updates once a day. See [Google TV](/features/ctv-attribution#google-tv) for how the numbers are shown.
+
+Clicks on your Linkrunner link, and the installs they lead to, are counted in your campaign table, not in the Google TV section.
+
+## Installs and postbacks
+
+Linkrunner credits an install to a Google campaign in two ways:
+
+- **From a click.** The install is matched to a click on your Linkrunner link that carried Google's click ID. Linkrunner then sends postbacks to Google for that install's events, as for any other Google click. See [Google Ads](/ad-networks/google-ads) for the event setup.
+- **From Google.** Linkrunner asks Google Ads about installs that carry a Google click ID, or, on iOS, the on-device click context that [Google ICM](/features/google-icm) reads.
+
+A viewer who only watches the TV ad does neither. Nothing is left on their phone, Linkrunner receives no impression records for the ad, and Google does not accept third-party tracking pixels for YouTube. See [Third-party measurement on YouTube](https://support.google.com/google-ads/answer/9741375). That install is not credited to the Google campaign, and no postback is sent for it.
+
+The Google TV numbers are Google's own. They never change your CTV installs, conversion rate or revenue from [CTV attribution](/features/ctv-attribution).
+
+To credit installs from viewers who never scan or tap, have a partner report each TV impression from its server. See [CTV attribution](/features/ctv-attribution).
+
+## Troubleshooting
+
+
+
+ The section appears once your project has a connected Google Ads account and Linkrunner has collected connected TV data for it. Check the connection in [Integrations → Google Ads](https://dashboard.linkrunner.io/dashboard/integrations/google-ads), and look again after a day.
+
+
+ Check that the campaign has served on TV screens in the date range, and that it appears in your Linkrunner campaign list. Linkrunner shows only campaigns it has already synced from your Google Ads account.
+
+
+ Linkrunner updates Google TV once a day, so today's activity is missing. Spend is shown in your project currency, so it can differ from the amount in your Google Ads account currency.
+
+
+ Check that the ad's Final URL is your Linkrunner link, and that auto-tagging is on in **Admin → Account settings**. Without Google's click parameters on the URL, Linkrunner cannot tie the click to the Google campaign.
+
+
+ That is expected. A Video campaign has no click for Linkrunner to match. See [Installs and postbacks](#installs-and-postbacks).
+
+
+
+**Need help?** Contact [support@linkrunner.io](mailto:support@linkrunner.io)
diff --git a/ad-networks/roku-ads.mdx b/ad-networks/roku-ads.mdx
new file mode 100644
index 0000000..a206016
--- /dev/null
+++ b/ad-networks/roku-ads.mdx
@@ -0,0 +1,157 @@
+---
+title: "Roku Ads"
+description: "Connect your Roku Ads Manager account to see impressions and spend next to your installs in Linkrunner, and send your installs and in-app events back to Roku"
+icon: "tv"
+keywords: ["roku ads", "roku ads manager", "roku conversions api", "roku postbacks", "connected tv", "ctv spend", "ctv impressions", "streaming tv ads"]
+---
+
+## Overview
+
+Connect your Roku Ads Manager account and Linkrunner does two things for it:
+
+- **Reporting:** it syncs the impressions and spend of each Roku campaign, day by day. They appear in the Campaigns table, Channels and Home next to your installs, so you can compare what a Roku campaign cost with what it drove.
+- **Postbacks:** it sends your installs and in-app events to Roku through the Roku Conversions API, so Roku can measure and optimize the campaign. This is optional and set up separately, after the account is connected. See [Send conversions to Roku](#send-conversions-to-roku).
+
+
+ The reporting connection brings in Roku's **impressions and spend only**. Roku shares aggregate numbers, not the device behind each impression, so Linkrunner cannot credit an install to a Roku campaign from this connection. To count installs, send viewers to a Linkrunner link (for example a QR code or short URL in your ad) or use [CTV attribution](/features/ctv-attribution) with a partner that reports impressions.
+
+
+## What you need
+
+- A Roku Ads Manager ad account. Roku's API supports self-service accounts only, so accounts run through a Roku insertion order cannot be connected yet.
+- The **Admin** or **Member** role in your Linkrunner project. Agency users need the connect permission, and only Admins and Members can remove an account.
+- A currency and a timezone set on the Roku ad account. Linkrunner needs both to put spend on the right day and in the right currency.
+- For postbacks only: an **Event Group ID** and a **Conversions API key** from Roku Ads Manager. Only a Roku Organization Admin or Account Admin can generate the key.
+
+## Connect Roku Ads
+
+
+
+ Go to [Integrations](https://dashboard.linkrunner.io/dashboard/integrations) and open **Roku Ads**. You can also go straight to [Roku Ads](https://dashboard.linkrunner.io/dashboard/integrations/roku-ads).
+
+
+ Click **Connect Roku Ads**. A Roku window opens. Sign in with the Roku Ads Manager user that owns the ad account and approve access.
+
+
+ Back in Linkrunner, **Select Roku Ads accounts** lists every ad account you approved, with its currency and timezone. Tick the accounts to sync and click **Import**.
+
+
+
+An account that Roku reports without a supported currency or a timezone is listed but cannot be selected. Fix it in Roku Ads Manager and connect again.
+
+## What syncs
+
+- **When:** every 6 hours. The first sync of an account loads up to 13 months of history, and every later sync re-reads the last 14 days, so numbers Roku restates are picked up.
+- **What:** impressions and spend for each Roku campaign, for each day, in the ad account's timezone.
+- **Where:** each Roku campaign appears in the [Campaigns table](https://dashboard.linkrunner.io/dashboard/campaigns) under its Roku name. Spend is kept in the ad account's currency and shown in your project's currency on the Campaigns table.
+
+Roku can take several hours to report a day, so today's numbers are incomplete until later. A Roku campaign with no delivery has no rows until it starts serving.
+
+## Send conversions to Roku
+
+Postbacks send each install and the in-app events you choose to Roku, so Roku can match them to the people who saw your ads. Set them up once per connected Roku ad account.
+
+
+
+ In Roku Ads Manager, open the **Events** page. Copy the **Event Group ID**. Then choose **CAPI** and generate an API key. Copy the key right away, because Roku shows it only once. If you cannot generate a key, ask a Roku Organization Admin or Account Admin.
+
+
+ Open [Roku Ads](https://dashboard.linkrunner.io/dashboard/integrations/roku-ads) in Linkrunner. Next to your ad account, click **Set up postbacks**. Paste the Event Group ID and the Conversions API key, click **Validate**, then **Save**.
+
+
+ In **Event mapping for Roku Ads**, check the events Linkrunner sends and add any others you want Roku to see. See [Map events for Roku](#map-events-for-roku).
+
+
+ By default Linkrunner sends only the users your Roku links bring in. To send every user, change **For users from**. See [Choose which users to send](#choose-which-users-to-send).
+
+
+
+**Validate** sends a test event to Roku's test endpoint. Roku checks that the key and Event Group ID work together and does not count the event as a conversion, so it is safe to run at any time. Use an Event Group ID and key from the same Roku account.
+
+The key is write-only. Linkrunner never shows it again after you save it. To change the Event Group ID and keep the key, leave the key field empty when you edit.
+
+### Map events for Roku
+
+Roku accepts only its own standard event names, so each Linkrunner event you send has to be mapped to one of them. The **Roku Event** list in the mapping table shows the full set.
+
+Installs and sign-ups are always sent, under these two names. They are created for you the first time you save postbacks, and you cannot map them to another Roku event:
+
+| Linkrunner event | Roku event |
+| --- | --- |
+| Install or first open | `APP_INSTALL` |
+| Sign up | `SIGN_UP` |
+
+Click **Add Mapping** for any other in-app event. Common choices:
+
+| Linkrunner event | Roku event |
+| --- | --- |
+| Purchase or payment | `PURCHASE` |
+| Add to cart | `ADD_TO_CART` |
+| Checkout started | `INITIATE_CHECKOUT` |
+| Lead | `LEAD` |
+| Free trial started | `START_TRIAL` |
+| Subscription started | `SUBSCRIBE` |
+| Content view | `VIEW_CONTENT` |
+| Search | `SEARCH` |
+
+Turn on **Send Revenue** and choose a currency for events that carry an amount. Roku needs the value on `PURCHASE` events to report return on ad spend.
+
+To check a mapping without sending a real conversion, use the check button on its row. Roku validates the event and does not count it.
+
+### Choose which users to send
+
+- **Only users from your Roku links (default):** Linkrunner sends the events of users whose install was attributed to a Linkrunner link created with the **Roku Ads** network. To use this, create your campaign link with Roku Ads as the network and use it as the destination of your Roku ad.
+- **All media sources:** change **For users from** to send the installs and in-app events of every user, including organic users and users from other networks. Roku decides for itself which conversions to credit, by matching them to the ads it showed, so this setting gives Roku the most to match. Sign-ups are still sent only for users your Roku links bring in.
+
+The **For users from** setting needs at least one account with postbacks set up. With more than one Roku ad account, you can pick which account receives these conversions. **Automatic** uses the newest account with postbacks set up.
+
+### What Linkrunner sends
+
+Each conversion goes to Roku as one event with:
+
+- The Roku event name you mapped, and `mobile_app` as the event source.
+- The time of the event.
+- A deterministic event ID, so a retry never counts twice.
+- The Google advertising ID on Android or the advertising ID (IDFA) on iOS, when the device shares it.
+- The IP address and user agent, when known.
+- The amount and currency, for revenue events with **Send Revenue** on.
+
+Linkrunner does not send email addresses or phone numbers to Roku.
+
+A conversion is not sent when the project has no Event Group ID and key, when the event name is not one of Roku's standard events, or when Linkrunner has neither a device advertising ID nor a public IP address to give Roku for matching.
+
+## Reconnect or remove an account
+
+If Roku access is revoked or stops working, the page shows **Reconnect Roku Ads to resume syncing**. Click it and approve access again. History stays in place.
+
+To stop sending conversions, remove the postbacks from the account's row. The account keeps syncing impressions and spend. Changing or removing postbacks needs the Admin or Member role.
+
+To stop syncing an account, open its row menu and remove it. Linkrunner stops pulling its impressions and spend, and stops sending conversions through it. Numbers already synced stay in your reports, and you can connect the account again later.
+
+## Troubleshooting
+
+
+
+ The first sync runs within 6 hours of the import. Campaigns that have not served an impression have no data to show. If the account still shows **Not synced yet** after a day, remove it and connect it again.
+
+
+ Linkrunner shows why under the account: its currency is not supported, or Roku has no timezone for it. Set the missing value in Roku Ads Manager and connect again. A connected account that shows **Sync paused** has the same gap.
+
+
+ Check that both use the same dates and timezone. Linkrunner reports each day in the ad account's timezone, and Roku can restate the last days, which Linkrunner picks up on the next sync.
+
+
+ Only Admins, Members and agencies with the connect permission can connect an account. Ask a project Admin to connect it.
+
+
+ Check that the Event Group ID and the Conversions API key come from the same Roku account, and that you pasted the whole key. Roku shows a key only once, so generate a new one if you are not sure. Only a Roku Organization Admin or Account Admin can generate keys.
+
+
+ Check, in order: the account row shows an Event Group ID, the event has a mapping, **For users from** includes the users you expect, and the user's device shared an advertising ID or Linkrunner has a public IP address for them. Events that are only checked with the test button are validated and never counted.
+
+
+ Setting up postbacks needs the same permission as connecting an account. Changing or removing them needs the Admin or Member role.
+
+
+
+**Need help?** Contact [support@linkrunner.io](mailto:support@linkrunner.io)
diff --git a/api-reference/ctv-impressions.mdx b/api-reference/ctv-impressions.mdx
index 1afcfbc..8a9732f 100644
--- a/api-reference/ctv-impressions.mdx
+++ b/api-reference/ctv-impressions.mdx
@@ -26,6 +26,10 @@ X-Linkrunner-Token:
If your ad server can only fire URLs, send it as the `lr_token` query parameter instead: `&lr_token=`. Linkrunner removes `lr_token` before it stores the impression, so it never appears in reports or postbacks. A request without a valid token is rejected with `401`.
+## DSP mode (lr_key)
+
+An advertiser can also send connected TV impressions from a DSP such as Samsung Ads with a Linkrunner DSP key. Add `lr_key=` to the request and it is handled as a DSP impression instead of a partner impression. The key replaces the partner token, `app_id`, `d` and `c`, and the campaign is created from the `li` parameter. The `ip` must still be a public address, and the key needs the CTV switch and view-through on. The parameters, tags and response reasons are on [DSP Sources](/ad-networks/dsps). Everything else on this page describes requests without `lr_key`.
+
## Parameters
Send all parameters as URL-encoded query parameters. Each value is limited to 256 characters.
diff --git a/api-reference/s2s-clicks.mdx b/api-reference/s2s-clicks.mdx
index ec28a11..78ddc47 100644
--- a/api-reference/s2s-clicks.mdx
+++ b/api-reference/s2s-clicks.mdx
@@ -4,7 +4,7 @@ description: "Report affiliate clicks server-to-server"
icon: "server"
---
-Affiliate partners use this endpoint to report a click from their server when the user never opens a Linkrunner tracking link. For the setup guide, see [Server-to-Server Clicks](/affiliate-partners/s2s-clicks).
+Affiliate partners use this endpoint to report a click from their server when the user never opens a Linkrunner tracking link. Advertisers can also use it for [DSP clicks](#dsp-mode-lr_key). For the setup guide, see [Server-to-Server Clicks](/affiliate-partners/s2s-clicks).
## Endpoint
@@ -28,6 +28,20 @@ If your ad server can only fire URLs, send it as the `lr_token` query parameter
Generate the token in your affiliate dashboard under [**Settings → S2S Credentials**](https://dashboard.linkrunner.io/affiliate/settings?tab=s2s). It is shown once, so store it as a secret. One token covers every app you're connected to, for both S2S clicks and impressions. A request without a valid token is rejected with `401`. For rotation and revocation, see [Authenticate your requests](/affiliate-partners/s2s-clicks#authenticate-your-requests).
+## DSP mode (lr_key)
+
+An advertiser can also send clicks from a DSP, today Samsung Ads, with a Linkrunner DSP key. Add `lr_key=` to `GET https://s2s.linkrunner.io/v1/click` and the request is handled as a DSP click instead of a partner click. Without `lr_key`, everything on this page applies unchanged.
+
+| Difference | DSP click |
+|---|---|
+| Identity | The key replaces the partner token, `app_id`, `d` and `c`. The campaign is created from `li`, the same campaign as the impressions of that line item. |
+| Switch | The advertiser must turn on **Clicks** for that DSP. It is off by default and separate from the CTV switch and view-through. Otherwise the request is rejected with `403 clicks_disabled`. |
+| Device ID | At least one of `gaid`, `idfa` or `sha1_advertising_id` (40 hexadecimal characters) must be filled. A click with only an IP address is rejected with `400 missing_device_id`. |
+| Parameters | `lr_key`, `li`, `li_name`, `tid`, `sha1_advertising_id`, `gaid`, `idfa`, `ua` and `click_time`. Values that are empty or still a literal macro such as `__TXN_ID__` are ignored. Each value is limited to 256 characters. In DSP mode a `click_time` that is missing, not a timestamp or more than 24 hours old is replaced with the time of the request instead of being rejected. |
+| Errors | `401 missing_key`, `401 invalid_key`, `403 clicks_disabled`, `400 missing_device_id` and `429 rate_limited` when the key sends too many clicks per second. |
+
+A successful request answers `{"status":"accepted","click_id":"..."}`, never a redirect. A click beats an impression when Linkrunner credits an install. The Samsung Ads click tag, its macros and caveats, and the switch are described on [DSP Sources](/ad-networks/dsps#samsung-ads-click-tag).
+
## Parameters
Send all parameters as URL-encoded query parameters. Each value is limited to 256 characters.
diff --git a/api-reference/s2s-impressions.mdx b/api-reference/s2s-impressions.mdx
index ef90488..fe0a3ab 100644
--- a/api-reference/s2s-impressions.mdx
+++ b/api-reference/s2s-impressions.mdx
@@ -28,6 +28,10 @@ If your ad server can only fire URLs, send it as the `lr_token` query parameter
Generate the token in your affiliate dashboard under [**Settings → S2S Credentials**](https://dashboard.linkrunner.io/affiliate/settings?tab=s2s). It is shown once, so store it as a secret. One token covers every app you're connected to, for both S2S clicks and impressions. A request without a valid token is rejected with `401`. For rotation and revocation, see [Authenticate your requests](/affiliate-partners/s2s-impressions#authenticate-your-requests).
+## DSP mode (lr_key)
+
+An advertiser can also send impressions from a DSP such as Samsung Ads, The Trade Desk or Google DV360 with a Linkrunner DSP key. Add `lr_key=` to the request and it is handled as a DSP impression instead of a partner impression. The key replaces the partner token, `app_id`, `d` and `c`, and the campaign is created from the `li` parameter. In this mode missing or unusable identifiers do not reject the impression, they make it count-only. The parameters, tags and response reasons are on [DSP Sources](/ad-networks/dsps). Everything else on this page describes requests without `lr_key`.
+
## Parameters
Send all parameters as URL-encoded query parameters. Each value is limited to 256 characters.
diff --git a/docs.json b/docs.json
index 3596c36..c228015 100644
--- a/docs.json
+++ b/docs.json
@@ -191,6 +191,7 @@
"group": "Ad Networks",
"pages": [
"ad-networks/google-ads",
+ "ad-networks/google-tv-campaigns",
"features/google-icm",
"ad-networks/meta-ads",
"ad-networks/tiktok",
@@ -198,7 +199,9 @@
"ad-networks/reddit-ads",
"ad-networks/chatgpt-ads",
"ad-networks/sharechat-ads",
+ "ad-networks/roku-ads",
"ad-networks/linkedin-ads",
+ "ad-networks/dsps",
"ad-networks/meta-web-to-app"
]
},
diff --git a/features/ctv-attribution.mdx b/features/ctv-attribution.mdx
index e13eb52..4f284db 100644
--- a/features/ctv-attribution.mdx
+++ b/features/ctv-attribution.mdx
@@ -74,7 +74,39 @@ The partner replaces the macros in braces with its own values, including the TV'
## See your results
-CTV installs appear in your campaign table as installs and as **View Through Attribution** installs. Accepted impressions appear in the **Impressions** column.
+### Connected TV page
+
+The [Connected TV page](https://dashboard.linkrunner.io/dashboard/connected-tv) shows only your CTV traffic: the impressions your partners reported and the installs credited to them. It appears in the sidebar once a connected partner has **Connected TV (CTV) impressions** on, for admins and members of your project. Pick a date range at the top right. Until a partner sends CTV traffic, the page shows **No CTV activity in this period**.
+
+- **CTV overview.** Tiles for **Impressions**, **CTV installs**, **Impression conversion rate** and **Revenue**, with a daily trend as a chart or a table. Use **Breakdown** to split the trend by **Partner**, **Campaign** or **Country**.
+- **CTV performance.** A ranked bar chart. Choose **Top 5**, **Top 10**, **Bottom 5** or **Bottom 10** under **Ranking**, then a **Group by** and a **Metric** (**Installs** or **Impressions**).
+- **Performance table.** One row per partner, campaign or country, with **Impressions**, **Installs**, **Conversion rate** and **Revenue**. Click a column heading to sort.
+
+How the numbers are counted:
+
+- **CTV installs** are installs credited to a CTV impression, counted on the day of the install.
+- **Impression conversion rate** is CTV installs as a percentage of impressions. It can pass 100%, because a day's installs need not come from that day's impressions.
+- **Revenue** is the revenue from CTV installs, with the same rules as the campaign table, in your display currency. Only people who can see financial data see it.
+- **Country** shows installs only. Impressions, conversion rate and revenue are not available by country.
+- Linkrunner keeps CTV impressions for 90 days. If your range starts earlier, the page says so, and the earlier days show 0 impressions.
+
+### Google TV
+
+If your project has a connected Google Ads account, the Connected TV page has a **Google TV** section below the CTV results. It shows what Google Ads reports for your ads that ran on connected TV devices. Google counts smart TVs and game consoles as connected TV.
+
+- **What you see.** Tiles for **Impressions**, **Clicks** and **Spend**, a daily trend, and a table with one row per campaign.
+- **Reporting only.** The numbers come from Google Ads and are not matched to installs. They are not part of the household IP address numbers above, so they never change your CTV installs, conversion rate or revenue.
+- **Updates once a day.** The section follows your date range, using the days Linkrunner has already collected from Google Ads.
+- **Spend** is shown in your project currency, and only to people who can see financial data.
+- **No impression matching.** Google TV ads give Linkrunner no impression record, so an install after a viewer only watches the ad is not credited to it. A viewer who scans a Demand Gen TV QR code and reaches your Linkrunner link is counted as a click in your campaign table.
+
+To create a Google Ads campaign that runs on TV screens, see [Run Google Ads on connected TV](/ad-networks/google-tv-campaigns).
+
+The section appears only for projects with a connected Google Ads account. You connect Google Ads at [Integrations → Google Ads](https://dashboard.linkrunner.io/dashboard/integrations/google-ads). The section shows up once Linkrunner has collected data from it.
+
+### Campaign table
+
+CTV installs also appear in your campaign table as installs and as **View Through Attribution** installs. Accepted impressions appear in the **Impressions** column.
- The **Impressions** column is off by default. Click the **Edit Columns** icon in the table toolbar, tick **Impressions**, and click **Save**.
@@ -112,6 +144,12 @@ You can also turn off view-through for the partner in **Settings → Attribution
- No click or device-ID impression was available to credit instead. Those always win.
- The home IP address did not trigger the shared-network limit of more than 4 installs in about a day.
+
+ The sidebar entry shows once a connected partner has **Connected TV (CTV) impressions** on, and only for admins and members. Partner, agency and influencer logins don't see it. If the entry is there but the page says **No CTV activity in this period**, no partner has sent an accepted impression or received a CTV install in that date range. Widen the range or check the partner's requests as described above.
+
+
+ The **Google TV** section appears only when your project has a connected Google Ads account and Linkrunner has collected Google Ads connected TV data for it. Check that Google Ads is connected in [Integrations → Google Ads](https://dashboard.linkrunner.io/dashboard/integrations/google-ads) and that you are on the **Connected TV** page. The section updates once a day, so data for a newly connected account may not be there yet. If the section is there but says **No Google TV traffic in this period**, Google Ads reported no connected TV activity in that date range. Widen the range.
+
The URL shows only for a partner's campaigns once CTV is on. Check that **S2S clicks and impressions** and **Connected TV (CTV) impressions** are both on for that partner, and that the partner is connected in **Integrations → Affiliate Partners**.