How to monitor performance across multiple sites and catch regressions
How an agency tracks Core Web Vitals across many sites: CrUX, its own RUM, scheduled tests, budgets, post-deploy alerts and client reports.
On this page 10 min read
- Field and lab data have different roles
- CrUX field data: what each access method provides
- Your own RUM: same-day data with the cause
- Scheduled lab tests without being fooled by variance
- Performance budgets per page type
- Regression alerts after a deploy
- Segmenting by page template and by device
- Client report
- How to do this with WebVyze
To track Core Web Vitals across many sites and catch regressions in time, an agency needs two sources working together. Field data tells you whether real visitors are having problems: Google's CrUX gives the overall picture for free, but with a delay of up to 28 days, and your own collection (RUM) shows the effect of a deploy within hours and points to the cause. Scheduled lab tests, with several runs compared by the median, catch the regression before or right after release. On top of that come performance budgets per page type, alerts tied to the time of the deploy, breakdowns by page template and by device, and a report that separates field data from test results.
This text applies to Google's public tools and limits as of October 2026. It does not compare commercial services; it covers categories of tools and what each data source allows.
Field and lab data have different roles
Field data comes from real visits. Lab data comes from a simulated page load, with a fixed device, network and location. web.dev recommends using field data to measure and prioritize and lab data to diagnose (web.dev, Core Web Vitals tools). The two diverge for known reasons: an empty cache in the test, a single device and network, no scrolling or clicking, personalized content and the fact that field data is a 28-day distribution (web.dev, lab and field differences).
For a portfolio of sites, this becomes a working rule: the alert that matters to the client is the field alert, and the lab test is there to catch the regression early and explain the cause. The full comparison between the sources is in Lighthouse, CrUX and RUM; the thresholds for each metric are in the Core Web Vitals guide.
CrUX field data: what each access method provides
CrUX (Chrome User Experience Report) has three programmatic access methods. They differ in frequency, granularity and cost.
| Access | Update | Granularity | Period | Cost and limits |
|---|---|---|---|---|
| CrUX API | Daily, around 04:00 UTC, with no guaranteed time | Origin or URL; phone, desktop, tablet or all | Rolling average of the last 28 days | Free, with a Google Cloud API key; 150 queries per minute per project, with no option to pay for more |
| CrUX History API | Weekly, on Mondays around 04:00 UTC, with data up to the previous Saturday | Origin or URL; breakdown by device | Weekly series of 28-day windows: 25 periods by default, up to 40 | Free; shares the 150 queries per minute quota with the CrUX API |
| CrUX on BigQuery | Monthly, on the second Tuesday of the following month | Origin | Full month, with history back to 2017 | Free within the BigQuery free tier; above it, billed to the Google Cloud account |
Sources: CrUX API, CrUX History API and CrUX on BigQuery. To see the weekly series without writing code, CrUX Vis shows History API data in charts.
To find out whether the quota is enough, do the math. An example: 40 sites, each with the origin plus 5 important URLs, queried for mobile and desktop, add up to 480 queries per day, which fits in just over 3 minutes at the limit of 150 per minute.
Three limitations matter for monitoring:
The 28-day window smooths everything out. A regression shipped today enters the average gradually and only shows up in full weeks later. That works for trend reports, not for deploy alerts (web.dev).
Not every site or URL has data. Only pages and origins that are publicly discoverable and have enough visits are included; the minimum is not disclosed. Small sites in the portfolio may have no URL data, or not even origin data (CrUX methodology).
Only Chrome users on desktop and Android who meet the collection criteria are included. Visits from other browsers do not appear (CrUX methodology).
Your own RUM: same-day data with the cause
RUM (real user monitoring) is data collected by a script on the site itself, which sends each visit's metrics to your own server or to a service. web.dev recommends building this dataset of your own and using CrUX as a comparison (web.dev). A ready-made base is the web-vitals library from the Chrome team, which measures LCP, INP, CLS, FCP and TTFB the same way Chrome measures them for Google's tools. It is about 3 KB compressed with brotli; the attribution build adds about 1.5 KB and reports the element or interaction that caused each value (web-vitals).
Some implementation precautions, according to the library's documentation and web.dev:
Send the data when the page becomes hidden (the
visibilitychangeevent), withnavigator.sendBeacon(), and not onunloadorbeforeunload(web-vitals).Send the diagnostic information along: the LCP element, the target and type of the INP interaction, the element of the largest CLS shift. When you aggregate these targets across all visitors, the elements that weigh most on the p75 stand out (web.dev, debug performance in the field).
LCP, INP, FCP and TTFB values work in Chrome, Firefox and Safari; CLS, for now, only in Chromium browsers (web-vitals). When comparing RUM with CrUX, filter for Chrome to compare the same population.
The script collects visitor data. Do not send anything in the beacon that identifies the person, such as an email address or URL parameters with personal data, and check with whoever handles the client's privacy whether the script needs to be listed in the site's policy.
With RUM you can compare the p75 before and after a deploy within one or two days, as long as the page has enough visits for the sample to make sense.
Scheduled lab tests without being fooled by variance
Running Lighthouse once a day on each site and alerting when the score drops tends to produce false alarms. The Lighthouse documentation lists the sources of variance between runs: page content that changes (A/B tests, ads), the local network, the test machine's hardware, CPU contention with other processes, the web server and the browser itself. The recommendation is to run several times and look at aggregate values, such as the median, instead of a single result. According to the same document, the median of 5 runs is twice as stable as a single run (Lighthouse, variability).
For scheduled tests across many sites, the same document recommends:
Using dedicated machines, with at least 2 cores (4 recommended) and 2 GB of memory (4 to 8 GB recommended), and avoiding shared or burstable CPU instances.
Not running several Lighthouse instances at the same time on the same machine. For a large portfolio, that means a queue, not parallel runs on the same instance.
Keeping the configuration the same across all runs: the same device profile, the same network and CPU throttling and the same test location. Simulated throttling reduces the variance caused by the network.
Isolating what you can: turning off extensions and antivirus on the test machine and, if possible, testing a version of the page without ads or A/B tests running.
The lab does not measure INP, because there is no visitor clicking. The Lighthouse stand-in is TBT (Total Blocking Time), the time the main thread was blocked during loading (web.dev). A rise in TBT is a good sign that field INP may get worse, but it is not INP.
Performance budgets per page type
A performance budget is a set of limits for metrics that affect site performance. web.dev describes three types: quantity limits (weight of images and scripts, number of fonts, third-party scripts), time limits on user-centric metrics and score limits in tools such as Lighthouse. The recommendation is to combine quantity with user metrics, set limits per page type and enforce them in the build process; when a limit is exceeded, the options are to optimize, remove or not add the new resource (web.dev, performance budgets). Lighthouse CI, an open source project from Google, runs Lighthouse on every commit and checks script and image budgets (Lighthouse CI).
The web.dev article on budgets dates from 2018 and cites metrics that predate Core Web Vitals. A current way to apply the same idea (and this is a recommendation, not a Google rule):
For time metrics, use the Core Web Vitals "good" thresholds (LCP up to 2.5 s, CLS up to 0.1) in the lab and in RUM, and TBT as the signal for INP.
For quantity, start from what each page template has today and set a ceiling slightly above it, so that a new script or image does not slip through unnoticed.
Set budgets per page template. A product page and a blog post have different weights and different LCP elements; a single budget for the whole site is either too loose or fires all the time.
Quantity budgets do not work well on sites where the client often publishes heavy content without going through the team; in that case, the limit becomes a reason to talk about the editorial process, and the field alert matters more.
Regression alerts after a deploy
A useful alert ties the change in a metric to an event: a deploy, a plugin update, a new marketing tag. One possible process with the sources above:
Log every deploy with date, time, site and version. Without this, the investigation starts with the question "what changed?".
Before shipping, run the lab test (5 runs, median) on representative URLs for each affected page template, in a staging environment if there is one.
After shipping, run it again in production, with the same configuration, and compare the medians. Alert when the median goes over budget or crosses out of the "good" band, not on every score fluctuation.
In RUM, compare the p75 for the window after the deploy with the previous window, by page template and by device, as soon as there is enough of a sample.
Follow CrUX over the next few weeks to confirm that the improvement or the regression reached the data Google uses.
The criteria in steps 3 and 4 are recommendations. Google does not define what counts as a regression; the goal is to keep normal variance between runs from turning into an alert.
Segmenting by page template and by device
Pages built on the same template share code: every product page uses the same gallery component, every post loads the same ad block. That is why a performance problem tends to repeat across the whole template. Search Console works the same way: the Core Web Vitals report groups URLs with a similar experience, gives each group a separate status for mobile and desktop and uses the worst metric as the group's status (Search Console Help).
In practice, for each site in the portfolio:
List the page templates that drive traffic or revenue (home, category, product, article, checkout) and pick one or two representative URLs from each for the lab.
In RUM, send the template name along with each metric, so you can aggregate by template instead of by URL.
Always separate mobile and desktop. Different screens show different elements, so the LCP element and the source of CLS can change from one to the other (web.dev).
Client report
One possible structure for the monthly report:
The p75 of LCP, INP and CLS on mobile and desktop, with the band (good, needs improvement, poor) and the data source.
The trend over recent weeks, which the CrUX History API and CrUX Vis provide for up to 40 weeks.
What changed in the period (deploys, new tags, fixes) and the effect seen in RUM.
What is left for the next cycle, with the affected metric and page template.
Two cautions. First, do not use the Lighthouse score as the headline number: web.dev recommends prioritizing field Core Web Vitals over Lighthouse scores (web.dev), and the score varies between runs. Second, do not promise ranking gains on Google. Google's documentation says Core Web Vitals are used by the ranking systems, but that good results do not guarantee the top spot and that Search prioritizes the most relevant content (Google Search Central).
How to do this with WebVyze
On WebVyze paid plans, each site in the portfolio gets scheduled audits and reports, and alerts by email, push, Slack, Teams, Google Chat, WhatsApp or Telegram. The real-visitor script (about 10 KB, based on the web-vitals library) records LCP, INP and CLS for each visit along with the cause. Each problem becomes an issue with evidence and a fix guide, and it is only marked as resolved after WebVyze checks again. From the Growth plan up, the client portal gives the agency's clients access to the results. For a quick check without signing up, the Core Web Vitals test shows CrUX data for up to 10 URLs, on mobile and desktop. WebVyze only reads public pages and does not change the sites.
Frequently asked questions
- Does CrUX include visits made on an iPhone?
- No. Chrome on iOS, Android apps with WebView and other Chromium-based browsers, such as Edge, do not send data to CrUX. Your own collection with the web-vitals library also measures LCP and INP in Safari and Firefox; CLS, for now, only in Chromium browsers.
- Can I monitor pages behind a login or with noindex?
- Not through CrUX: it only includes pages that are publicly discoverable, and pages with noindex or a status other than 200 are left out. A RUM script works on any page where it is installed, including logged-in areas.
- Should I use the Lighthouse score as a target in a contract?
- It is not a good idea. The score varies between runs for reasons unrelated to the site, and web.dev recommends prioritizing field Core Web Vitals over Lighthouse scores. A target based on the field p75, per device type, is more stable and closer to what the visitor experiences.
- How long does Search Console take to confirm a fix?
- When you click validate fix in the Core Web Vitals report, Search Console starts a 28-day monitoring period. If the issue does not appear on any URL in the group during that period, it is considered fixed. Validation does not force reindexing.
See what your site needs to fix.
A free check by law, with the cause and the fix guide for each problem.
Keep reading
- Technical SEO
AI crawlers in robots.txt: search, user access and training
GPTBot, ClaudeBot, OAI-SearchBot, Google-Extended: what each AI crawler does, whether it respects robots.txt, and how to block training but stay in search.
- Technical SEO
Redirects: chains, loops and how to fix them
How Google handles 301, 302, 307 and 308, what chains and loops do to crawling and speed, and how to map, fix and test your redirects.
- Technical SEO
llms.txt: what it is, what it doesn't do and how to create one
llms.txt summarizes a site for AI agents. See the format, what Google and other companies say about it, when it's worth creating and how to write a good one.