12 Premium Checks - Updated July 2026

Google Core Web Vitals and Performance Checklist

Optimize Google Core Web Vitals for loading speed, interactivity, and visual stability across all devices. INP replaced FID in March 2024 making this the most important Core Web Vitals SEO focus area. These 12 checks cover every layer from server to browser.

What Core Web Vitals Measure

Core Web Vitals are Google's three metrics that quantify the real-world user experience of a web page. They are confirmed ranking signals and directly impact user engagement, conversion rates, and bounce rates.

In 2026, CWV also affects AI search visibility. AI agents that render pages for screenshots or parse HTML expect fast, stable content. Poor CWV correlates with poor user experience across all surfaces including AI-generated answers.

Each metric measures a different aspect of the loading experience:

<2.5s LCP Target
<200ms INP Target
<0.1 CLS Target

CWV Metrics Comparison

Metric Measures Good
LCP Loading speed Under 2.5s
INP Interactivity Under 200ms
CLS Visual stability Under 0.1
TTFB Server response Under 200ms
FID (legacy) First input delay Replaced by INP

The 12 Performance Checks

Grouped by metric and ranked by impact. Fix in priority order.

# Check Metric Impact Difficulty
1 Optimize LCP element (preload, eliminate blockers) LCP Critical Medium
2 Eliminate render-blocking resources LCP Critical Medium
3 Optimize images (next-gen formats, responsive) LCP Critical Easy
4 Reduce server response time (TTFB) LCP High Hard
5 Break up long JavaScript tasks INP Critical Medium
6 Defer and audit third-party scripts INP High Medium
7 Debounce and throttle event handlers INP Medium Easy
8 Set explicit dimensions on all media CLS Critical Easy
9 Reserve space for ads and embeds CLS High Medium
10 Use font-display: swap for web fonts CLS High Easy
11 Enable CDN and caching strategy All High Medium
12 Set a performance budget and monitor CrUX All Medium Hard

INP Replaced FID: What Changed

Google replaced First Input Delay (FID) with Interaction to Next Paint (INP) in March 2024. Here is what that means for Core Web Vitals SEO.

FID measured the time from when a user first interacted with a page to when the browser could begin processing the event handler. It only captured the first interaction and was a poor proxy for overall interactivity. A page could have excellent FID but terrible responsiveness on subsequent taps or clicks.

INP measures the latency of all interactions throughout the page lifecycle and reports the worst (or near-worst) interaction. This gives a much more accurate picture of real-world responsiveness. INP is a more rigorous metric that catches issues FID missed: slow event handlers, long tasks from third-party scripts, and main thread congestion during the full user session.

Key changes for SEO:

  • INP threshold: good under 200ms, poor over 500ms (vs FID 100ms/300ms)
  • INP considers all interactions, not just the first one
  • Pages that passed FID may fail INP if they have any slow interactions
  • INP is a confirmed ranking signal in the Core Web Vitals assessment

Core web vitals news: Since the INP rollout, approximately 30-40% of sites that previously passed FID now need optimization work to pass INP. This makes INP optimization the most important CWV focus area for 2025-2026.

FID vs INP Comparison

Metric INP FID (legacy)
Good threshold ≤200ms ≤100ms
Poor threshold >500ms >300ms
What it measures All interactions First interaction only
Rolled out March 2024 Deprecated 2024
Ranking signal Yes (active) Replaced

Rendering Architecture and CWV

How your rendering strategy affects Core Web Vitals and SEO performance.

Your choice of rendering architecture directly determines your CWV baseline. Different architectures trade off initial load speed against interactivity and scalability. Understanding which one you use (and whether you should switch) is a foundational performance decision.

Architecture LCP INP CLS SEO Best For
SSR (Server-Side Rendering) Good Fair Good Excellent Content sites, SEO-critical pages
SSG (Static Site Generation) Excellent Excellent Excellent Excellent Blogs, docs, marketing pages
ISR (Incremental Static Regeneration) Excellent Good Good Excellent Large content sites with frequent updates
CSR (Client-Side Rendering) Poor Poor Fair Poor Web apps, dashboards (with SSR fallback)
DPR (Distributed Persistent Rendering) Excellent Excellent Excellent Excellent Edge-rendered dynamic content

Architecture Impact Summary

Fastest LCP SSG / ISR
Best INP SSG / Static
Lowest CLS SSG / ISR
Worst CWV CSR (no SSR fallback)
Best SEO baseline SSG / SSR

Migrating from CSR to SSR or SSG typically improves LCP by 40-60% and INP by 30-50%. If your site is CSR-only, add SSR for critical pages using frameworks like Next.js, Nuxt, or Astro.

Deep Dive: Every Check Explained

Implementation guides with code examples for all 12 checks.

1 Optimize Largest Contentful Paint (LCP)

Target: under 2.5 seconds. Identify the LCP element using Lighthouse or Chrome DevTools. It is usually a hero image, large heading, or video poster. Preload the LCP resource and eliminate any render-blocking scripts or stylesheets above the fold.

<!-- Preload the LCP image with high priority -->
<link rel="preload" as="image" href="/images/hero.webp" fetchpriority="high">

<!-- Preload critical CSS -->
<link rel="preload" as="style" href="/css/critical.css" onload="this.onload=null;this.rel='stylesheet'">

<!-- Defer non-critical JavaScript -->
<script defer src="/js/main.js"></script>

Monitor LCP in the field using the CrUX report in Google Search Console. Lab tools (Lighthouse) show potential issues; field data shows real user impact.

2 Eliminate Render-Blocking Resources

Render-blocking resources delay the browser from painting anything on screen. Inline critical CSS in the head and defer all non-critical CSS and JS. This is the single highest-impact fix for LCP on most sites.

<!-- Inline critical CSS directly in the HTML head -->
<style>
  /* Critical above-the-fold styles */
  body { font-family: sans-serif; margin: 0; }
  .hero { display: flex; ... }
</style>

<!-- Load non-critical CSS asynchronously -->
<link rel="preload" as="style" href="/css/full.css"
      onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/full.css"></noscript>

3 Optimize Images

Images account for 50-70% of page weight on most sites. Use next-gen formats (WebP, AVIF), serve responsive sizes with srcset, lazy load below-the-fold images, and compress aggressively without visible quality loss.

<picture>
  <source srcset="/image.avif" type="image/avif">
  <source srcset="/image.webp" type="image/webp">
  <img src="/image.jpg"
       srcset="/image-400.jpg 400w,
               /image-800.jpg 800w,
               /image-1200.jpg 1200w"
       sizes="(max-width: 600px) 100vw, 800px"
       width="800" height="450"
       loading="lazy"
       decoding="async"
       alt="Description">
</picture>

# Bulk convert to WebP with cwebp
for img in *.jpg; do
  cwebp -q 80 "$img" -o "${img%.jpg}.webp"
done

# Convert to AVIF with avifenc
for img in *.jpg; do
  avifenc --speed 6 --min 20 --max 40 "$img" "${img%.jpg}.avif"
done

4 Reduce Server Response Time (TTFB)

Target: under 200ms. Slow TTFB indicates server-side bottlenecks. Upgrade hosting, enable PHP OPcache, optimize database queries, implement server-side page caching, and use a reverse proxy like Nginx or Varnish.

# Test TTFB from multiple locations
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}s\n" \
  https://www.yourdomain.com

# PHP OPcache configuration
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60

# Nginx fastcgi cache
fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=mycache:10m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout updating;

5 Break Up Long JavaScript Tasks

Target INP: under 200ms. Long tasks (over 50ms) block the main thread and make the page feel unresponsive. Break them up by yielding to the main thread, using async/await, and splitting work into smaller chunks.

New in 2025-2026: The scheduler.yield() API provides a dedicated mechanism for yielding control back to the browser without the overhead of setTimeout(0). Unlike setTimeout, scheduler.yield() integrates with the browser's task prioritization system and does not require a minimum delay. It is supported in Chrome 115+ and is the preferred way to break up long tasks.

// Modern approach: scheduler.yield() (Chrome 115+)
async function processItems(items) {
  for (const item of items) {
    heavyProcess(item);
    await scheduler.yield();  // yield without timeout overhead
  }
}

// Fallback: yield via setTimeout
async function processItemsWithFallback(items) {
  for (const item of items) {
    heavyProcess(item);
    if ('scheduler' in window && 'yield' in scheduler) {
      await scheduler.yield();
    } else {
      await new Promise(r => setTimeout(r, 0));
    }
  }
}

// Use requestIdleCallback for non-critical work
function scheduleWork(task) {
  if ('requestIdleCallback' in window) {
    requestIdleCallback(task, { timeout: 2000 });
  } else {
    setTimeout(task, 1);
  }
}

// Avoid forced reflows
// Bad: Reading layout after writing
element.style.width = '100px';
const width = element.offsetWidth;  // triggers forced reflow

// Good: Batch reads separately from writes
const reads = [];
// ... all writes first, then reads

6 Defer and Audit Third-Party Scripts

Third-party scripts (analytics, ads, social widgets, chatbots) are the #1 cause of poor INP. Each script competes for the main thread. Audit every third-party script, load them async, and remove any that are not essential.

<!-- Load third-party scripts with async or defer -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXX"></script>

<!-- Use IntersectionObserver to lazy load non-critical widgets -->
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const script = document.createElement('script');
      script.src = entry.target.dataset.src;
      document.body.appendChild(script);
      observer.unobserve(entry.target);
    }
  });
});
document.querySelectorAll('[data-lazy-script]').forEach(el => observer.observe(el));

Use Chrome DevTools Performance tab to record page load and identify which scripts take the most main thread time. Remove any tag that does not provide clear business value.

7 Debounce and Throttle Event Handlers

Event handlers attached to scroll, resize, mousemove, or keydown fire hundreds of times per second. Without debouncing, each invocation runs on the main thread and degrades INP. Debounce delays execution until after a pause; throttle limits execution to once per interval.

// Debounce: waits for a pause before executing
function debounce(fn, delay = 150) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

window.addEventListener('resize', debounce(() => {
  // handle resize
}, 150));

// Throttle: limits execution rate
function throttle(fn, limit = 100) {
  let inThrottle;
  return function(...args) {
    if (!inThrottle) {
      fn.apply(this, args);
      inThrottle = true;
      setTimeout(() => { inThrottle = false; }, limit);
    }
  };
}

window.addEventListener('scroll', throttle(() => {
  // handle scroll
}, 100));

8 Set Explicit Dimensions on All Media

CLS is caused primarily by images, videos, iframes, and ads that load without reserved space. Always set explicit width and height attributes on all media elements. This allows the browser to reserve the correct space before the resource loads.

<!-- Always set explicit width and height -->
<img src="/image.webp" width="800" height="450" alt="" loading="lazy">

<!-- For responsive images with unknown aspect ratios, use aspect-ratio CSS -->
img, video, iframe {
  max-width: 100%;
  height: auto;
  aspect-ratio: attr(width) / attr(height);
}

<!-- Reserve space for embeds with a wrapper -->
<div style="position: relative; padding-bottom: 56.25%; height: 0;">
  <iframe src="https://www.youtube.com/embed/..."
          style="position: absolute; top: 0; left: 0;
                 width: 100%; height: 100%;"></iframe>
</div>

9 Reserve Space for Ads and Embeds

Dynamic content like ads and embeds cause the most disruptive layout shifts because they load after the initial paint. Reserve the exact space they will occupy using min-height placeholders.

<!-- Reserve ad space with a placeholder -->
<div style="min-height: 250px; width: 100%; background: #f0f0f0;"
     id="ad-slot-desktop">
  <!-- Ad loads here -->
</div>

<!-- For multi-size ads, reserve the maximum possible space -->
<div class="ad-container" style="min-height: 90px;">
  <div id="ad-slot-responsive"></div>
</div>

10 Use font-display: swap for Web Fonts

Custom web fonts cause CLS in two ways: FOIT (Flash of Invisible Text) where text is hidden until the font loads, and FOUT (Flash of Unstyled Text) where text swaps from fallback to custom font. Use font-display: swap to show text immediately with a fallback font.

@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom-font.woff2') format('woff2');
  font-display: swap;
  font-weight: 400;
}

/* Preload the font for earlier discovery */
<link rel="preload" as="font" href="/fonts/custom-font.woff2"
      type="font/woff2" crossorigin>

/* Use font-size-adjust to minimize layout shift during swap */
body {
  font-family: 'CustomFont', Arial, sans-serif;
  font-size-adjust: 0.5;
}

11 Enable CDN and Caching Strategy

A CDN serves content from servers closest to the user, reducing latency by 30-60%. Cloudflare, BunnyCDN, and AWS CloudFront offer generous free or low-cost tiers. Combine with proper Cache-Control headers and Brotli compression.

# Cache-Control headers for different asset types
# Images and fonts: cache for 1 year
location ~* \.(webp|avif|jpg|png|woff2)$ {
  expires 1y;
  add_header Cache-Control "public, immutable";
}

# CSS and JS: cache for 1 month
location ~* \.(css|js)$ {
  expires 1M;
  add_header Cache-Control "public";
}

# HTML: short cache or no cache
location ~* \.html$ {
  expires 0;
  add_header Cache-Control "no-cache";
}

# Enable Brotli compression on CDN
brotli on;
brotli_comp_level 6;
brotli_types text/html text/css application/javascript
             image/svg+xml application/json;

12 Set a Performance Budget and Monitor CrUX

A performance budget defines the maximum allowed size or time for each page. Track it in CI/CD to prevent regressions. Monitor Chrome User Experience Report (CrUX) data for real-user performance trends.

Understanding CrUX: The 75th Percentile

Google uses the 75th percentile of real-user measurements to determine whether a page passes Core Web Vitals. This means at least 75% of visits must meet the good threshold. If your LCP is 2.0s median but 30% of users experience 4.0s, you fail the LCP assessment. This is why lab tools (Lighthouse) alone are insufficient. Always validate against CrUX field data because real-user conditions vary widely by device, network, and geography.

Monitor CrUX in Google Search Console under the Core Web Vitals report. It shows the percentage of URLs rated Good, Need Improvement, and Poor for each metric. A sudden shift from Good to Poor often correlates with a recent deployment.

// Performance budget example (budget.json)
{
  "resources": {
    "total": { "maxSize": "500kB" },
    "javascript": { "maxSize": "200kB" },
    "css": { "maxSize": "50kB" },
    "images": { "maxSize": "300kB" },
    "fonts": { "maxSize": "50kB" }
  },
  "timings": {
    "lcp": { "maxTime": 2500 },
    "inp": { "maxTime": 200 },
    "cls": { "maxScore": 0.1 },
    "ttfb": { "maxTime": 200 }
  }
}

# Use Lighthouse CI to enforce budgets
# npx lhci collect --no-lr
# npx lhci assert --budget-file budget.json
# npx lhci upload

Lab vs Field Data: Lighthouse runs on a simulated device with a throttled connection. It catches obvious issues but cannot represent real-user conditions. CrUX aggregates data from millions of real Chrome users. Always prioritize field data for ranking decisions because Google uses field data (CrUX) for the CWV ranking signal. Use lab data for debugging specific issues, and field data for understanding real-world impact.

Common Performance Mistakes

Bad practices that wreck Core Web Vitals.

Bad Practice vs Best Practice

JPEG/PNG only, no compression WebP/AVIF with 80% quality compression
All JavaScript loaded synchronously Critical JS inlined, rest deferred with async/defer
No image dimensions set Explicit width/height on all images and videos
Third-party scripts loading on every page Conditional loading per page type
No Cache-Control headers Aggressive caching with immutable flag for assets
Single large CSS file Critical CSS inlined, rest loaded async
No CDN Cloudflare free tier or equivalent CDN

Performance Tools

Tools for measuring, monitoring, and debugging Core Web Vitals.

Google PageSpeed Insights

Lab and field data for any URL. Shows LCP, INP, CLS with improvement suggestions.

Free

CrUX Dashboard

Real-user performance data from Chrome users. Track CWV trends over time for your entire site.

Free

Lighthouse CI

Automated performance testing in CI/CD pipelines. Enforce performance budgets on every deployment.

Free

WebPageTest

Detailed waterfall charts, filmstrip view, and multi-location testing for advanced debugging.

Free

Chrome DevTools

Performance tab, Network tab, Coverage tab, and Lighthouse panel for in-browser debugging.

Free

Request Metrics

Real user monitoring (RUM) with weekly reports and alerting for CWV regressions.

Paid (free tier)

Related Checklists

Keep exploring the technical SEO series. Every checklist follows the same structure.

CDN, Caching, and Hosting

TTFB and cache hit rates set the floor for every performance metric.

Image SEO

The fastest and most common way to cut LCP and page weight.

JavaScript SEO and Rendering

How rendering pipelines delay LCP and INP.

Website Accessibility

Semantic HTML and keyboard support overlap with performance.

Technical On-Page SEO

Titles and metas are part of the same performance pass.

Crawl Budget and Log Analysis

How slow responses throttle crawl rate in your logs.

Need Technical SEO Help?

Get professional SEO audit services and technical SEO solutions from Clienvora. Our expert team delivers measurable results for businesses of all sizes.

Free consultation. Get a personalized technical SEO audit for your website today. Or download the full checklist PDF.

Frequently Asked Questions

Common questions about Core Web Vitals and site performance.

What are Core Web Vitals?

Core Web Vitals are Google's three metrics for measuring real-world user experience: Largest Contentful Paint (LCP for loading speed), Interaction to Next Paint (INP for interactivity), and Cumulative Layout Shift (CLS for visual stability). They are confirmed ranking signals.

How do I fix poor LCP?

Identify the LCP element using Lighthouse, preload it with fetchpriority=high, eliminate render-blocking resources, optimize images to WebP/AVIF, reduce TTFB under 200ms, and remove unnecessary third-party scripts.

What causes high CLS?

Images and videos without explicit dimensions, dynamically injected content without reserved space, web fonts with FOIT, ads and embeds that resize after loading, and custom fonts that cause FOUT without proper font-display settings.

How do I improve INP?

Break up long JavaScript tasks by yielding to the main thread, defer third-party scripts, debounce event handlers, avoid forced reflows, minimize DOM size, and use web workers for heavy computation.

What is a good TTFB?

Under 200ms. TTFB (Time to First Byte) measures how long the server takes to start responding. Poor TTFB is usually caused by slow hosting, unoptimized databases, missing cache layers, or slow application code.

Did INP replace FID? What changed in Core Web Vitals?

Yes, INP (Interaction to Next Paint) replaced FID (First Input Delay) as a Core Web Vital in March 2024. INP measures all interactions throughout the page lifecycle, not just the first one. The good threshold is under 200ms (vs 100ms for FID). This was one of the biggest core web vitals news updates in recent years, affecting 30-40% of sites that previously passed FID.

Should I use lab data or field data?

Both. Lab data (Lighthouse) helps you debug specific issues. Field data (CrUX, RUM) shows real user experience. Always prioritize field data for ranking decisions because Google uses field data for the CWV ranking signal.

How often should I check Core Web Vitals?

Check the CrUX report in Google Search Console weekly. Set up alerts for CWV regressions using tools like Request Metrics or DebugBear. Run Lighthouse after every significant deployment to catch regressions early.

AA

Amir Ali

Founder of Clienvora, a content marketing agency that combines SEO and copywriting to drive rankings, traffic, and revenue. This checklist is maintained and updated regularly.