Field data decides, lab data diagnoses
A Lighthouse score is one synthetic run on one machine on one network. Core Web Vitals are assessed on the 75th percentile of real visits over 28 days. Reporting the first as if it were the second is how a site "passes" in a slide deck and fails in Search Console.
Two kinds of data, two jobs
Field data comes from the Chrome User Experience Report: real users, real devices, real networks, aggregated at the 75th percentile. That's what Google assesses and what the Page Experience signal reads. Lab data comes from a tool (Lighthouse, WebPageTest, a local trace) running a controlled load. It's reproducible, which is exactly what field data isn't, and that's the point: the lab is where you find out why the field number is what it is.
So the verdict is always field. If CrUX says LCP is 3.4 seconds at p75 on mobile, the page fails, however green the lab run looks. And the diagnosis is always lab, because CrUX will never tell you that the culprit is a 900 KB hero image served at the wrong size to a plugin-injected slider.
Work at the template level
Search Console groups URLs into "poor", "needs improvement" and "good" by example URL, which tempts people into fixing one page at a time. Don't. The performance profile of a WordPress site is set by its templates, so one fix to the single service template repairs every service page. Pull CrUX by URL where it exists, group by template, fix the worst template first, and measure the group.
This also keeps the reporting honest. "LCP improved on 34 service pages after the hero change" is a sentence a client can act on; "the homepage went from 78 to 91" is not.
The four usual suspects on healthcare sites
Practice sites on WordPress fail in the same handful of ways. After enough of them, the audit almost writes itself.
| metric | usual cause | usual fix |
|---|---|---|
| LCP | unoptimised hero image; render-blocking page-builder and plugin CSS | size and compress the hero, preload it, defer non-critical CSS, remove plugins the template doesn't use |
| CLS | booking widgets and review badges injected without reserved space; web fonts swapping late | reserve dimensions for injected embeds, set explicit aspect ratios, self-host fonts with size-adjust fallbacks |
| INP | long tasks from tag managers and chat widgets on the main thread during interaction | load third-party scripts after interaction or on idle, audit every tag, remove the ones nobody can name |
| TTFB | uncached dynamic pages on shared hosting behind no CDN | page caching, a CDN in front, and edge rules when the host can't be changed |
A note on booking widgets
Almost every practice site has one, and almost every one is injected by a script that resizes itself after paint. That's a layout shift by definition. The fix isn't to remove the widget; it's to give it a container with the height it will end up at, so the page doesn't move when it arrives. Ten minutes of CSS, and CLS on the contact template drops from red to green.
Measure it the same way Google does
CrUX has an API and a BigQuery dataset. Pull p75 for the site's origin and its key URLs monthly into the same BigQuery project that holds the Search Console export and the logs, and chart it in Looker Studio. Then a fix shipped in week two shows up as a field movement in week six, and the report can say so with the same data Google is reading.
Field data decides. Lab data diagnoses. Never report a lab score as the verdict.