Yuval Fisher - August 26th 2021
“The wolf shall live with the lamb, the leopard shall lie down with the kid, the calf and the lion and the fatling together, and…” the ad pod shall be filled with amusing creatives and all shall convert to impressions. In a world where all is perfect, we wouldn’t have ad-holes.
This ad-hole investigation began with a demand partner contacting Wurl to report low use-rate (see the first blog post to understand use-rate). The demand was returning ads galore – “take my ad, please” – but almost all the ads were not converting to impressions. It was AdOps ulcer-inducing stuff. What could cause that? The investigation started with a list of possibilities, painstakingly eliminated one by one.
One cause of an unplaced ad is a corrupted source creative. Most creatives for over-the-top (OTT) are delivered as MP4 files rather than the delivery streaming format. These MP4 files must be transcoded into multiple bitrates and resolutions suitable for adaptive bitrate distribution, for example HTTP Live Streaming (HLS). But that wasn’t the problem here, because a small number of ads were actually being inserted, though not at the rate they were being returned by the demand’s ad server. Clue #1.
A second reason an ad may not be inserted is if it is new. New ads cannot be inserted as-is into a stream. Like a sacrificial bottle of champagne smashed at the launch of a new ship, the first ad-insertion opportunity for a new ad is thrown away while the ad is being transcoded into the delivery format. How does the ad stitcher know if the ad is new or already transcoded? Different ad splicers use different techniques. In our case, the key used to determine if the ad was new was the “Ad ID,” a value returned in the VAST response.
Unfortunately, in this case the demand partner chose to regularly change this ID, probably for some sort of tracking purposes. Clue #2. Thus, even when the same ad was returned in successive VAST responses, the ad insertion system thought it was new, ignored the ad-insertion opportunity, and started to transcode the ad. Ads were being transcoded again and again.
“To every thing there is a season, and a time to every purpose under the heaven: A time to be born, and a time to die; a time to plant, and a time to pluck up that which is planted…” but sometimes there isn’t enough time to transcode and transcode and transcode yet again.
The solution was (duh) to avoid using the Ad ID and use something else to recognize ads that have been returned (and transcoded) before. “What else can one use?” you may ask. A first idea might be: use the actual creative source URL. Doing this almost fixes the problem, but it’s not a panacea. Unfortunately, demand partners will sometimes use the same source URL and change the underlying creative. That’s a serious problem.
In an example we’ve seen, a creative had:
(A side comment about transcoding: it, too, can be problematic; the wolf shall live with the lamb, but the transcoder does not always live with the MP4). To dive into an arcane HLS example, some source content with a EXT-X-TARGETDURATION set at 7 seconds had ads transcoded to have 8 second fragments due to a transcoder setting (with 2 second key-frame duration, per Apple’s recommendations. That broke the playback. Tricky).
It’s hard to figure out when the creative returned in a VAST response has been encountered before. There’s a fantastic plan to use a universal Ad ID, which is waiting for the wolf to stop eating the lamb next door; at that point, everyone will use this universal Ad ID (google it), and the problem will go away: want to know if you’ve transcoded this ad? Track the universal Ad ID for it and keep a “I transcoded this Ad ID before” table.
For now, people mostly use the creative URL. But it is often full of timestamps and other dynamic parts, so it can’t be used as is.
To fix this, it’s necessary to look at demand-side responses source-by-source and figure out what parts change and what parts are static (per ad) in their response – then key in on the static parts. Read that again. It’s not simple. Every distinct demand source needs to have rules that specify which portions of their response are static for a specific ad. This is how the problem is solved at Wurl. It works well, but it doesn’t address the full problem. The same ad routed through different demand sources will not be recognized as being the same, for example. Such ads will get transcoded more than once, which is not that bad. But it may also be placed in the break more than once, which can be annoying.
This short blog entry represents weeks of work which ended up with a significantly improved use-rate, as well as a nice way to de-duplicate repeated instances of an ad in the same ad pod (at least when routed through the same demand source). As we wait for Ad ID to be universally used (and the lion to develop a taste for grass), we have a solid interim solution.