We can't tell what content our CTV ads ran next to. How do we find out?
You find out by getting two values written down for every impression, the content ID and the playhead position, and by joining them to an index of what is on screen at each second of that content. CTV rarely records either value for the buyer today, which is why your report stops at the app or the channel. Three moves close most of the gap: write show-level reporting into the deal, put the VAST content macros into your impression trackers, and have the party that holds the video (publisher, SSAI service or FAST channel operator) run the join against a scene index.
Why is CTV placement so hard to see?
The problem is common enough that it has been measured.
Three things cause it.
The bid request is thin. OpenRTB has a full
content object with series, episode, genre and category
fields, and all of them are optional
(OpenRTB 2.6). Our
guide to why CTV bid requests lack content categories covers how
often they arrive empty.Privacy law makes publishers careful. The Video Privacy Protection Act limits sharing show-level viewing data, so some publishers hold titles and episodes out of the bid stream (Advertising Week).
The video has no text to read. A web verification tag can read the article around an ad. A CTV ad plays inside a stream, and what the viewer saw before the break lives in pictures and sound that no tag can parse. Someone has to analyze the video itself, and only the party holding the files can.
Who can see what?
| Party | What it usually knows | What it usually lacks |
| Advertiser or agency | The creative, the DSP line item, the app or bundle ID when passed | Show, episode, and what was on screen at the break |
| DSP | Whatever the bid request carried | Anything the seller left out of the request |
| SSP | The full request, the publisher, often the content ID | The video itself |
| Publisher, SSAI service or FAST operator | The video files, content IDs, ad break positions | A buyer-facing record of which ad played where |
| Verification vendor | Signals its tag or integration can collect | Scene content, unless the publisher shares it |
Which VAST macros record what an ad ran next to?
VAST macros are placeholders in tracking URLs that the player or ad server fills in when it fires the pixel. Three from IAB Tech Lab's macro list do this job (VAST 4 macros):
| Macro | Added in | What it carries |
[CONTENTID] | VAST 4.1 | The publisher's ID for the content asset the ad is inserted into, as a registry ID, a space, and the ID value. In-stream only |
[CONTENTURI] | VAST 4.1 | The URI of the main content asset the ad is inserted into. In-stream only |
[MEDIAPLAYHEAD] | VAST 4.1 | The playhead position on the content timeline, as HH:MM:SS.mmm |
https://track.example.com/imp?cid=[CONTENTID]&curi=[CONTENTURI]&pos=[MEDIAPLAYHEAD]&cb=[CACHEBUSTING]
[CONTENTID], which is an easy thing to count.How does the scene join work?
Once an impression carries a content ID and a playhead, the rest is a lookup.
1. Index the content once. The publisher or operator splits each episode, movie or FAST segment into scenes and stores, per scene, its start and end time and what it contains: labels from the frames, a speech transcript, on-screen text, and IAB Content Taxonomy 3.1 categories (IAB Tech Lab). 2. Key it by the same content ID the player sends in
[CONTENTID].
3. Join each impression to the scene that ends at the break. Find the scene for that content ID whose time range
contains or ends just before [MEDIAPLAYHEAD], plus the scene that starts after the break.
4. Report what aired around the break. A per-impression row now says "aired after a scene with a car crash
on a news channel" or "aired after a cooking segment", which is the level brand suitability decisions are made at.The index is built once per asset, so the per-impression cost is a key-value read. The video never leaves the publisher's storage, which also keeps the viewing data question with the party that already holds it.
What should we put in the deal?
content object in the bid request, including cat with cattax: 9 for Content Taxonomy 3.1,Private marketplace and direct deals are where these terms are usually negotiated. Open-exchange CTV will often not carry them.
What does this leave to other tools?
Content adjacency says what was on screen. Fraud and spoofed apps are handled by invalid traffic detection and supply chain files such as app-ads.txt and sellers.json. Audience reach and attribution come from your measurement partner. A correct content ID on a spoofed impression is still a spoofed impression.
How does Mixpeek fit?
Mixpeek builds the scene index in step 1 for the party that holds the video. It reads files where they already live in object storage, splits video into scenes with start and end times, extracts frames, speech and on-screen text, and classifies each scene against IAB Content Taxonomy 3.1 with a confidence score per label. The output is queryable by content ID and time range, which is the join in step 3. See how to classify content against a taxonomy and the video scene segmentation guide. If you are a buyer, Mixpeek is useful to you through the publisher or SSP that runs it, so the ask in the deal above is the part you control.
An open benchmark for scene-level IAB classification is not yet published, so test any classifier on a sample of your own catalog before its labels decide where ads run.
Frequently Asked Questions
Can an advertiser see which CTV show an ad ran on?
Sometimes. It depends on whether the seller passes the series and episode in the bid request or in a post-campaign report, and many open-exchange impressions carry only an app ID. Ask for show-level reporting in the deal and add
[CONTENTID] to your impression tracker.What is the VAST [MEDIAPLAYHEAD] macro?
It is the playhead position on the content timeline, in
HH:MM:SS.mmm format; the ad's own position is [ADPLAYHEAD].
It was added in VAST 4.1 and replaced the deprecated [CONTENTPLAYHEAD]
(VAST 4 macros).Why do CTV publishers hold back show-level data?
Two reasons come up most: the Video Privacy Protection Act limits sharing show-level viewing data, and some publishers keep their best content data for direct deals (Advertising Week).
Is knowing the show enough for brand suitability?
Often it is not. A news program or a drama can carry a scene you would block in one episode and nothing of concern in the next. Scene-level adjacency, joined on the playhead, tells you what aired right before your ad.