How to serve other people’s ads on your own website — and why it is a completely different world from Google Ads.
1. The three names everyone confuses
Before anything else, we need to clear up a naming disaster. Google has three products whose names are almost identical, and mixing them up leads entire projects astray:
| Product | Who uses it | What it does |
|---|---|---|
| Google Ads | Advertisers (buy side) | You buy ad space to promote your own business on Google Search, YouTube, and partner sites. |
| Google Ads Manager Account (MCC) | Agencies & freelancers (buy side) | An umbrella login on top of Google Ads. It runs no campaigns itself — it lets an agency manage many client Google Ads accounts from one dashboard (up to 85,000 linked accounts). |
| Google Ad Manager (GAM) | Publishers (sell side) | You sell ad space. It is an ad server: it decides, in real time, which advertiser’s creative appears in each slot on your website. |
This article is about the third one: Google Ad Manager (GAM) — the platform you use when the ads on your site are not yours. You own the shelf space; advertisers rent it.
The key mental shift: in Google Ads you think in campaigns, keywords, and bids to win someone else’s audience. In GAM you think in inventory, orders, and priorities to arbitrate between advertisers competing for your audience.
2. What Google Ad Manager actually is
Picture a digital billboard in a train station, where someone decides — at the very second you look at it — which poster to display. GAM is that “someone”: an ad server. It sits on Google’s infrastructure and waits. Every time a page on your site loads with an empty ad slot, the page raises its hand and asks: “I have a free slot, what should I display?” GAM looks at every campaign that could match, applies priority rules, and answers with the winning creative — or with an empty response if nothing matches (a no-fill).
Two halves make the system work:
- GAM (server side) — the brain. Holds your inventory definitions, the campaigns (orders and line items), the creatives, and the decision logic.
- GPT (Google Publisher Tag, site side) — the mouth. A small JavaScript library (
gpt.js) embedded in your pages that describes each slot, calls GAM, and injects the returned creative into the right<div>.
GAM does nothing on its own. If GPT is not deployed on a page, that page generates zero ad requests and therefore zero impressions — no matter how perfectly the server side is configured. This is not theoretical: real-world audits regularly find sites showing 0 impressions for a whole quarter simply because the tag was never published on the production templates.
3. The building blocks (inventory model)
You describe your world to GAM with a small set of stacked bricks:
your GAM account — numeric code, e.g. 1234567
travels in every ad request
the shelves — each has an address
/1234567/SITE_TOP_BANNER↓ can be grouped into
PLACEMENTS (bundles sold together)
↓ contain
LINE ITEMS
which ad units · sizes · dates ·
priority · targeting
↓ carry
CREATIVES (image, HTML5, video)
section=politics, pageID=1234- Network — your GAM account, identified by a numeric network code. It travels inside every ad request like a postal code.
- Ad unit — one sellable slot, with a full path such as
/NETWORK_CODE/UNIT_NAME. This path is the key: the page and the server must pronounce it identically or they will not understand each other. - Placement — an optional grouping of ad units you sell as a package.
- Order + line items — an order represents a deal with one advertiser; each line item inside it says where to show (which ad units), what (sizes, creatives), when (flight dates), and how strongly (priority). A reserved “guaranteed” line beats an auction-based line.
- Creative — the visual itself (image, HTML5, third-party tag, video).
- Key-values — optional labels the page attaches to its request (“this page = politics section, id = 1234”) so line items can target or exclude finely.
⚡ TL;DR — Network > ad units (path = matching key) > placements; orders > line items (targeting + priority) > creatives; key-values refine. GAM only reacts when a page asks.
4. The life of an ad request
Here is the full round trip — the thing you must be able to replay in your head when debugging:
gpt.jsdefineSlot('/NETWORK/UNIT', [[728,90]], 'div-id')+ options:
enableSingleRequest(), consent, lazy loaddisplay('div-id') / refresh() → HTTP callsecurepubads.g.doubleclick.net/gampad/ads(unit path, sizes, key-values, consent signals)
creative returned →
GPT injects it into the
<div>empty response →
GPT collapses the
<div> (height 0)GPT performs three gestures, always in this order:
- Declare the slot —
googletag.defineSlot('/1234567/SITE_TOP', [[728,90]], 'div-gpt-top'): the exact ad unit path (same as in GAM), the accepted sizes, and the id of the HTML<div>that will host the ad. - Set options —
pubads().enableSingleRequest()(SRA), consent handling, lazy loading,collapseEmptyDivs(). - Fire —
googletag.display('div-gpt-top')(orrefresh()): only now does the real network call togampad/adsleave the browser.
The golden rule: GAM and GPT must pronounce exactly the same ad unit path. If the page asks for an address GAM doesn’t know (typo, wrong path), GAM finds nobody and returns empty. The ad fails not because the campaign is misconfigured, but because the question was badly asked. Conversely — and this trips people up — an empty response with a perfectly correct path means the blocker is on the server-side matching (expired order, size mismatch, targeting, unverified site…).
⚡ TL;DR — defineSlot (path + sizes) → options → display() = one gampad/ads request. Path must match GAM exactly. Empty answer = no line item matched; the response body tells you more than the console.
5. How GAM decides: line item types and priorities
This is where GAM differs most radically from Google Ads. In Google Ads, an auction decides everything. In GAM, you define a waterfall of priorities, and the auction only fills what your direct deals leave over.
| Line item type | Priority (default) | Typical use |
|---|---|---|
| Sponsorship | 4 | “Advertiser X owns 100% of this slot for the period” — share-of-voice deals, roadblocks, homepage takeovers |
| Standard | 6 / 8 / 10 | Classic guaranteed campaigns: deliver N impressions between two dates; GAM paces delivery automatically |
| Price Priority | 12 | Non-guaranteed: serves only if nothing above wants the impression, at a fixed price |
| Network / Bulk | 12 / 16 | Remnant fillers |
| House | 16 | Self-promotion, defaults when nothing else fills |
| AdSense / Ad Exchange backfill | dynamic | The programmatic auction competes for whatever direct sales don’t take |
Lower number = higher priority. A Sponsorship (4) line always beats a Standard (8) line, which beats programmatic backfill. This waterfall is the entire point of GAM: it lets a sales team promise “your banner will be on the homepage all of March” and guarantee it against the open auction.
Contrast with Google Ads — there is no equivalent concept on the buy side. An advertiser in Google Ads can only bid harder; a publisher in GAM can simply decree who wins.
6. Configuration points, end to end
The practical checklist for setting up a GAM network, in the order that avoids rework.
6.1 Network level (Admin → Global settings)
- Note your network code — it will prefix every ad unit path.
- Time zone and currency (affects flight dates and reporting).
- User access: invite traffickers/admins with appropriate roles (Administrator, Trafficker, Salesperson, Report-only…).
6.2 Inventory
- Ad units (Inventory → Ad units): create one per slot template, with clear hierarchical naming (
SITE_SECTION_POSITION, e.g.NEWS_HOME_TOP_BANNER). Avoid a flat list of units with typos — inconsistent naming (“LATTERAL” vs “LATERAL”) is a real-world classic that poisons trafficking forever. - Sizes: prefer standard IAB formats (300×250, 728×90, 970×250, 320×50, 300×600). Exotic in-house sizes (1000×123, 1800×800…) work for direct deals but are incompatible with programmatic demand.
- Placements: group units you sell as bundles.
- Sites (Inventory → Sites): declare and verify every domain that will request ads. Verification typically relies on your
ads.txtfile or a tag. An unverified site sits with a “Needs attention” badge, and unrecognized domains are a documented cause of chronic no-fill even for reserved campaigns. - ads.txt: publish
https://yourdomain.com/ads.txtlisting your authorized sellers. For pure direct-sold setups there may be no AdSensepub-ID to list (that ID only exists if you use AdSense/AdX) — but the file still matters for site verification and becomes mandatory the day you open programmatic. An ads.txt containing a wrong publisher ID is worse than an empty one.
6.3 Tagging (the site side)
- Generate GPT tags per ad unit, or hand-write them:
gpt.jsin<head>,defineSlot+ a<div>per slot, onedisplay()per slot. - Deploy on the real production templates — via hardcoding or a GTM custom HTML tag. Either works; hardcoding is often more robust for ad slots, while measurement tags (GA4, CMP) live comfortably in GTM. What matters is that someone actually publishes it — an unpublished tag means zero requests forever.
- SRA (Single Request Architecture):
enableSingleRequest()sends all the page’s slots in one call — required for roadblocks (guaranteeing competing ads don’t share a page) and better for consistency. collapseEmptyDivs()so no-fills don’t leave white holes.- Lazy loading for below-the-fold slots — a direct lever on viewability (moving from ~35% to 60%+ viewability changes what your inventory is worth).
- Key-values: send structured context (
site,section,pageID…) withsetTargeting(). Define the keys in GAM first (Inventory → Key-values).
6.4 Privacy and consent (not optional in the EEA)
- Install a CMP (Consent Management Platform) certified for IAB TCF v2.3 (Didomi, Axeptio, Sourcepoint…). Without a TCF consent string, requests fall back to limited/non-personalized modes (
npa=1,ltd=1), which crushes CPMs (personalized demand typically pays 3–5× more) and can restrict serving altogether for EEA traffic. - Configure Privacy & messaging → European regulations at the network level — a brand-new network has nothing configured there, and that gap combined with consentless test traffic is a classic hidden blocker.
- Make sure your test pages carry the CMP too, or your tests will run in a different consent mode than production and mislead you.
6.5 Trafficking a campaign (the daily workflow)
- Order — create one per advertiser deal (advertiser, salesperson, dates).
- Line item — choose type/priority, flight dates, goal (impressions or %), rate, then targeting: ad units and/or placements, geography, device, key-values. Two silent killers to double-check:
- End date: an expired order stops serving everywhere, instantly — the #1 cause of “the ads suddenly disappeared”.
- Key-value exclusions: a line excluding
pageID = Xis harmless while no page sendspageID, and becomes a bomb the day the site starts sending it.
- Creatives — upload one per booked size. A size declared in the page’s
defineSlotbut missing from the line item’s creatives = no match for that request (GAM only considers creatives matching the requested sizes during selection). - Preview and check delivery after launch (see §8).
6.6 Opening up to programmatic (when ready)
- AdSense backfill — one checkbox per ad unit; fills unsold impressions with the AdSense auction. Zero risk, modest revenue.
- Ad Exchange (AdX) — Google’s premium exchange (requires eligibility/GAM 360 or an MCM partner); real-time competition from many buyers.
- Header bidding (Prebid.js) — external exchanges bid before the GAM call; their bids enter GAM as key-values matched by price-priority line items.
- Open Bidding — Google’s server-side equivalent.
- Set real rates on direct line items (even informational): a system where every deal is booked at €0 gives you reports with impressions but no revenue visibility.
7. Direct sold vs programmatic — the two revenue engines
price: as negotiated
AdX / Open Bidding / Prebid
or 🏠 house ad / collapse (no-fill)
| Direct sold | Programmatic | |
|---|---|---|
| Who sells | Your sales team, human negotiation | Automated auction |
| Pricing | Fixed (CPM/CPD/flat), agreed offline | Dynamic, per impression |
| Booking | Orders + line items, manually trafficked | Demand connects via AdX/Prebid |
| Formats | Anything you agree on (including custom sizes) | Standard IAB sizes only, in practice |
| Guarantee | Yes (Sponsorship/Standard) | No |
| Typical role | Premium inventory, brand deals | Fill the remnant, price discovery |
Mature publishers run both: direct deals take the premium slots at guaranteed prices, programmatic monetizes everything left over.
8. Debugging: the toolkit that actually works
GAM ships with excellent diagnostic tools; knowing them turns week-long mysteries into 5-minute checks.
Google Publisher Console — append ?google_console=1 (or ?googfc) to any page URL that loads GPT. A debug panel opens showing every slot, its unit path, the request status, and fill/no-fill per slot. Crucial detail: it only activates if the page already loads gpt.js — on an untagged page the parameter does nothing (which is itself a diagnostic: no console = no GPT = no requests). It works on production pages; it is a viewer, it changes nothing.
The Network tab — find the gampad/ads request. Read iu= (the requested unit path) and the sizes, and compare against GAM. A 200 OK with a tiny/empty body is a no-fill (Google’s docs: 200 = “an ad OR a blank response was returned”). An empty body with a correct iu means the blocker is server-side matching, not the tag. Also read the consent params: npa=1, rdp=1, ltd=1 = the request went out in limited-ads mode without TCF consent.
Delivery Tools → Inspect webpage ads — GAM’s native inspector: give it a URL and the line item you expect, and it returns Google’s official verdict (e.g. “Line item not found — the line item is not targeting as expected or is not serving”), plus a per-dimension targeting breakdown.
Ad Request Simulator — replays an exact captured request against the ad server and lists which line items were candidates. If your line is absent from the candidate pool while its targeting looks right, the block is upstream of the line item (site recognition, consent, network-level).
Line item → Troubleshoot tab — shows delivery causes (“line item always delivers, no non-delivery reasons”) and creative render rates.
Reports — a Domain × Ad server impressions report instantly reveals whether a site has ever served (a domain at 0 impressions over a quarter = chronic, structural problem, not a recent regression).
Field-tested failure catalogue
Real causes of “the ads don’t show”, roughly ordered by how often they bite:
- GPT never deployed on production templates — the site emits zero requests. Symptom: no
gpt.js, nogampad/adsin the Network tab. Beware static<img>banners hardcoded in the CMS that look like ad serving but generate 0 GAM impressions. - Order/line item expired — everything worked yesterday, empty responses today, on every domain at once. Check flight end dates first.
- Ad unit path mismatch — typo or wrong network code in
defineSlot. - Size mismatch — the page requests sizes the line item has no creative for.
- Site not declared/verified in Inventory → Sites — reserved campaigns can be blocked on unrecognized domains; the “Needs attention” badge means verification is incomplete (often because
ads.txtis missing or wrong). - ads.txt with a wrong publisher ID — worse than absent; blocks domain trust.
- Consent chain broken — no CMP/TCF on the page →
ltd=1limited mode → EEA demand restricted, CPMs crushed. - Key-value exclusion trap — an exclusion that was dormant activates when the site starts sending that key.
- Test page vs production divergence — the test page has GPT but no CMP, production has CMP but different tags; you end up debugging a configuration that exists nowhere.
Method note: debug by differential. Compare a working page and a failing page captured at the same time (same request minutes). One variable at a time; every hypothesis must survive a hard proof (HAR capture, UI screenshot, official Delivery Tools verdict) before you act on it.
9. KPIs: publisher metrics vs advertiser metrics
Another deep difference with Google Ads. Advertisers optimize acquisition cost; publishers optimize yield.
| Google Ads (advertiser) | Google Ad Manager (publisher) |
|---|---|
| Impressions, CTR | Ad server impressions, per domain/unit/advertiser |
| CPC — what a click costs you | eCPM — what 1,000 impressions earn you |
| CPA / ROAS — cost per result | Fill rate — % of requests that returned an ad |
| Quality Score | Viewability (% of impressions actually seen — target 60%+) |
| Impression share (auction) | Delivery/pacing — is a guaranteed line on track for its goal? |
| Conversion volume | Programmatic vs direct revenue split |
A publisher’s daily dashboard: impressions by site and unit, fill rate, eCPM by demand channel, viewability, and delivery health of guaranteed lines.
10. Quick-start checklist
- ☐ Network: code noted, timezone/currency set, users invited
- ☐ Ad units created with clean hierarchical naming, IAB sizes
- ☐ All domains declared and verified in Inventory → Sites
- ☐
ads.txtpublished and correct on every domain - ☐ GPT deployed on production templates (verified in the Network tab:
gpt.js+gampad/adspresent) - ☐ SRA +
collapseEmptyDivs+ lazy loading configured - ☐ CMP (IAB TCF v2.3) live on production and test pages; European regulations configured in Privacy & messaging
- ☐ First order + line item + creatives for every booked size; end dates sane
- ☐ Test with
?google_console=1; confirm fill on a real article page - ☐ Reporting: domain-level impression report scheduled; rates set to real values
- ☐ Runbook written: “ads not showing” → Publisher Console → Network tab → Delivery Tools → Simulator
11. Summary
Google Ads spends money to place your ads on other people’s screens. Google Ad Manager earns money by orchestrating other people’s ads on your screens — a server-side brain (network, ad units, orders, line items, creatives) paired with an on-page mouth (GPT) that must pronounce the exact same ad unit paths. Its superpower over any auction-only system is the priority waterfall: guaranteed direct deals always beat programmatic backfill. Its fragility is the number of silent single points of failure — an unpublished tag, an expired order, an unverified domain, a missing consent string — each of which produces the same symptom: an empty slot. Configure the foundations in order (inventory → sites/ads.txt → tags → consent → campaigns → programmatic), and learn the four debug tools; they turn every empty slot from a mystery into a diagnosis.