Back to Blog
Best Practices November 10, 2025 4 min read

Lazy Loading Without Layout Shift: Core Web Vitals for Ad-Heavy Local News

Local news sites run many ad slots on long pages, which makes layout shift and slow interactions common. Here is how to lazy load ads and keep Core Web Vitals healthy without losing revenue.

HR
HBDR Research
November 10, 2025

Why local news feels this most

Local news pages tend to be long and busy. A typical article might carry a leaderboard, several in-content units, a sticky anchor, a sidebar, and widgets for weather, obituaries or school closings, all on audiences that skew toward mobile devices and older phones. Every one of those elements competes for bandwidth and main-thread time. When ads load without reserved space, content jumps. When scripts pile up, taps feel sluggish. Readers notice, and so do search engines.

The goal is not fewer ads for its own sake. It is loading the right ads at the right moment, in space that was set aside for them, without blocking the reader. That usually improves both user experience and revenue per session.

The metrics that matter

Google's Core Web Vitals measure three things. Largest Contentful Paint tracks how quickly the main content appears, with 2.5 seconds or less considered good. Cumulative Layout Shift tracks unexpected movement of page content, with 0.1 or less considered good. Interaction to Next Paint, which replaced First Input Delay as a Core Web Vital in March 2024, measures how quickly the page responds to taps, clicks and key presses, with 200 milliseconds or less considered good. Ads can hurt all three, but the most common problems are layout shift and slow interactions.

Stop the jumps: reserve space

Google's guidance on optimizing CLS is direct: reserve space for ad slots before the ad loads. In practice:

  • Set a minimum height on every slot container matching the most likely creative size for that position and breakpoint. For multi-size slots, use the smallest common size, or the most frequently served one if data shows a clear winner.
  • Do not collapse empty slots near the top of the page. Collapsing a reserved space after the page has rendered causes a shift. If a slot often goes unfilled, reconsider the slot rather than collapsing it.
  • Keep sticky and anchor units out of the flow. Fixed-position elements do not push content, but anything that inserts itself into the article body does.
  • Watch for creatives that resize. Some formats expand after rendering. Restrict sizes on positions where expansion would move content.

Load ads when they are needed

Lazy loading requests and renders ads only as the reader approaches them. Google Publisher Tag supports this through enableLazyLoad, documented in the GPT reference, with three settings:

  • fetchMarginPercent controls how far from the viewport, measured in viewport heights, a slot must be before its ad is requested.
  • renderMarginPercent controls how close it must be before the ad is rendered.
  • mobileScaling applies a multiplier to both margins on mobile, where scrolling is faster.

If you run header bidding, the auction for a lazy-loaded slot needs to happen before the ad server request, not at page load. The common pattern is to trigger the Prebid auction for a slot when it crosses a margin a little further out than the fetch margin, then call the ad server with the results. That gives bidders time to respond without auctioning slots the reader never reaches.

Tuning the margins

Margins that are too small cause blank slots as fast scrollers reach them before the ad arrives, which costs viewable impressions. Margins that are too large load ads that are never seen, which hurts viewability and wastes bids. Start with moderate settings, then test. Compare viewability, revenue per session and CLS across a few margin combinations over at least two weeks.

Keep interactions fast

INP problems usually come from long tasks on the main thread. Ad-related causes include large wrapper bundles, many identity modules, synchronous third-party scripts, and heavy creatives.

  1. Trim the wrapper. Build Prebid with only the adapters and modules you use. Remove bidders and ID modules that do not earn their cost.
  2. Load third-party scripts asynchronously and defer anything not needed for the first view.
  3. Spread work out. Stagger auctions for below-the-fold slots through lazy loading rather than running every auction at once on page load.
  4. Audit widgets. Weather, video players and social embeds often cost more main-thread time than ads do. Include them in your review.

A pattern that works for long article pages

A common local news layout is an article with an in-content ad every few paragraphs. A reliable setup looks like this: the first in-content slot loads with the page in reserved space; every later slot is defined with a fixed minimum height and lazy loaded; the Prebid auction for each later slot starts as the reader scrolls within a couple of screens of it; and the sticky anchor loads after the main content has painted. Spacing the in-content slots by content length rather than a fixed count keeps short articles from being crowded and long ones from being under-monetized.

Measure with field data

Lab tools are useful for debugging, but Core Web Vitals are assessed on real-user data. Collect field metrics from your own pages, segmented by template and device, and check how ad changes affect them. When you change lazy loading settings or slot layouts, look at CLS, INP, viewability and revenue together.

The takeaway

For ad-heavy local news sites, good Core Web Vitals and strong ad revenue are not in conflict. Reserve space for every slot, load ads close to when they will be seen, run header bidding auctions on the same schedule, and keep scripts lean. Most of the gains come from disciplined implementation rather than removing inventory. HBDR builds these practices into the setups it manages, and reviews them whenever templates or layouts change.

Tags: core web vitals cls lazy loading google publisher tag local news

Ready to maximize your ad revenue?

Get Started