In this article
1. What Is Prebid.js?
Prebid.js is the dominant open-source header bidding wrapper used by publishers worldwide to implement client-side header bidding. Launched in 2015 by AppNexus (now Xandr) and Rubicon Project, it has become the de facto standard, powering header bidding on over 70% of programmatic publisher sites globally.
Prebid.js provides a standardized framework for integrating multiple demand partners (SSPs, ad exchanges, ad networks) into a single, unified auction that runs in the user's browser before the publisher's ad server is called. It handles bid request dispatch, response collection, auction resolution, price bucketing, and ad server integration — all through a single JavaScript library that publishers include on their pages.
The library supports 300+ demand partner adapters, multiple ad formats (display, video, native), consent management (GDPR, CCPA, GPP), and extensive analytics hooks for measurement and optimization. Prebid.js is maintained by the Prebid.org community, a consortium of ad tech companies that governs the project's development roadmap.
2. Installation & Setup
Download vs CDN
Prebid.js can be deployed in two ways. The custom download from Prebid.org's download page allows you to select only the bidder adapters and modules you need, producing a smaller file size. The CDN-hosted version (cdn.jsdelivr.net/npm/prebid.js) includes all adapters but is larger. For production use, the custom download is strongly recommended for performance.
<!-- Include Prebid.js in the <head> before ad server tags -->
<script async src="prebid.js"></script>
<!-- Google Ad Manager (GPT) should load after Prebid -->
<script async src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
Basic Integration Sequence
The integration follows a specific sequence: define ad units, configure bidders, request bids, then initialize the ad server. Prebid.js must complete its auction before the ad server (Google Ad Manager) makes its final decision, ensuring header bidding bids compete correctly with direct-sold campaigns.
// 1. Initialize Prebid.js
var pbjs = pbjs || ;
pbjs.que = pbjs.que || [];
// 2. Define ad units with bidders
var adUnits = [{
code: 'div-gpt-ad-1234567890-0',
mediaTypes: {
banner: { sizes: [[300, 250], [300, 600]] }
},
bids: [
{ bidder: 'appnexus', params: { placementId: 123456 } },
{ bidder: 'rubicon', params: { accountId: 1001, siteId: 2002, zoneId: 3003 } }
]
}];
// 3. Request bids, then initialize GPT
pbjs.que.push(function() {
pbjs.addAdUnits(adUnits);
pbjs.requestBids({
bidsBackHandler: function(bidResponses) {
// Bids are back, initialize ad server
googletag.pubads().refresh();
},
timeout: 1500
});
});
3. Configuration: Ad Units, Bidders & Price Granularity
Ad Unit Definition
Each ad unit represents a single ad slot on the page. The code property must match the GPT ad slot's element ID. The mediaTypes object declares supported formats (banner, video, native), and the bids array lists all demand partners that should bid on this slot.
Price Granularity
Price granularity determines how bid prices are bucketed into key-value pairs for the ad server. Prebid.js provides several built-in granularity options:
| Granularity | Bucket Size | Max Price | Use Case |
|---|---|---|---|
| Low | $0.50 | $5.00 | Low-value remnant inventory |
| Medium | $0.10 | $20.00 | Standard publisher setup |
| High | $0.01 | $20.00 | Premium inventory with tight competition |
| Auto | Varies | $5.00 | Simplified configuration |
| Dense | $0.01/$0.05/$0.50 | $3/$8/$20 | Most popular; fine-grained at low prices |
The dense granularity is the most commonly used configuration because it provides fine-grained price buckets at lower prices (where most impressions trade) while coarsening at higher prices to avoid creating an unmanageable number of ad server line items.
// Configure price granularity
pbjs.setConfig({
priceGranularity: 'dense',
// Or define custom granularity:
/*
customPriceBucket: {
buckets: [
{ precision: 2, min: 0, max: 3, increment: 0.01 },
{ precision: 2, min: 3, max: 8, increment: 0.05 },
{ precision: 2, min: 8, max: 20, increment: 0.50 }
]
}
*/
});
4. Bidder Adapter Setup
Each demand partner in Prebid.js is represented by a bidder adapter. Adapters are included in the Prebid.js build at download time. Each adapter requires specific configuration parameters provided by the demand partner.
Common Adapter Configurations
// AppNexus (Xandr / Microsoft Advertising)
{ bidder: 'appnexus', params: { placementId: 13144370 } }
// Rubicon (Magnite)
{ bidder: 'rubicon', params: {
accountId: 14062, siteId: 70608, zoneId: 335918
}}
// PubMatic
{ bidder: 'pubmatic', params: {
publisherId: '156209', adSlot: '385198;300x250'
}}
// Index Exchange
{ bidder: 'ix', params: { siteId: '12345' } }
Each adapter's parameters are documented in Prebid.js's bidder reference. Publishers should work with their demand partner account managers to obtain the correct IDs and verify adapter configuration before going live.
5. Auction Flow
Understanding the Prebid.js auction flow is essential for debugging and optimization:
- Page load: Prebid.js initializes and queues ad unit definitions.
- requestBids(): The wrapper fires bid requests to all configured adapters in parallel.
- Adapter processing: Each adapter constructs a bid request specific to its exchange protocol and sends it to the exchange endpoint.
- Response collection: Adapters receive bid responses (bid or no-bid) and normalize them into Prebid.js's standard bid object format.
- Auction resolution: After the timeout expires (or all bids return), Prebid.js selects the highest bid per ad unit.
- Targeting set: The winning bid's price bucket and bidder name are set as key-value targeting parameters on the ad server's ad slot.
- Ad server call: The ad server evaluates header bidding bids alongside direct-sold campaigns and selects the final winner.
pbjs.getConfig('bidderTimeout') to check the current setting. A timeout of 1000-1500ms works for most publishers. Monitor actual response times via analytics and adjust the timeout to the 85th-90th percentile of partner response distributions.
6. Analytics Integration
Prebid.js provides a comprehensive analytics module that hooks into every stage of the auction lifecycle. Publishers can send auction data to Google Analytics, Adobe Analytics, or any custom endpoint for detailed reporting.
// Enable Google Analytics adapter
pbjs.enableAnalytics({
provider: 'ga',
options: { global: 'ga' }
});
// Or use a custom analytics adapter
pbjs.enableAnalytics({
provider: 'custom',
options: {
url: 'https://analytics.example.com/prebid',
sampling: 0.1 // Log 10% of auctions
}
});
Key analytics events include bidRequested (when a bid request is sent to an adapter), bidResponse (when a bid is received), bidWon (when a bid wins the auction and renders), auctionEnd (when the full auction completes), and bidTimeout (when an adapter fails to respond within the timeout window).
Third-party analytics platforms like Datawrk, Prebid Analytics with Simply, and Confiant offer specialized dashboards for header bidding performance monitoring, including bid density analysis, partner latency distributions, and revenue attribution by partner.
7. Troubleshooting
Common Issues
- Bids not being passed to the ad server: Check that Prebid.js completes before the GPT
refresh()call. Usepbjs.getAllWinningBids()in the browser console to verify winning bids are captured. - High timeout rates: Review adapter timeout configuration and partner endpoint health. A partner with >15% timeout rate should be investigated or removed.
- Ad server not recognizing bids: Verify that the targeting key-value pairs (
hb_pb,hb_bidder) match the line item targeting in Google Ad Manager. Mismatched granularity is the most common cause. - Creative rendering failures: Ensure the winning bidder's creative ID is correctly passed to the ad server. Check the browser console for JavaScript errors from the creative rendering script.
Debug Mode
Enable Prebid.js debug mode for detailed console logging during development:
pbjs.setConfig({ debug: true });
// Or append ?pbjs_debug=true to the page URL
8. Version Migration
Prebid.js releases major versions annually with breaking changes. Key migration considerations:
- Prebid.js 5.x to 7.x: The
mediaTypeproperty was renamed tomediaTypes(plural). Video configuration moved frommediaType: 'video'tomediaTypes: { video: {...} }. Ensure all ad unit definitions are updated. - Prebid.js 7.x to 8.x: Introduced GPP (Global Privacy Platform) support alongside TCF v2. The consent management module was restructured. Update
consentManagementconfiguration to use the new format. - Module system: Starting in v7, many features were moved to optional modules (e.g.,
consentManagementTcf,consentManagementUsp). Ensure required modules are included in your custom build.
multibid and testBidder modules for controlled A/B testing.
9. Performance Optimization
Build Size Optimization
A full Prebid.js build with all 300+ adapters can exceed 500KB. Use the Prebid.org download tool to include only the adapters you need. A typical production build with 8-12 adapters runs 80-150KB gzipped. Every unused adapter adds unnecessary JavaScript parsing time.
Lazy Loading
For pages with multiple ad slots (especially below-the-fold), implement lazy loading to defer Prebid.js auctions until the ad slot is near the viewport. Prebid.js supports this through the lazyLoad module, which triggers requestBids() only when the ad slot enters a configurable viewport threshold (typically 200-400px from the viewport edge).
Bidder Sequence Randomization
Prebid.js randomizes the order in which adapters are called by default. This prevents systematic latency advantages for adapters listed first in the configuration. Ensure you haven't disabled this randomization, as it ensures fair competition among demand partners.
Caching and Reuse
For single-page applications (SPAs) or infinite-scroll pages, use Prebid.js's built-in bid caching to reuse bids from previous auctions when the same ad unit configuration is requested again. Configure the auctionOptions with appropriate cacheTimeout values to balance freshness with performance.