Plenty of publishers have years of GPT code embedded in their CMS templates, their AMP pages and their app webviews. Being told that adopting header bidding means rewriting all of it is often what kills the project.
It does not. There are two integration models, and the choice between them is about ownership, not capability.
Model A — the wrapper owns the slots
You remove your defineSlot calls and let the platform define, size, target and refresh everything. You get central control: sizes, lazy loading, refresh and collapse behaviour are all managed from one place, and changing them does not require a deploy.
The cost is that your ad rendering now lives outside your codebase.
Model B — you own the slots, header bidding attaches
Your page keeps defining its own slots. The wrapper reads them, matches each to a configured ad unit, and contributes bids. In ssm.codes this is the dfp_hb ad unit type.
You keep your existing code and your existing deployment process. What you give up is central control of the things you did not hand over — if a slot's sizes are wrong, that is a template fix, not a dashboard change.
Matching units to slots
The mapping needs a stable key. In order of reliability: the ad unit path as passed to defineSlot, the div id the slot renders into, or the GPT slot element id. Paths are the most robust because they rarely change; div ids are convenient but tend to get regenerated by CMS templates, which breaks the mapping silently.
// Your existing code — unchanged.
googletag.cmd.push(function () {
googletag.defineSlot('/1234567/homepage_top', [[970,250],[728,90]], 'div-top')
.addService(googletag.pubads());
googletag.enableServices();
});
// Configured in the dashboard as a dfp_hb unit:
// path = /1234567/homepage_top
// sizes = 970x250, 728x90 (must match the slot)
// div = div-top
The one thing you must get right
The ad request still has to wait for the auction. If your page calls googletag.pubads().refresh() or relies on enableSingleRequest() firing immediately on load, the request goes out before any bid arrives and header bidding contributes nothing.
So one line does change: the moment the ad request fires. Either hand that trigger to the wrapper, or gate your own refresh on the auction completing. Everything else — slot definitions, sizes, targeting, your own key-values — stays untouched.
Symptom of getting this wrong: the debug output shows healthy bids, and the ad server reports zero header bidding revenue. That is always a timing or targeting-order problem, never a demand problem.
Sizes have to agree
If the slot accepts 728×90 and the ad unit is configured for 300×250, you will get bids that cannot render. The impression is logged, no creative appears, and your discrepancy grows. Audit this first whenever a dfp_hb unit underperforms.
Related questions
What is a dfp_hb ad unit?
An ad unit type that adds header bidding to a Google Ad Manager slot defined in the publisher's own page code, rather than defining the slot itself. The wrapper matches it to the existing slot by ad unit path or div id, runs the auction, and writes price targeting onto that slot before the ad request fires.
Do I lose lazy loading or refresh if I keep my own slots?
Partly. Features that depend on the wrapper controlling when a slot is requested — lazy loading, refresh, collapse-on-empty — need the wrapper to own the request trigger. You can hand over just the trigger and keep your slot definitions, which recovers most of it. Full central control requires the wrapper owning the slots.
Can I mix both models on one site?
Yes, and it is a good migration path. Convert one template at a time: leave the legacy sections as attach-mode units and let the wrapper own slots in newly built templates. Nothing in the auction cares which model a given unit uses.
Why do I see bids but no header bidding revenue?
Almost always one of three things: the ad request fired before the auction finished, the targeting was set after refresh() instead of before it, or your ad server line items are not targeting the wrapper's key-values correctly. Check in that order — the first is by far the most common.
Try it on your own site
Free up to 1 million ad impressions a month. You keep your Ad Manager account and your SSP contracts.
Start free