TrafficTriage

Do Ads Affect Core Web Vitals? What Our Field Data Showed

By Ugur Saritepe · October 28, 2026

Ads do affect Core Web Vitals, and a PageSpeed score will not show you how much. On game-scout.app, Google's own field data moved with each of two ad scripts: phone LCP fell 232 ms after one came out, and CLS more than tripled within 11 days of the next going in. Every value stayed inside "good".

Where this came from

game-scout.app is my other site, a catalogue of curated game lists built on Next.js and hosted on Vercel. On 2026-08-19 I added the Journey by Mediavine ad script. A month later I took it out, and typed this to the assistant I work with:

Lets remove our ads script, it does not bring any value. It pays daily 0.02 to 0.10 Euro

The removal shipped on 2026-09-18. Nobody measured what it did to speed, and the note I left for myself said to look again after 2026-10-16. By then Google AdSense was on the site instead: the loader with Auto ads went in on 2026-10-07, set to load after the page. Five days later, on my phone:

We have Ads from Adsense but it is blocking most of the page.

So the overdue readout became a question with two changes in it: what did each ad script do to the numbers Google actually collects from visitors?

What Google's field data showed, window by window

The field data behind Core Web Vitals comes from real Chrome visits and is reported as the 75th percentile (the value three visits in four beat) over a rolling 28 days. Google's CrUX History API returns 25 of those windows a week apart, so each change can be lined up against the windows before and after it. I pulled game-scout.app at the origin level, phones first, on 2026-10-23.

CrUX History API
origin https://game-scout.app, phone, p75
result
window          LCP ms   INP ms   CLS    ads in the window
07-12..08-08     1,454       -    0.00   none
08-23..09-19     1,616      78    0.02   Mediavine, 27 of 28 days
09-13..10-10     1,397      84    0.02   Mediavine 6 days, AdSense 3
09-20..10-17     1,384     106    0.07   AdSense, last 10 to 11 days
2026-10-23

LCP tracked the Mediavine script. Largest Contentful Paint (how long until the biggest thing on screen has drawn) sat between 1,402 and 1,519 ms in the six windows ending 07-11 to 08-15, rose to 1,616 ms in the window with Mediavine on 27 of 28 days, and came down to 1,384 ms once it was gone. (The first two windows Google ever reported for the site, ending in late June and early July, read 1,690 and 1,591 ms, before any ad script existed, so LCP was not flat to begin with.) The share of phone visits with a good LCP went from 89% to 91%.

CLS and INP tracked AdSense. Cumulative Layout Shift (how much the page jumps while you read it) held between 0.01 and 0.02 for five weekly windows, then read 0.07 in the first window with AdSense in it, the highest value in the 25-week series. Interaction to Next Paint (the delay after a tap) rose from 78 to 106 ms, also a series high. The share of phone visits with a good CLS fell from 82% to 77%. That is what an ad that slides content down after the page has drawn looks like, and it fits what I saw on my phone.

Desktop moved less over the same two windows: LCP 1,494 to 1,513 ms, INP 42 to 47 ms, CLS 0.00 to 0.03.

Two ad scripts, two different signatures. The one that loaded early cost LCP; the one that placed ads after load cost CLS and INP. Neither pushed a metric out of Google's good band.

Why no window shows one change cleanly

A 28-day window blends everything that shipped in it. The gap between the two scripts was 19 days, shorter than one window, so there is no window with no ads in it at all. The 09-13 to 10-10 window, which reads the lowest LCP, still had six days of Mediavine and three of AdSense. Mediavine's own servers were blocked by our firewall most of the time until 2026-08-27, so how many ads it actually filled in its first week is unknown. Every window also carries other deploys: list-card changes, a rewrite of how pages read the catalogue, and new pages every day.

So the honest reading is direction and signature, not size. The LCP drop of 232 ms is the cleanest number here and is still not the ad script alone. The AdSense read is 10 to 11 days out of 28; the first window with AdSense on every day ends around 2026-11-04 and reaches the History API on the Monday after.

What the PageSpeed score saw: almost nothing

The same day I ran our get_core_web_vitalstool, which reads Google's PageSpeed Insights, on the detective games list and the home page.

get_core_web_vitals
https://game-scout.app/best/best-detective-games
result
field  LCP 1,481 ms   INP 112 ms   CLS 0.06   (fieldSource "url")
lab    score 0.98   LCP 1,801 ms   CLS 0   TBT 141 ms
2026-10-23

The lab half is Lighthouse: one simulated phone load, scored out of 1. It gave the list 0.98 and a lab CLS of 0. Of the 70 network requests Lighthouse recorded, 2 went to Google's ad servers. The home page scored 0.68 for its large images, with a lab CLS of 0 and 2 ad requests out of 144. Lighthouse finished before Auto ads placed anything, so the layout shift the field data caught never happened in the test. Google's PageSpeed Insights documentation says field data covers the previous 28-day collection period, which is the half to read when ads are the question.

Our own tool reported site data as page data

Look at the field values again: the home page returned exactly the same LCP 1,481, INP 112 and CLS 0.06 as the detective list. Two pages with different layouts and different traffic do not share three percentiles. Our tool labelled both fieldSource "url", and the dashboard prints that as "this URL".

The raw PageSpeed response says otherwise. For both pages the page-level block carries the origin as its id and origin_fallback: true, Google's flag for a page with too few Chrome visits, where it substitutes data from every page on the site. The History API agrees: the detective list has no page-level record after early September. Our code treats the page-level block as page data whenever it has numbers in it and never reads the flag. We have not fixed it yet.

"loadingExperience": {
  "id": "https://game-scout.app",
  "origin_fallback": true,
  ...
}

For a small site this matters more than the score does. Most pages on a site like game-scout will never have their own field data, so "my page is fast" usually means "my site is fast on average", and an ad that only appears on some templates is diluted across all of them.

Does any of this matter for rankings?

Not at these values. Google's Core Web Vitals page sets good at LCP within 2.5 seconds, INP under 200 ms and CLS under 0.1, and says good results align with what its ranking systems reward, not that they guarantee anything. game-scout stayed inside all three on both devices through both ad scripts. Core Web Vitals works as a tiebreaker; a site in the good band gains nothing measurable by going deeper into it.

The CLS number is the one I would watch. 0.07 is 70% of the way to the line after 10 or 11 days of Auto ads, and the window that is all AdSense has not been read yet.

What we have not done

We have not fixed the origin-fallback label in get_core_web_vitals. The history above came from a script against Google's CrUX History API, not from our tool, which does not expose it. I have not changed any AdSense setting in response to the CLS rise, and I have not measured which page templates the shift comes from, because origin data cannot say.

How to check whether ads are hurting your Core Web Vitals

  1. Write down the day the ad script went live.Your deploy history has it. Good: a date. Bad: "sometime last month", which makes every window ambiguous.
  2. Read field data, not the score. In PageSpeed Insights, the top section is the field data. Good: you compare LCP, INP and CLS percentiles. Bad: you compare two Lighthouse scores, which on our site could not see the ads at all.
  3. Check whether the field data is your page or your whole site. If PageSpeed Insights says it is showing the origin, or the API response has origin_fallback: true, the numbers cover every page. Good: page-level data for the template that carries the ads. Bad: two different pages with identical percentiles.
  4. Compare a 28-day window fully before the change with one fully after. That means waiting four weeks. Good: windows that do not touch the change date. Bad: reading the week after and calling it done.
  5. Match the metric to the script.A script that loads early shows up in LCP; ads that are placed after load show up in CLS and INP. If a metric crosses out of good (LCP 2.5 s, INP 200 ms, CLS 0.1), reserve the ad slot's space or move it below the first screen before deciding the ads have to go.

Speed is not one of the eight checks in the free triage report, which looks at whether Google can crawl and index the page at all. A related case of analytics and consent tags getting in the way of the numbers is why GA4 and Search Console disagree on clicks, and the other measured reads are in the AI-assistant SEO series.

FAQ

Do ads affect Core Web Vitals?

Yes, and the field data shows it even when a lab test does not. On game-scout.app, phone LCP at the 75th percentile fell from 1,616 ms to 1,384 ms after one ad script came out, and CLS went from 0.02 to 0.07 within 11 days of Google AdSense Auto ads going in. All of it stayed inside Google's good thresholds.

Why does PageSpeed Insights show a good score when my site has ads?

Because the Lighthouse score is one simulated page load, and a lazy-loaded ad script often has not placed an ad by the time it finishes. On our list page Lighthouse scored 0.98 with a lab CLS of 0 and made 2 ad requests out of 70, while the field CLS for the same site read 0.06. Use the field data section, not the score.

How long does it take for Core Web Vitals to update after a change?

About four weeks for a clean read. Field data is a rolling 28-day window, so a change is fully reflected only once every day in the window comes after it. Google's CrUX History API updates each Monday with data to the previous Saturday, which adds up to a few more days.

Is the PageSpeed Insights field data for my page or my whole site?

It depends on traffic. When a page has too few Chrome visits, PageSpeed Insights falls back to origin data, which covers every page on the site. The raw API marks this with origin_fallback set to true. Two different pages on our site returned identical field values for exactly that reason.

The field half of this check is one tool call. Connect the TrafficTriage MCP server to your assistant and ask it for Core Web Vitals on the page that carries your ads. It returns the real-user LCP, INP and CLS with Google's own labels, plus the Lighthouse run for debugging. Until we fix the label, ask the assistant to compare two pages: identical field numbers mean you are looking at site-wide data.

Connect TrafficTriage to your assistant

Claude running a scheduled TrafficTriage daily check: a Search Console report on a real site, summarized with clicks, impressions, and the one query cluster that lost rank

In your AI assistant

Ask your AI about your own site

TrafficTriage plugs into Claude, Cursor, and ChatGPT. Your assistant runs the 8 checks, reads your Search Console data, and can even check your site every morning. Free account, no API key, nothing to install.