NEWVectors or files. Pick a path.Start →
    Video Understanding
    8 min read
    Updated 2026-10-16

    We Can't Tell What Content Our CTV Ads Ran Next To. How Do We Find Out?

    If you cannot tell what content your CTV ads ran next to, the record was never written: most CTV impressions reach the buyer with an app ID at best, and no show, episode or scene. Ask sellers for show-level reporting in the deal, add the VAST [CONTENTID] and [MEDIAPLAYHEAD] macros to your impression trackers so each impression carries the content ID and the second it played at, and have whoever holds the video join those two values to a scene index of the content. Covers what each party can see, the macros, the join, and what to put in a deal.

    CTV
    VAST
    Ad Tech
    Brand Suitability
    Transparency
    Video
    Contextual Advertising

    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.

  1. DoubleVerify and IAB Europe surveyed more than 420 senior advertiser and publisher executives. Only 30% said
  2. they have full transparency into where ad placements appear, and 27% never or rarely have insight into the brand suitability of the shows ads run alongside (ExchangeWire).
  3. DoubleVerify reports that in its 2024 data only 50% of CTV impressions offered full app transparency
  4. (DoubleVerify). Both figures come from a verification vendor that sells a fix, so read them as directional.

    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?



    PartyWhat it usually knowsWhat it usually lacks
    Advertiser or agencyThe creative, the DSP line item, the app or bundle ID when passedShow, episode, and what was on screen at the break
    DSPWhatever the bid request carriedAnything the seller left out of the request
    SSPThe full request, the publisher, often the content IDThe video itself
    Publisher, SSAI service or FAST operatorThe video files, content IDs, ad break positionsA buyer-facing record of which ad played where
    Verification vendorSignals its tag or integration can collectScene content, unless the publisher shares it
    The party with the files is the only one that can say what was on screen. Everything below is about getting that party to write the answer down in a form you can join to your impressions.

    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):

    MacroAdded inWhat it carries
    [CONTENTID]VAST 4.1The 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.1The URI of the main content asset the ad is inserted into. In-stream only
    [MEDIAPLAYHEAD]VAST 4.1The playhead position on the content timeline, as HH:MM:SS.mmm
    An impression tracker that uses them looks like this:
    https://track.example.com/imp?cid=[CONTENTID]&curi=[CONTENTURI]&pos=[MEDIAPLAYHEAD]&cb=[CACHEBUSTING]
    The catch is support. IAB Tech Lab's CTV addendum says support for the latest macros "is not required", and that partners may request or require select ones (VAST CTV Addendum 2024). So ask for them by name in the deal, then check your logs: a macro the player does not support comes back unreplaced, as the literal text [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?



  5. Show-level reporting: series, episode and network per impression or per day, with the content ID.
  6. The three macros above in your impression trackers, and a check on the unreplaced rate after launch.
  7. A filled content object in the bid request, including cat with cattax: 9 for Content Taxonomy 3.1,
  8. so you can target and block before the auction rather than only report after it.
  9. A scene-level adjacency report where the seller can produce one, for categories you block.


  10. 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.
    Managed Mixpeek

    Put multimodal search to work

    Connect a bucket and Mixpeek runs the whole multimodal search pipeline for you: extraction, indexing, and search over your own objects. No models to wire up, nothing to host.

    Start with Managed
    MVS · bring your own

    Already have vectors?

    Keep your embeddings on your own cloud and run dense, sparse, and BM25 search directly on object storage. From $25/mo.

    Start with MVS

    Run this on your own data

    Point Mixpeek at the storage you already have and search your video, images, audio, and documents the way this guide describes. Build starts at $25/mo for up to 1M vectors.

    Search your own archiveRead Docs