Header bidding 101: how publishers maximize revenue

Header bidding is the architecture every meaningful publisher now uses to monetise display and video inventory. This is what it actually does, why it works, and where its sharp edges live.

The problem header bidding solved

Until about 2015, programmatic monetisation on the open web had a structural unfairness baked into it. Google's ad server (DFP, now Google Ad Manager / GAM) gave Google's own exchange (AdX) the right to bid last — to see what every other demand source had offered and then decide whether to outbid them by one cent or pass. Everyone else had to commit to a static CPM in advance. Publishers were leaving money on the table because non-Google demand sources never got to compete in a fair, dynamic auction.

Header bidding was the publisher-led answer. The idea is simple: before calling the ad server, ask every demand partner — directly from the page — what they would pay for this impression right now. Collect all the responses, pick the highest, and pass that price into the ad server's auction as the floor for AdX to beat. Suddenly every demand source was bidding in real time, and AdX no longer had a structural advantage.

Header bidding is often called pre-bid for this reason — the auction happens in the page header, before the ad server call. Hence the name.

The old way: the waterfall

Before header bidding, the ad server worked through demand sources sequentially in a configured priority order — the "waterfall."

  1. Try direct-sold campaign A (guaranteed $5 CPM). If fill rate is 100%, use it.
  2. If no fill, try direct-sold campaign B ($3 CPM). If fill, use it.
  3. If no fill, call SSP 1 (typically with a static "expected CPM" the publisher set manually).
  4. If SSP 1 doesn't fill, call SSP 2.
  5. ...and so on down to a backup remnant tag.

The problems were severe. The static "expected CPM" for each SSP was an estimate set by the publisher's ad-ops team, usually based on last month's averages. If SSP 2 would have actually paid $4 for this particular user but its average was $1.20, it never got the chance because SSP 1 (with an expected CPM of $1.50) filled first at $1.50. Inventory was being sold to whichever SSP came first in the chain at whatever they happened to pay, not to whoever valued it most for this particular impression.

The new way: parallel auctions

Header bidding turns the sequence on its head. Before the ad server call, a JavaScript wrapper on the page (Prebid.js is the most common implementation, but there are others) does the following:

  1. Identifies the ad slots that will be requested.
  2. Builds a bid request for each configured demand partner (six to twenty is typical).
  3. Fires all the requests in parallel.
  4. Waits up to a configured timeout (commonly 1,500 to 2,500 ms — though many publishers tune this much tighter).
  5. Collects bids that returned in time. Late bids are dropped.
  6. Picks the highest bid per slot.
  7. Passes the winning CPM into the ad server as a key-value targeting parameter (e.g. hb_pb=4.20).
  8. Lets the ad server run its own auction, where the highest-bidding header-bidding partner competes against direct-sold campaigns and AdX.
  9. If a header-bidding partner wins the ad-server auction, the wrapper script substitutes in that partner's creative.

The result is that every demand partner gets to bid every time, dynamically, on every impression — instead of being placed in a static priority order.

Client-side vs server-side

Two flavours of header bidding exist, and most large publishers use both.

AspectClient-sideServer-side
Where auction runsIn the user's browser via JavaScriptOn an "S2S" endpoint operated by a vendor
Page weightHeavy — each bidder adapter is JS that ships to the userLight — one request from the page to the S2S server
Page latency impactSum of slowest bidder's response time and parsing timeSingle round trip plus S2S server's own bidder timeout
User-data accessFull — cookies, localStorage, fingerprintsLimited — must rely on user-sync calls and S2S cookies
Win rate per bidderHigher (more signals)Lower (less signal, plus cookie sync gaps)

The pragmatic pattern is: keep two or three top-revenue bidders client-side, where they have full signal access; push the long tail server-side, where they cost almost nothing in page weight. This balances revenue and Core Web Vitals.

First-price economics and bid shading

Almost all header bidding auctions are first-price — the winner pays their actual bid. This is a meaningful change from how RTB worked through 2018, and it has a non-obvious consequence: a bidder's optimal strategy is no longer "bid your full value." In a first-price auction, bidding your full value means you win at break-even or worse. The optimal bid is a function of the bidder's distribution of competing bids.

This is the problem bid shading solves. A DSP using bid shading does roughly this:

  1. Calculates the bidder's internal value for the impression (what they would pay in an oracle world).
  2. Builds a model of the distribution of competing bids on similar impressions from this exchange / publisher / hour-of-day.
  3. Picks a bid price that maximises expected surplus: probability-of-winning × (value − price).

The bid sent to the exchange is therefore typically 60 to 85 percent of the bidder's true valuation. The exchange knows this and (mostly) does not try to fight it — overall, first-price plus bid shading produces a healthier market than second-price ever did, because there is no longer any incentive for the exchange to engage in hidden margin manipulation.

Caveat: if you are auditing your own DSP's bid shader and notice the win rate is exactly the same as before shading was introduced, you are leaking money. A good shader produces a slightly lower win rate at a noticeably lower average paid price.

Floor prices, dynamic floors, and unified pricing

A floor price is the minimum bid the publisher will accept. Bids below the floor are dropped. The reason floors matter so much in a first-price world is that without them, bidders' shading models converge on bidding very low — because everyone else is too. Floors break the race to the bottom by truncating the bid distribution from below.

Three patterns are common:

Integration with the ad server

The ad server (almost always Google Ad Manager, but DFP-replacement vendors exist) is the source of truth for which creative is actually shown. Header bidding plugs into it via line items and key-value targeting.

The classic pattern: the publisher creates a series of line items, each targeting a CPM bucket — say hb_pb = 1.50, hb_pb = 1.60, hb_pb = 1.70, and so on up to hb_pb = 20.00. Each line item has its bid floor set to that CPM. When Prebid.js sets hb_pb=4.20 as the targeting key on the ad request, the ad server's auction matches the hb_pb = 4.20 line item — which then competes against direct-sold and AdX bids at its declared CPM.

This bucket pattern only resolves CPM to two decimals, but at typical CPM levels that is more precision than the market actually needs. Newer ad servers can pass the full CPM as a numeric value, eliminating the buckets entirely.

Latency tradeoffs

Header bidding adds a real cost: the time between page load and ad render goes up. Whatever the auction timeout is set to (1,500 ms is a common starting point), the ad slot can't paint until either every bidder has responded or the timer expires.

The most common levers publishers pull:

Core Web Vitals — specifically Largest Contentful Paint — care about how quickly the page becomes visually complete. A heavy header-bidding wrapper that blocks ad rendering for two seconds can directly drag LCP from "good" into "poor," which then affects search ranking. Modern wrappers asynchronously load and bid in parallel with critical content render to avoid this.

Honest pros and cons

Header bidding is widely deployed and largely good. But it is not free.

The wins

The costs

When header bidding is the right tool

For publishers with meaningful programmatic revenue — anywhere above the long tail — header bidding is essentially the default in 2026. The question is which flavour to deploy, not whether. The decision tree typically considers traffic volume, the publisher's appetite for in-house ad-ops engineering, the latency budget of the page template, and the mix of direct-sold versus programmatic revenue. A site doing 80 percent direct sales will tune its setup very differently from a site doing 95 percent programmatic.

For smaller publishers, a simpler setup is often better:

For everyone else, learn Prebid.js, instrument your auctions, monitor your win rates per bidder, and treat the wrapper as production infrastructure — because that is what it is.

Closing thought

Header bidding looks complex from outside, but the core idea is a one-paragraph change to the auction order: ask every buyer in parallel before letting your ad server pick, instead of going down a list one at a time. The complexity that grew on top of that simple idea — first-price economics, bid shading, dynamic floors, server-side endpoints, identity gaps — is what the rest of the industry now spends its time on. Whichever flavour of header bidding you run, the discipline that separates a well-tuned setup from a leaky one is the same: instrument every auction, track per-bidder win rate and average paid CPM, watch latency carefully, and treat every new bidder you add as a configuration change that needs the same scrutiny as a deploy. Done that way, header bidding is one of the highest-leverage engineering investments a publisher can make.


Related reading