Become a partner

Blog / Header Bidding

Header Bidding video header biddingPrebidVASToutstreamad pods

How to Integrate Video Header Bidding Using Prebid

Prebid runs video through the same auction as display, but delivery changes: the winning bid must resolve to a VAST tag your player can parse.

by WireAds 2023-07-17 updated 2026-02-02 9 min read
Broadcast-control cover in charcoal navy with gold and coral for integrating video header bidding with Prebid
On this page

Header bidding for video changes one thing at the delivery step: the winning bid must resolve to a VAST XML document the player can parse, not a block of display HTML. Prebid.js runs the same request, auction, and key-value targeting cycle for a video ad unit that it runs for a banner, but the creative payload has to survive an extra handoff through a cache and the player's VAST parser. Publishers lose video revenue to that handoff more often than to the auction itself: demand partners bid, Prebid selects a winner, and the player still renders nothing because the tag never arrives in a usable form. The three implementation paths below, client-side Prebid.js, Prebid Server with the cache, and a managed setup on our side, differ mainly in where that handoff happens.

What changes when the impression is video

Prebid models video as a media type inside the same adUnit object that carries your banner configuration. The auction logic, the adapter layer, and the key-value targeting system stay identical. What changes is the payload: display bids return HTML or a creative URL, while video bids return a VAST tag URL or raw VAST XML. VAST, the IAB VAST video standard, is the universal XML schema for serving ads to video players, and every demand partner we connect returns responses against it. That single constraint drives the rest of the integration: where the VAST gets cached, how the player receives the reference, and which component assembles the final tag.

Prerequisites before you write any code

Four things must exist before a video auction can clear, and most failed integrations miss at least one. Check each against your current stack before you touch Prebid configuration.

  • A VAST-capable player: your player must parse VAST through its ad SDK or a native parser, with a defined ad schedule (pre-roll, mid-roll, post-roll) and error reporting you can read.
  • GAM video inventory: an ad unit with video sizes such as 640x360 or 1280x720, and line items with the video creative type enabled.
  • Authorization files in place: ads.txt on web, app-ads.txt in apps and CTV, plus sellers.json and a SupplyChain object so buyers can audit the reseller path.
  • Video-capable demand: not every adapter supports the video media type, and those that do often require a video object inside their own bidder params.

Content metadata matters as much as the plumbing. Buyers price against duration caps, mime types, skip behavior, and placement position, so define minduration, maxduration, mimes, protocols, playbackmethod, skip, and skipafter at the adUnit level. OpenRTB 2.6 added plcmt to describe placement context more precisely than the older context field, and current Prebid versions pass both when you supply them. Undeclared metadata does not fail loudly; it just makes entire demand partners decline to bid.

Path one: Prebid.js running the auction in the browser

Pipeline from a video adUnit through requestBids into an auction flanked by bidder columns and delivery stages

The client-side path keeps everything in the page. Prebid.js requests bids from each adapter, runs the auction in the browser, and hands the result either to the ad server or directly to the player. A minimal instream adUnit looks like this:

pbjs.addAdUnit({
  code: 'video-1',
  mediaTypes: {
    video: {
      context: 'instream',
      playerSize: [640, 360],
      mimes: ['video/mp4'],
      protocols: [2, 3],
      playbackmethod: [1],
      maxduration: 60,
      skip: 1,
      skipafter: 5
    }
  },
  bids: [
    { bidder: 'partner-alias', params: { placementId: 12345, video: { skippable: true } } }
  ]
});

Two details trip up most first implementations. Several adapters require their own video object inside params, and omitting it silently drops that partner's video demand. Timing is the second: call requestBids before the player initializes for pre-roll, re-run it on content events for mid-rolls, and gate the ad request inside bidsBackHandler so the player never starts an ad break without a decision.

After the auction, the winning bid exposes bid.vastUrl or bid.vastXml. Prebid.js ships an ad server module that assembles the ad tag URL from the winning bid and hands it to the player directly, bypassing GAM. Most publishers we work with prefer routing through GAM, because it keeps AdX, direct deals, and house ads in the same decision. That routing requires the cache, which is path two.

Path two: Prebid Server and the cache

Players and ad server tags do not accept raw VAST XML as a key-value, so the tag has to live at an addressable URL before GAM can serve it. Prebid Server caches the VAST document server-side and returns a cache uuid alongside the bid. The Prebid video overview documents this flow: video bids are cached server-side, and the cache ID travels into GAM through key-value targeting. On the GAM side, the line item creative is a VAST redirect whose URL uses the Prebid Server cache endpoint with the cache uuid, exactly as the getting started with Prebid video guide specifies.

Configure the server-to-server path through s2sConfig, list only the video-capable bidders there, and set a realistic timeout, because video auctions typically need 1500 to 3000 ms rather than the 1000 ms default many display setups use. Keep the cache domain reachable from your consent and security setup: a blocked cache request produces a blank ad break with a winning bid attached, which is the worst failure mode to diagnose from delivery reports alone.

CTV and OTT inventory deserve this path almost without exception. Smart TV and console environments run limited browsers and strict app review, and a client-side auction across many adapters stalls player start. Prebid Server consolidates the requests server-side, the app passes a single cache uuid to its player, and app-ads.txt plus sellers.json keep the supply path auditable for buyers paying CTV premiums.

Path three: a managed Prebid integration on our side

The third path removes the wrapper from your codebase entirely. With our Prebid integration, we host the Prebid configuration, adapter parameters, price granularity, and cache setup, and we push the resulting demand into our SSP alongside OpenRTB exchange demand, Google MCM and AdX supply, and direct deals from global and local brand agencies. Your team implements one tag set and receives the combined auction output.

Video does not sit in a separate silo on our side. Our video monetization formats, instream, outstream, and CTV/OTT, compete in the same auction as display demand, and our ad sources meet the same filtering standards regardless of format: premium brand supply with strict review of unwanted ads. We price CPM-based, pay Net 30, and operate in every country with Google monetization across web, app, and CTV/OTT.

Outstream as the fastest format to launch

If your player stack is not ready for instream, outstream is the lowest-friction entry point. An outstream unit renders the video inside a display placement, typically within article content, and needs no ad schedule on the content player. Prebid runs the same auction; the adUnit declares context: 'outstream', and the winning bid carries a renderer that plays the VAST inside a div.

Renderers are the main decision. Bidder-provided renderers vary in behavior, so most publishers pin a known renderer at the adUnit level through the renderer field and override per-bid renderers. Our outstream video ads format handles rendering on our side, which removes that variable: the winning bid returns through the same key-values, and the renderer obeys your sound, autoplay, and player size policies.

GAM line items for video

The ad server side needs its own configuration, and it is where most revenue leaks. Create one line item per price bucket under a single order, targeted on the standard hb_pb key. The creative is a VAST redirect whose URL points at the cache endpoint, with a macro in place of the literal cache uuid so GAM substitutes the value from targeting at serve time. Set the line item type to price priority, enable the video creative type, and attach the video ad units.

Price granularity deserves a deliberate choice. Dense buckets, one cent increments up to a realistic ceiling, maximize auction precision but multiply line items; coarse buckets trade a few cents of clearing price for manageability. Match the granularity between your Prebid config and GAM exactly, because a mismatch produces unserved impressions with valid winning bids. When you run Google MCM with us, AdX demand competes in the same decision through dynamic allocation, so the header bidding line items only need to clear the exchange floor, not the entire market.

Consent architecture gates video demand more sharply than display. In EEA traffic, TCF consent strings travel inside the bid request, and several video buyers decline to bid without a valid signal. Global Privacy Control headers produce the same effect for a growing set of demand partners. Wire your consent platform into Prebid's consentManagement configuration before you debug bid responses, because missing consent looks identical to broken parameters in the response logs.

Privacy signals also change what you can declare about the viewer. Autoplay with sound off, indicated through playbackmethod, prices differently than click-to-play, and several demand partners treat a muted impression as a different product entirely. Declare the behavior you actually ship, not the behavior that prices highest, because buyers audit playback against the declared metadata and will adjust bids or blocklist supply when they find a mismatch.

Testing, validation, and common failure modes

Validate in this order: auction, cache, ad server, player. Each layer can pass while the next one fails, so isolate them before you draw conclusions.

  • Auction: set pbjs.debug = true and inspect the responses for the ad unit; confirm that at least two bidders return video bids with nonzero CPMs.
  • Cache: confirm each winning bid carries a cache uuid and that the composed URL resolves to VAST XML in a plain browser request.
  • Ad server: check GAM delivery on the hb_pb line items, then creative-level delivery, to confirm the VAST redirect actually served.
  • Player: run an end-to-end test on a real device and read completion and error events, not just impressions.

The recurring failure modes are consistent. Protocol mismatch: the player supports VAST 3.0 but the adUnit only declared 2.0. Timeout starvation: the auction cuts off before slower adapters respond.

Cache blocking: a consent script or content security policy blocks the cache domain. Metadata gaps: a missing maxduration or playbackmethod suppresses entire demand partners. And the silent one, a player that swallows VAST errors, leaves you with reported impressions and zero completed views.

What to expect once the auction runs

Expect the first weeks to be calibration rather than peak performance. Completion rate, skip rate, and player errors feed back into adUnit metadata and timeout settings, and demand partners tune their bids once they see consistent, clean supply. Video CPMs typically clear above display on the same geography because buyers pay for completed, auditable attention, but the range depends on format, geography, and content length, so treat any specific number with suspicion.

We pay Net 30 on CPM-based terms, we filter aggressively, and we run video in every market with Google monetization across web, app, and CTV/OTT. Choose the integration path that matches your player architecture: client-side Prebid.js when you control the page and want full ownership, Prebid Server with the cache when you route through GAM or run app and CTV inventory, or our managed setup when you would rather ship product than maintain a wrapper. If the player parses VAST reliably and the cache handoff works, the auction does the rest.

Related

Keep reading.

Chalkboard cover in ochre and red chalk for an article on five common Prebid setup mistakes hurting revenue
Header Bidding

5 Common Prebid Setup Mistakes Hurting Your Ad Revenue

Most header bidding revenue leaks come from setup errors, not weak demand: here are five P...

2025-09-29 · 8 min
Ivory field-manual cover with navy ink and red stamps for a publisher's guide to debugging Prebid like ad ops
Header Bidding

A Publisher's Guide to Debugging Prebid Like an Ad Ops Pro

A failed Prebid auction leaves no error banner on the page, so publishers need a repeatabl...

2024-11-21 · 10 min
Muted duotone cover in slate indigo and coral for a comparison of client-side versus server-side header bidding
Header Bidding

Client-Side vs. Server-Side Header Bidding: What's Best for Your Site?

Client-side header bidding caps out around a dozen bidders before latency bites, while ser...

2024-01-24 · 10 min

The WireAds market brief

Monthly CPM trends and monetization tactics for publishers. No spam, one email a month.