How Ads Are Served
The complete impression lifecycle: slot discovery, viewport filtering, traffic quality gate, Prebid auction, lazy load trigger, creative render, viewability measurement, and smart refresh.
This article explains the full lifecycle of a single ad impression — from slot discovery through creative render, viewability measurement, and refresh — so you understand exactly what happens on your pages and why.
1. Slot discovery
When hb.js initialises, it scans the DOM for every element carrying both data-advlume-site and data-advlume-slot attributes. For each match it records the slot key, format, and any data-sizes fallback values, then applies the authoritative size list from the site config fetched from the CDN.
Before the auction runs, two size filters are applied:
- Viewport filter: any size wider than
window.innerWidthis removed from the slot's size set. If this leaves a slot with no valid sizes, the slot is dropped entirely for this page load (e.g. a 970×250 billboard on a 375px mobile screen). Video and outstream slots are exempt. - Responsive size mapping: if a slot's sizes include both mobile sizes (≤320px wide) and desktop sizes (>320px wide), the wrapper builds a GPT size mapping with two breakpoints — mobile below 768px viewport width, desktop above. GPT uses this to request only the correct sizes for each visitor.
2. Traffic quality gate (ADMD)
Before ads are served, the wrapper injects the traffic monitoring script (if configured for your site) and waits for a risk score. A score of 1 (high risk / non-human traffic) blocks all ad rendering for that session — GPT is never refreshed, protecting your account from invalid traffic penalties. All other scores proceed normally.
3. The header bidding auction
With valid slots and a clean traffic signal, the wrapper runs the Prebid auction in parallel with GPT slot definition. See How Header Bidding Works for the full step-by-step. The auction resolves within the 1,500ms timeout, and the winning bid's key-values are written to GPT before the ad request is sent.
4. Lazy loading (out-of-viewport slots)
Slots that are not visible in the current viewport are not auctioned on page load. Instead, an IntersectionObserver watches each slot element with a 800px root margin — meaning the auction fires when the visitor is within 800px of scrolling the slot into view, not when it's actually on screen. This gives the auction enough lead time to complete before the element becomes visible, preserving a smooth scroll experience while ensuring buyers get viewable impressions.
Slots in the viewport at load time are auctioned immediately. Slots below the fold wait for the scroll trigger. This behaviour cannot be disabled per-slot from the dashboard — it is applied to all banner placements by default.
5. Creative rendering
When GAM returns a winning creative, GPT renders it inside an iframe in the slot's container element. The wrapper then:
- Constrains the container to the exact rendered size. The winning creative's dimensions are read from the
slotRenderEndedevent (or thehb_sizekey-value for Prebid winners). The container div'swidth,height, andmax-heightare set to match, and any parent wrappers between the iframe and the container are similarly constrained. This prevents the ad from pushing layout elements around after load. - Collapses empty slots. GPT is configured with
collapseEmptyDivs(). If no creative fills — no Prebid winner and no AdX fill — the slot collapses to zero height automatically, avoiding a blank white gap. - Shows the "Ads by Advlume" label. A small, semi-transparent badge is injected over the top-left corner of the creative iframe. It expands to show the full label on hover and links to advlume.com.
- Identifies the win source. If
lineItemIdis present in the GAM render event, a Prebid price-priority line item rendered (Prebid won). IflineItemIdis null, AdX dynamic allocation served. This distinction is used when attributing CPM to the correct source in reporting.
6. Viewability measurement
After a creative renders, a second IntersectionObserver tracks viewability per the IAB standard: 50% of the ad in view for 1 continuous second. When this threshold is met, a bidViewable event is emitted to the real-time ingest endpoint with the slot, DSP, CPM, and size. This event powers the Live dashboard and the viewability metrics in reporting.
The viewability observer fires once per slot render — it resets when the slot refreshes.
7. Smart refresh
Once a slot has rendered, smart refresh takes over. A viewability-based timer runs while 50% or more of the slot is in the viewport:
| Parameter | Value | Notes |
|---|---|---|
| Refresh interval | 30 seconds | Timer resets if the slot leaves viewport |
| Max refreshes | 10 per slot per page session | Prevents runaway refresh loops on very long sessions |
| Min hidden time | 5 seconds | If the page is hidden (tab inactive) for less than 5s, the timer pauses |
On each refresh, the wrapper clears all hb_* targeting keys on the GPT slot and runs a fresh Prebid auction before calling pubads().refresh(), ensuring each refresh impression competes in a clean open auction.
8. Failsafe
3,000ms after slot display is triggered, the wrapper runs a failsafe pass: it checks each in-viewport slot for a rendered iframe. Any slot that is in view but has no iframe — indicating a stuck or slow creative — is force-refreshed with a new Prebid auction. This recovers impressions lost to GPT race conditions or slow creative loading.
What publishers see in DevTools
Every step above produces a log line visible in the browser console when DevTools is open:
[advlume] Config loaded for site {uuid}
[advlume] Viewport filter: dropped 1 slot(s) that don't fit
[advlume] Active bidders: adformOpenRTB, adkernel, …
[advlume] GAM targeting for advlume-leaderboard-top-0: {"hb_bidder":["…"],"hb_pb":["1.50"],"hb_size":["728x90"]}
[advlume] Ad rendered: advlume-leaderboard-top-0 path=/NETWORK/domain/slot via=lineItem advertiser=… lineItem=… creativeId=…
[advlume] Constrain advlume-leaderboard-top-0 to 728x90
[advlume] bidViewable: advlume-leaderboard-top-0 dsp=adformOpenRTB $1.50
Further reading
- Lazy Loading & Smart Refresh — configuration and tuning details
- Layout Shift (CLS) Issues — pre-reserving slot height to avoid CLS
- How Header Bidding Works — the auction that precedes every impression
- Console Errors & Debugging — reading the wrapper's log output
Last updated 2 months ago