Module 2.7 — Measurement Workflow
Phase: Phase 2 — Performance Engineering (Core Web Vitals)
Fixing Core Web Vitals without a disciplined measurement workflow is like adjusting a car engine with the hood closed.
You need to know exactly what you're measuring, why lab numbers and field numbers disagree, and
which tool to use at each stage of diagnosis, implementation, and verification. This module builds that
end-to-end workflow from first measurement through confirmed improvement.
1. The Two Realities: Lab Data vs Field Data
Before touching any tool, you must internalize this distinction — it governs every decision in performance work.
1.1 Field Data (Real-User Monitoring / RUM)
Field data is collected from real users on real devices, real networks, in real conditions.
It reflects what people actually experience. The canonical public source is the
Chrome User Experience Report (CrUX), a dataset Google builds from
opted-in Chrome browser telemetry.
- PageSpeed Insights — shows CrUX field data at the URL level and the origin level (28-day rolling window)
- Google Search Console → Core Web Vitals report — groups URLs by "Good / Needs Improvement / Poor" based on CrUX field data
- The
web-vitals JavaScript library — lets you collect your own RUM data and send it to any analytics backend
- CrUX BigQuery / CrUX API — programmatic access for large-scale analysis
Field data is the ground truth for Google's ranking signal.
If PageSpeed Insights shows a green Lighthouse score in the lab but your CrUX field data is red, your
users are experiencing a poor page — and Google knows it. Fix field data, not lab scores.
1.2 Lab Data (Synthetic Testing)
Lab data is collected in a controlled, simulated environment — fixed device, fixed network,
no other browser tabs, no real user variability. The primary lab tool is Lighthouse,
which runs inside Chrome DevTools, as a CLI, or via PageSpeed Insights.
- Reproduces a specific scenario consistently — great for spotting regressions
- Gives you a waterfall, filmstrip, and trace so you can find the exact cause of a problem
- Uses throttled CPU and network presets (e.g., Moto G Power, 4G) — results vary from real devices
- Does not capture INP (INP requires real user interaction; Lighthouse only measures TBT, which correlates with INP)
1.3 Why They Disagree — and Which to Trust
- Your real users may be on high-end MacBooks or on $80 Android phones in rural areas — CrUX captures both
- Lighthouse uses a fixed network profile; your CDN, edge caching, and server location all affect real TTFB differently per user geography
- Third-party scripts (chat widgets, analytics, A/B testing tools) often load differently in lab vs real sessions
- CrUX only reports on URLs with enough visits — new pages or low-traffic pages may have no field data
Decision rule: Use field data to understand the problem and measure success. Use lab data to
diagnose the root cause and iterate quickly without waiting days for CrUX to update.
2. The Measurement Toolkit
2.1 Chrome DevTools — Performance Panel
The Performance panel is your surgical instrument. It records a full trace of everything that happens in the
browser during page load or interaction.
How to use it effectively:
- Open DevTools (
F12 / Cmd+Option+I) → Performance tab
- Click the gear icon to set CPU throttling (4× or 6× slowdown) and network throttling (Slow 4G)
- Hit the record + reload button (circular arrow) to capture a full page load trace
- For INP diagnosis, hit record, perform the interaction (click a button, open a dropdown), then stop recording
What to look for in the trace:
- LCP: Find the "LCP" marker in the Timings row. Click it to see which element was the LCP candidate and when it painted
- CLS: Look for "Layout Shift" events in the Experience row — click them to see which DOM nodes shifted and by how much
- Long Tasks: Any task in the Main thread longer than 50ms appears with a red corner — these block the main thread and cause poor INP/TBT
- Network waterfall: Identify render-blocking resources, late-discovered images (LCP candidate loaded too late), and third-party script load order
2.2 Lighthouse
Lighthouse gives you a structured report with scored audits, not just a raw trace. It is best used for:
- Getting an overview of all performance opportunities on a page
- Running in CI/CD to catch regressions before deploy (Lighthouse CI)
- Understanding which resources contribute most to LCP delay (the LCP phase breakdown audit)
Key Lighthouse audits for CWV work:
- Largest Contentful Paint — breakdown into sub-phases: TTFB, resource load delay, resource load duration, element render delay
- Total Blocking Time (TBT) — proxy for INP; sum of blocking time beyond 50ms for all long tasks during page load
- Cumulative Layout Shift — lists contributing elements
- Render-blocking resources — lists specific stylesheets or scripts delaying first paint
- Properly sized images, next-gen formats, efficient cache policy
Run Lighthouse in an incognito window to avoid extension interference. Run it
three times and average the scores — single runs have natural variance.
2.3 WebPageTest
WebPageTest (webpagetest.org) is the most powerful free synthetic testing tool available. Unlike Lighthouse
(which runs on your local machine), WebPageTest runs from real infrastructure in real global locations
against a real server — so TTFB, CDN behavior, and geographic differences are all real.
Key capabilities:
- Test from multiple global locations (e.g., Frankfurt, Mumbai, São Paulo) to understand geographic TTFB variance
- Test on real device profiles or emulated devices with specific network throttling
- Filmstrip view — frame-by-frame screenshots showing exactly when content appears; use this to find the LCP moment visually
- Waterfall chart — full resource waterfall with request timing, priority, and blocking relationships
- Opportunities & Experiments — run what-if scenarios (e.g., "what if this resource was preloaded?") without changing code
- Core Web Vitals timeline — LCP, CLS, TBT all annotated on the waterfall
- Repeat view — first load vs cached load, revealing whether your caching strategy is effective
WebPageTest is the gold standard for diagnosing LCP root causes because it shows you
exactly when the LCP resource was discovered, when it started downloading, and when it finished rendering.
2.4 The web-vitals JavaScript Library
This is Google's official library for measuring Core Web Vitals in real users' browsers. It is the
foundation of any production RUM setup.
// Install
npm install web-vitals
// Measure all Core Web Vitals and send to your analytics endpoint
import { onLCP, onINP, onCLS } from 'web-vitals';
function sendToAnalytics(metric) {
const body = JSON.stringify({
name: metric.name, // 'LCP', 'INP', 'CLS'
value: metric.value, // the metric value
rating: metric.rating, // 'good', 'needs-improvement', 'poor'
id: metric.id, // unique ID for deduplication
navigationType: metric.navigationType,
});
// Use navigator.sendBeacon for reliability (fires even if tab closes)
navigator.sendBeacon('/analytics', body);
}
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
Send this data to Google Analytics 4, BigQuery, or any custom backend. This gives you field data
segmented by your traffic — by device type, geography, page template, user cohort — unlike CrUX
which is an aggregate. This is critical for finding that, say, your LCP is good for desktop users but
catastrophic for mobile users in Southeast Asia.
Important notes on web-vitals metric delivery:
- CLS is reported when the page lifecycle ends (tab close, navigation away) — use
sendBeacon, not fetch
- INP is reported as the worst interaction during the session — it reflects the 75th percentile of all interactions that session
- Always report the 75th percentile of your collected data, not the average — this is how Google defines "good" for a URL group
3. The End-to-End Measurement Workflow
This is the repeatable process you follow every time you work on a CWV problem. Each stage has a specific
purpose — do not skip stages.
Stage 1: Identify the Problem in Field Data
- Open Google Search Console → Core Web Vitals. Note which URL groups are "Poor" or "Needs Improvement" and which metric is failing.
- Open PageSpeed Insights for a representative URL from the failing group. Look at the field data section (CrUX). Confirm which metric(s) are failing and at what values.
- Check whether the problem is at the URL level (one specific page) or the origin level (a systemic pattern across your whole site).
- Prioritize by traffic and business value — fix the highest-traffic, highest-revenue URL groups first.
Stage 2: Reproduce and Diagnose in the Lab
- Load the failing URL in Chrome in an incognito window.
- Run Lighthouse from DevTools (throttled: Slow 4G, 4× CPU). Read the LCP phase breakdown, TBT value, and CLS contributors in the audit list.
- Run the DevTools Performance panel with throttling. Find the LCP candidate, the CLS-causing layout shifts, and any long tasks blocking interaction.
- Run WebPageTest from a location matching your primary user geography. Study the waterfall for late-discovered LCP resources, render-blocking scripts, and third-party load order.
- Note the exact root cause for each failing metric. Write it down explicitly:
- Example LCP: "Hero image is discovered late because it has
loading='lazy' and is not in the initial HTML — fetching doesn't start until the browser renders the page."
- Example CLS: "Ad slot at the top of the article has no reserved height — when the ad loads at 3s it shifts all content down by 210px."
- Example INP: "Clicking 'Add to Cart' triggers a 650ms long task: a third-party analytics event fires synchronously in the click handler."
Stage 3: Implement the Fix
- Implement only one fix at a time where possible, so you can isolate which change moved which metric.
- Document what you changed: the file, the specific code modification, the expected impact on which metric.
- If you cannot deploy to production immediately, use a staging environment or WebPageTest's "Experiments" feature to simulate the fix.
Stage 4: Verify the Fix in the Lab
- Re-run Lighthouse on the same throttling settings. Compare numbers directly with your Stage 2 baseline.
- Re-run WebPageTest. Compare the waterfall — does the LCP resource now start earlier? Do layout shifts disappear from the filmstrip?
- Re-run the DevTools Performance panel. Are the long tasks shorter? Is the LCP timing improved?
- Produce a before/after comparison table. You need specific numbers, not vague impressions:
Metric Before Fix After Fix Target
LCP 4.2s 2.1s < 2.5s
TBT 680ms 120ms < 200ms
CLS 0.24 0.04 < 0.1
Stage 5: Confirm Improvement in Field Data
- Deploy to production.
- Wait 28 days for a full CrUX collection cycle. (CrUX is a 28-day rolling window; you'll start seeing change after ~7 days but the full picture takes 28 days.)
- Re-check PageSpeed Insights field data for the URL. Compare the field LCP, INP, and CLS values before and after.
- Re-check Google Search Console Core Web Vitals to confirm the URL group has moved status.
- Check your RUM data (if you have
web-vitals implemented) segmented by device and geography — confirm the improvement is real for your actual users, not just the CrUX aggregate.
4. Building a Before/After Evidence Package
A documented before/after comparison is your proof of work. It protects you when stakeholders ask
"did this actually help?", and it is the standard of advanced technical SEO — not anecdote, but measurement.
Your evidence package should contain:
- Field data screenshots — PageSpeed Insights field section, before and after, for the same URL
- GSC Core Web Vitals report — before and after, showing the URL group status
- Lab data comparison — Lighthouse and WebPageTest results side by side
- Filmstrip comparison — WebPageTest filmstrips showing visual progression before vs after; LCP marked on both
- Root cause documentation — a clear statement of what was wrong, what was changed, and why that change addresses the root cause
- RUM data (if available) — 75th percentile field values from your analytics, segmented by device type
5. Continuous Monitoring — Don't Measure Once
Performance degrades silently. A new marketing script, a CMS update, a new image uploaded without compression,
a third-party A/B testing tool — any of these can undo months of CWV work overnight.
Set up monitoring so you find out immediately, not weeks later from a GSC warning.
5.1 Lighthouse CI in Your Deploy Pipeline
Lighthouse CI runs Lighthouse automatically on every pull request or deploy and fails the build if
performance budgets are exceeded.
# .lighthouserc.js (minimal example)
module.exports = {
ci: {
collect: {
url: ['https://staging.example.com/', 'https://staging.example.com/products/'],
numberOfRuns: 3,
},
assert: {
assertions: {
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'total-blocking-time': ['error', { maxNumericValue: 200 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
},
},
upload: {
target: 'temporary-public-storage', // or your LHCI server
},
},
};
This ensures regressions are caught before they reach production and real users.
5.2 Scheduled Synthetic Monitoring
- PageSpeed Insights API — schedule a daily script that fetches field and lab data for your key URLs and logs the values to a spreadsheet or monitoring dashboard
- WebPageTest API — schedule weekly runs from multiple locations; alert if LCP exceeds a threshold
- CrUX API — pull field data programmatically for your priority URL groups
5.3 Always-On RUM with web-vitals
With the web-vitals library deployed, you have a continuous stream of real-user metric data.
Set up alerts in your analytics platform to notify you when the 75th percentile of LCP, INP, or CLS
crosses the "Good" threshold for any meaningful traffic segment.
6. Common Measurement Mistakes to Avoid
-
Celebrating a Lighthouse score instead of field data improvement.
A green Lighthouse score with red CrUX field data means your real users are still suffering.
The ranking signal comes from CrUX, not Lighthouse.
-
Testing without throttling.
Running Lighthouse on a fast developer machine without CPU/network throttling gives unrealistically
good scores. Always throttle to emulate the median real-world device.
-
Single-run results.
Lighthouse has natural variance. Always average at least three runs. WebPageTest recommends a median
of five runs for LCP-sensitive testing.
-
Reporting averages from RUM instead of the 75th percentile.
Google defines a URL's CWV status at the 75th percentile of all field sessions. Reporting your mean LCP
of 1.8s means nothing if your 75th percentile is 4.2s — Google sees 4.2s.
-
Not waiting for field data to update.
Immediately after a fix, CrUX data won't change. Impatient stakeholders will claim the fix "didn't work."
Explain the 28-day rolling window and show lab data improvement as early evidence while field data catches up.
-
Measuring the desktop version of a mobile problem.
CrUX is primarily mobile-dominant for most sites. Always check the Mobile tab in PageSpeed Insights.
A passing desktop score with a failing mobile score is a failing site — Google uses mobile-first indexing.
Summary: The Measurement Workflow at a Glance
- Field data (CrUX / PageSpeed Insights / GSC) — defines the problem and confirms the solution
- Lab data (Lighthouse / DevTools / WebPageTest) — diagnoses root causes and validates fixes quickly
- RUM (
web-vitals library) — gives you segmented, real user data that CrUX can't
- CI monitoring (Lighthouse CI) — prevents regressions before they hit production
- Before/after documentation — proves that your work moved real metrics
Milestone Task
Select a live URL that has field data in PageSpeed Insights (use your own site, a client site, or a
publicly accessible site with enough traffic for CrUX data).
- Record the field data baseline: LCP, INP (or FID if INP is not yet available), and CLS values at the 75th percentile for mobile.
- Run Lighthouse (throttled), a DevTools Performance trace, and a WebPageTest run. Write down the precise root cause of whichever metric is weakest.
- Implement or mock a fix. Re-run all three lab tools and produce a before/after table with specific numbers.
- Write a one-page diagnosis document: what was failing, the root cause, what you changed, the lab evidence of improvement, and the plan to confirm in field data after 28 days.
You have completed this module when you can walk through all five stages of the measurement workflow — from
identifying a field data problem to producing a documented, quantified, before/after evidence package — without
referring to these notes.