Interactive Header Bidding Guide

Prebid.js & Header Bidding Architecture

Understand how wrapper auctions execute in the browser and server, how winning bids pass into Google Ad Manager (GAM), and how to isolate latency, pricing, and rendering bottlenecks in production.

Header Bidding Track

Master client-side and server-side header bidding orchestration

Prebid is the industry-standard open-source header bidding wrapper. Learn how it orchestrates multi-bidder auctions before the ad server is called, how GAM key-values are passed, and how to debug latency and no-bid drops.

What you'll learn

  • Prebid.js lifecycle from addAdUnits to GAM line item selection and rendering
  • Client-side vs Prebid Server (PBS): latency, cookie sync, and device trade-offs
  • Price granularity (auto, dense, custom) and key-value mapping (hb_pb, hb_bidder)

What is inside

  • Full annotated Prebid.js configuration code with multi-format banner + video slots
  • Browser console debugging toolkit for live inspection (pbjs.getBidResponses)
  • Top 5 real-world header bidding failure modes and recovery playbooks

How to use this guide

  • Open the browser developer console on any publishing site and test pbjs commands
  • Use the price granularity table to calibrate GAM line item tiering
  • Review the troubleshooting scenarios for yield optimization and AdOps support
In Plain English

What is Header Bidding & Prebid?

Historically, ad servers called demand sources in a waterfall (one by one). If the first partner passed, the second partner was offered the impression at a lower price, even if a third partner was willing to pay more. Prebid solves this by holding a fair, simultaneous mini-auction right inside the webpage header before calling Google Ad Manager. It collects everyone’s best prices, sends the winning bid into GAM as key-values, and forces GAM to beat that price or let the Prebid partner win.

Prebid.js 8-Step Execution Lifecycle

The exact technical sequence that runs on every page view before an ad displays:

  • 1
    Page Load & Queue Initialization
    The browser loads prebid.js asynchronously. Calls to pbjs.que.push() queue functions safely until the Prebid library is fully parsed.
  • 2
    Ad Unit Definition (addAdUnits)
    Publisher defines slot IDs, supported media types (banner, outstream video), dimensions, and partner bidder params (e.g. AppNexus placementId, Rubicon accountId).
  • 3
    Auction Trigger & Timer Start (requestBids)
    Prebid sends simultaneous AJAX/fetch requests to all configured bidder adapters. The bidderTimeout timer (e.g. 1000ms) begins ticking.
  • 4
    Adapter Request Transformation
    Each adapter translates the Prebid ad unit into that SSP's specific OpenRTB or proprietary format and communicates with the partner's bid endpoint.
  • 5
    Bid Collection & Timeout Cutoff
    Bids that return with a positive CPM before bidderTimeout are registered in memory. Any response arriving after the timeout is marked as timed out and discarded.
  • 6
    GAM Key-Value Setting (setTargetingForGPTAsync)
    Prebid calculates the winning bidder for each slot, rounds the CPM to the configured price granularity (e.g. $2.84 → hb_pb=2.80), and attaches targeting parameters to Google Publisher Tags (GPT).
  • 7
    GAM Ad Server Evaluation
    GAM evaluates direct sponsorship lines, price priority lines (targeting hb_pb values), and Google Ad Exchange (AdX). If a Prebid line item is higher than AdX, Prebid wins.
  • 8
    Creative Rendering (pbjs.renderAd)
    The winning GAM creative snippet triggers a postMessage or callback to pbjs.renderAd(document, adId), which safely injects the advertiser's creative markup into an iframe.

Client-Side (Prebid.js) vs Server-Side (Prebid Server / PBS)

Choosing the right architecture depends on device capabilities, user network speed, and identity syncing needs:

Attribute Client-Side (Prebid.js) Server-Side (Prebid Server / PBS)
Network Requests Fans out 10–20+ network requests directly from the user's browser, consuming mobile bandwidth and CPU. Fans out 1 single request from browser to PBS; PBS handles multi-bidder fan-out on ultra-fast cloud server connections.
Latency Impact Subject to user's local connection speed and browser connection limits (max 6 connections per domain). Extremely low network overhead on user device; responses return in under 150ms.
User Sync & Identity Direct access to 3rd-party and 1st-party cookies; highest match rates on desktop web. Requires cookie-sync redirection tables; slightly lower identity match rates if syncs are unprimed.
Best Use Cases Desktop websites with high-speed broadband users and complex custom client adapters. Mobile Web, AMP, Mobile Apps (SDK), and Connected TV (CTV) where device resources are constrained.

Annotated Prebid.js Setup Code

Standard production setup with multi-bidder configuration, timeout rules, consent management, and GPT integration:

JavaScript Prebid.js Configuration & GAM Integration
// 1. Initialize Prebid and GPT queues
var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];

// 2. Global Prebid Configuration
pbjs.que.push(function() {
  pbjs.setConfig({
    bidderTimeout: 1000,                  // Wait maximum 1000ms for bidder responses
    priceGranularity: 'dense',               // $0.01 increments up to $3, $0.05 up to $8, etc.
    enableSendAllBids: true,                 // Send all bidder key-values into GAM for granular reporting
    consentManagement: {
      gdpr: {
        cmpApi: 'iab',                        // Automatically detect IAB TCF v2.2 CMP on page
        timeout: 800,                         // CMP timeout before falling back
        defaultGdprScope: true
      },
      usp: {
        cmpApi: 'iab',                        // US Privacy / CCPA string detection
        timeout: 500
      }
    }
  });

  // 3. Define Ad Units with Multi-Bidder Parameters
  var adUnits = [
    {
      code: 'div-gpt-ad-leaderboard',          // Div ID of the ad slot on page
      mediaTypes: {
        banner: {
          sizes: [[728, 90], [970, 250]]  // Multi-size support
        }
      },
      bids: [
        {
          bidder: 'appnexus',
          params: { placementId: 13144370 }
        },
        {
          bidder: 'rubicon',
          params: { accountId: 14062, siteId: 70608, zoneId: 344324 }
        },
        {
          bidder: 'openx',
          params: { unit: '541234567', delDomain: 'publisher-d.openx.net' }
        }
      ]
    }
  ];

  pbjs.addAdUnits(adUnits);

  // 4. Request Bids and Send Key-Values to GAM
  pbjs.requestBids({
    bidsBackHandler: initAdserver
  });
});

// 5. Handoff to Google Ad Manager
function initAdserver() {
  if (pbjs.initAdserverSet) return;
  pbjs.initAdserverSet = true;
  googletag.cmd.push(function() {
    pbjs.que.push(function() {
      pbjs.setTargetingForGPTAsync();      // Sets hb_pb, hb_bidder, hb_adid on GPT slots
      googletag.pubads().refresh();        // Fires GAM ad request with targeting
    });
  });
}

Price Granularity & Key-Value Mapping

How Prebid converts exact floating-point CPM bids into rounded buckets that match GAM line items:

Granularity Mode CPM Range Bucket Increment Example Mapping
low $0.00 – $5.00 $0.50 increments $2.43 bid → hb_pb=2.00 ($0.43 value loss)
medium $0.00 – $20.00 $0.10 increments $2.43 bid → hb_pb=2.40 ($0.03 value loss)
dense (Recommended) $0.00 – $3.00
$3.00 – $8.00
$8.00 – $20.00
$0.01 increments
$0.05 increments
$0.50 increments
$2.43 bid → hb_pb=2.43 (Exact clearing)
$5.23 bid → hb_pb=5.20
custom Configured by publisher Any custom tiered array Tailored specifically to publisher inventory CPM distribution

Browser Console Debugging Toolkit

Run these one-line commands in Chrome DevTools Console (F12) on any Prebid page to inspect live auctions:

JavaScript Developer Console Diagnostic Commands
// 1. Enable Prebid verbose logging in console
pbjs.logging = true;

// 2. Inspect all received bid responses for all ad units
pbjs.getBidResponses();

// 3. View only the winning (highest CPM) bids
pbjs.getHighestCpmBids();

// 4. Check bids that exceeded the timeout window
pbjs.getBidResponsesForAdUnitCode('div-gpt-ad-leaderboard').bids.filter(b => b.timeToRespond > 1000);

// 5. View exact key-values currently targeted to GAM
pbjs.getAdserverTargeting();

// 6. Inspect current Prebid configuration and consent modules
pbjs.getConfig();

Top 5 Prebid Header Bidding Failures & Fixes

Common issues encountered during header bidding deployments and how to resolve them:

⏱️ 1. High Bidder Timeout Rate (>30%)

Problem: Bidders submit high CPMs, but GAM renders fallback AdX or house ads because responses arrive after bidderTimeout.

Root Cause: Timeout set too low (<600ms) for mobile connections, or calling too many client-side adapters simultaneously.

Fix: Increase timeout to 1000–1200ms on mobile, or migrate high-latency bidders to Prebid Server (PBS).

🎯 2. Winning Bid Not Displayed in GAM (AdX Always Wins)

Problem: Prebid records a $4.50 winning bid, but GAM serves an AdX impression at $2.10.

Root Cause: GAM line items are not configured to match the exact hb_pb key-value format (e.g. GAM line item targets hb_pb=4.5 instead of hb_pb=4.50).

Fix: Verify that price granularity formatting in Prebid matches GAM line item targeting rules with 2 decimal places.

πŸ›‘ 3. Consent String Blocking Partner Bids

Problem: Prebid adapters return immediate No-Bid in European traffic without sending network requests.

Root Cause: The CMP did not grant consent for the specific Vendor ID under IAB TCF v2.2 Purpose 1 (Device Storage) or Purpose 2 (Basic Ads).

Fix: Audit CMP vendor registration to ensure all Prebid bidder GVL IDs are included in the consent modal.

πŸͺŸ 4. Blank Ad Slot on Creative Win (Iframe Error)

Problem: Prebid line item wins in GAM, but the ad container remains completely blank.

Root Cause: Missing pbjs.renderAd(document, '%%PATTERN:hb_adid%%') script inside the GAM creative snippet, or SafeFrame preventing DOM access.

Fix: Check GAM Creative code snippet and ensure "Serve into a SafeFrame" is unchecked if using standard Prebid universal creative.

πŸ”„ 5. Double Refresh / Memory Leaks on Infinite Scroll

Problem: On infinite scroll pages, slots repeatedly call auctions for old destroyed divs, causing memory bloat and latency.

Root Cause: Failure to call pbjs.removeAdUnit() before re-requesting bids for dynamically inserted content units.

Fix: Destroy slot GPT instances and call pbjs.removeAdUnit(slotCode) before injecting new ad units.

Prebid & Header Bidding Interview Q&A Cheat Sheet

Key technical talking points for AdOps and Solution Engineer interviews:

Q: How does Prebid communicate with Google Ad Manager (GAM)?

Prebid executes before GPT refreshes. It identifies the highest bid per slot, rounds the CPM into a price bucket (e.g. hb_pb=3.50), and attaches targeting key-values (hb_bidder, hb_adid, hb_size) using pbjs.setTargetingForGPTAsync(). GAM receives these key-values and matches them against pre-configured Price Priority line items.

Keywords: setTargetingForGPTAsync, Price Priority line items, hb_pb key-value.

Q: What is the risk of setting bidderTimeout too high or too low?

Setting bidderTimeout too low (e.g. 300ms) causes bid drops because bidders cannot return in time, leaving revenue on the table. Setting it too high (e.g. 3000ms) delays the GAM ad call, causing page load lag, lower ad viewability, and poor user experience.

Keywords: Timeout calibration, latency vs yield trade-off, viewability impact.

Q: What is Send All Bids vs Send Top Bid?

In Send Top Bid mode, Prebid only sends key-values for the single highest bidder. In Send All Bids (enableSendAllBids: true), Prebid sends key-values for every participating bidder with bidder-specific prefixes (e.g. hb_pb_appnexus=3.20, hb_pb_rubicon=3.10). This provides granular reporting inside GAM and allows multi-bidder line item competition.

Keywords: enableSendAllBids, granular GAM reporting, bidder-specific targeting.

Q: What is User Syncing in Prebid and why is it important?

User syncing enables SSPs to drop an iframe or image pixel to synchronize their proprietary cookie ID with the user’s browser. Without user syncing, DSPs cannot recognize the user across different domains, resulting in un-targeted bids with 50–80% lower CPMs.

Keywords: Cookie sync, iframe/image pixels, identity resolution, match rate.

AdTech Toolkit

Enter any two values
to calculate the third

More tools coming soon