What this page covers
- Line item types, priority waterfall, and how GAM selects a winner.
- Key-value targeting that connects header bidding and programmatic demand.
- Unified Pricing Rules — how floors interact with Open Auction demand.
Learning Track
Master line item priority, key-value targeting, Unified Pricing Rules, and systematic troubleshooting of delivery failures.
Intermediate track
This page is for practitioners who already know what GAM is and want operational depth: how line item priority actually resolves, how key-value targeting connects Prebid to GAM, and how to diagnose delivery failures systematically.
Google Ad Manager is the ad server that sits at the center of most large publisher ad stacks. It decides which ad wins every impression: a direct sponsorship, a programmatic bid, a house ad, or a backfill. Every revenue decision flows through GAM’s priority waterfall. A misconfigured line item — wrong priority, missing targeting, bad creative — can cause an entire campaign to under-deliver without any error shown in the UI. TAMs who understand GAM troubleshoot faster and communicate better with trafficking, yield, and DSP teams.
GAM evaluates every eligible line item in priority order for each ad request. Higher priority wins — regardless of price — unless the lower-priority line item is a programmatic or open auction type. Understanding this waterfall prevents conflicts and underdelivery.
| Type | Priority range | Reservation? | Typical use | Beats |
|---|---|---|---|---|
| Sponsorship | 4 | Yes (% of impressions) | Branded takeovers, SOV buys, home page 100% share | Everything below priority 4 |
| Standard | 8 | Yes (impression goal) | Guaranteed display campaigns with pacing | Network, Bulk, Price Priority, Open Auction |
| Network | 12 | No | Ad network fill (AdSense, third-party networks) | Bulk, Price Priority, Open Auction |
| Bulk | 12 | No (impression goal, no pacing) | Non-guaranteed inventory sell-through | Price Priority, Open Auction |
| Price Priority | 12 | No | Header bidding line items (Prebid) — compete by CPM | Open Auction, House |
| House | 16 | No | Own promotions, default ads, passbacks | Nothing (lowest priority — serves only when nothing else wins) |
| Open Auction (programmatic) | varies | No | DV360 open auction, other programmatic DSPs via Open Bidding | House; competes with Price Priority by CPM |
Ad request arrives for: homepage leaderboard (728x90), US, logged-in user
Eligible line items evaluated in order:
1. Sponsorship — "ACME Brand Takeover" (priority 4)
→ Targeting: homepage + US ✓ | Frequency: 3/day | User has seen 3 today
→ SKIPPED — frequency cap reached
2. Standard — "Winter Campaign 2024" (priority 8)
→ Targeting: article pages only ✗
→ SKIPPED — targeting does not match
3. Price Priority — Prebid HB line items (priority 12)
→ hb_pb=3.50 targets "3.50" key-value — line item CPM $3.50 ✓
→ hb_pb=4.20 targets "4.20" key-value — line item CPM $4.20 ✓
→ Both eligible — GAM selects highest CPM among Price Priority
4. Open Auction — DV360 programmatic (priority 12, competes by CPM)
→ DV360 returns $3.80 CPM in unified auction
Final decision: Prebid $4.20 wins over DV360 $3.80 and Prebid $3.50
Prebid creative renders. Win notice fires to AppNexus.
GAM records impression against that Price Priority line item.
Prebid sets key-values on the GPT ad request. GAM line items target those key-values to compete. The setup below is the standard pattern for connecting header bidding demand to GAM.
// After pbjs.setTargetingForGPTAsync() fires, each GPT slot gets these key-values:
googletag.pubads().getSlots().forEach(slot => {
console.log(slot.getTargetingMap());
});
// Example output for the winning bid from AppNexus at $3.50 CPM:
{
"hb_pb" : ["3.50" ], // Price bucket — must match GAM Price Priority line item CPM
"hb_bidder" : ["appnexus" ], // Winning adapter name — used for per-bidder line items
"hb_adid" : ["abc123def456" ], // Bid ID — Prebid uses this to look up and render the correct creative
"hb_size" : ["300x250" ], // Creative size — for targeting size-specific line items
"hb_source" : ["client" ] // 'client' = Prebid.js; 'server' = Prebid Server
}
// With enableSendAllBids: true, all bidders write keys (not just the winner):
{
"hb_pb_appnexus" : ["3.50" ],
"hb_pb_rubicon" : ["2.80" ],
"hb_pb_pubmatic" : ["3.10" ],
...
}
hb_pb equals 3.50. This is how GAM knows to serve this line item when Prebid sets that value on the ad request.<script> that calls pbjs.renderAd(document, '%%PATTERN:hb_adid%%'). The %%PATTERN:hb_adid%% macro substitutes the bid ID at serve time so Prebid renders the correct DSP creative.<script>
// Paste this into the GAM creative "Third party" creative type
var w = window;
for (var i = 0 ; i < 10 ; i++) {
w = w.parent;
if (w.pbjs) {
try {
w.pbjs.renderAd(document, '%%PATTERN:hb_adid%%' );
// %%PATTERN:hb_adid%% is replaced by GAM with the actual hb_adid value at serve time
} catch (e) { console.error(e); }
break;
}
}
</script>
UPRs replaced individual line item floors in GAM 360. They set a CPM floor that applies across all programmatic demand — Open Auction and Open Bidding. Any programmatic bid below the floor is filtered before GAM’s auction.
bidfloor param and your UPR is set separately in GAM, they are enforced at different layers and you must calibrate them independently.
| UPR dimension | Options | Guidance |
|---|---|---|
| Targeting scope | All inventory, ad unit, placement, geo, device | Start broad. Narrow to high-value placements once you have bid distribution data. |
| Floor type | Fixed CPM, Revenue share | Fixed CPM is simpler to audit. Revenue share is complex and rarely used by publishers. |
| Floor value | Any CPM in your currency | Set at the 25th–40th percentile of your historical clearing prices. Too high kills fill; too low doesn’t protect yield. |
| Bid landscape report | GAM → Reports → Bid Landscape | Use this before setting UPRs. Shows CPM distribution by buyer, placement, and geo — informs floor calibration. |
A Standard line item is pacing behind and will not hit its impression goal. Common causes: targeting too narrow, insufficient eligible inventory, frequency cap too tight, or competing line item taking impressions at higher priority.
▸ Open GAM Reports → Delivery → run a Delivery Diagnostics report for the line item. Check “available inventory” vs goal, and inspect the “lost due to” breakdown.
Header bidding bids are returning but the Prebid Price Priority line item never gets impressions. Either the key-value targeting in GAM does not match the hb_pb values Prebid is setting, or the line item CPM is wrong.
▸ Use GPT console (googletag.openConsole()) → Targeting tab to see live key-values. Compare the exact hb_pb string (e.g. “3.50”) against the GAM line item key-value rule. Character case and decimal format must match exactly.
The correct line item wins the auction but the wrong creative renders. Usually caused by creative targeting overrides, wrong size assignment, or multiple creatives on the line item without proper rotation settings.
▸ Check the creative’s own targeting (overrides line item targeting). Confirm creative sizes match the slot sizes. For Prebid line items, confirm the creative contains the correct pbjs.renderAd snippet and %%PATTERN:hb_adid%% macro.
Programmatic CPMs have dropped. Could be a floor set too high (reducing bid volume) or too low (reducing clearing price), or a change in buyer competition. UPRs changed without reviewing bid landscape first.
▸ Pull the Bid Landscape report in GAM. Check bid count trend over time. Compare clearing price against UPR floor value. If floor was recently raised, lower it incrementally and monitor fill rate vs CPM tradeoff.
House line items passback to a third-party network that passbacks back to GAM — creating a loop. Users see blank ads or experience slow load times. This is a trafficking error in the passback tag configuration.
▸ Trace the passback chain in the creative tags. Confirm the last tag in the chain does NOT call back to GAM. Replace with a static default creative or a direct ad network tag that serves its own inventory without passback.
A Sponsorship line item is trafficked at 100% share of voice for a placement, but other ads are still serving into that slot. Either the SOV targeting is not set correctly, or another line item has a higher priority (rare) or is ignoring frequency.
▸ Verify the Sponsorship is set to 100% for the exact ad unit path, not a parent unit. Check if any other line items share the same placement with incompatible SOV splits totaling more than 100%.
Run through this before activating any line item to catch the most common setup errors.
| Check | What to verify | Risk if skipped |
|---|---|---|
| Line item type + priority | Correct type (Standard/Price Priority/Sponsorship) set; priority matches business intent | Wrong type causes direct campaigns to lose to programmatic or vice versa |
| Dates and pacing | Start/end dates correct; pacing set to Even or Frontloaded as required by IO | Immediate pacing frontloads impressions; “Even” may under-pace on low-traffic days |
| Targeting | Ad unit, geo, device, key-value, audience segment targeting all reflect IO requirements | Over-narrow targeting causes underdelivery; over-broad targeting wastes impressions |
| Creative assignment | Correct creative(s) attached; sizes match slot; creative is approved and not in review | Missing or mis-sized creative causes blank ad or no delivery |
| Frequency cap | Cap matches IO; test that cap does not prevent pacing on low-volume audiences | Overly tight frequency cap on small audience means line item can never reach goal |
| Forecast check | Run Reach Forecast before save — confirm available impressions ≥ goal | Over-sold inventory; cannot deliver without overbooking or contention |
| Prebid key-values (if applicable) | hb_pb value matches line item CPM; hb_adid macro in creative is correct | Prebid bids never match GAM line item; header bidding revenue goes unmonetized |
gam-priority-test-notes.md — priority waterfall observations.gam-troubleshooting-sheet.md with symptom → cause → fix table.upr-calibration.csv — floor, fill rate before/after, CPM before/after.Enter any two values
to calculate the third
More tools coming soon