**TL;DR.** Core Web Vitals in 2026 are LCP ≤ 2.5s, INP ≤ 200ms, CLS ≤ 0.1 at p75. On ecommerce sites, LCP is fixed via hero-image preload, INP via deferring JS and using React 18+ concurrent features, and CLS via reserving space for images and dynamic regions. Google scores at p75 over a 28-day window; fixes take weeks to reflect.

## 2026 thresholds

| Metric | Good   | Needs improvement | Poor    |
| ------ | ------ | ----------------- | ------- |
| LCP    | ≤ 2.5s | 2.5s – 4.0s       | > 4.0s  |
| INP    | ≤ 200ms| 200ms – 500ms     | > 500ms |
| CLS    | ≤ 0.1  | 0.1 – 0.25        | > 0.25  |
| TTFB   | ≤ 800ms| 800ms – 1.8s      | > 1.8s  |

Source: [web.dev/vitals](https://web.dev/articles/vitals). INP replaced FID as a Core Web Vital in March 2024 and remains the metric for 2026.

## Why CWV matters

Google uses CWV as a page-experience signal in ranking. Real-user data shows pages with all-green CWV outranking comparable pages with poor CWV in competitive niches.

Beyond rankings, CWV directly affects conversion. Studies in 2024–2025 consistently show:

- 1-second LCP improvement: 5–15% conversion lift on PDP.
- INP under 200ms: 10–20% reduction in cart abandonment.
- CLS under 0.1: noticeable UX quality perception lift.

## Measuring the right way

Two data sources matter:

1. **CrUX (Chrome User Experience Report)**: real-user data Google uses to rank you. 28-day rolling window, p75. Surfaced in PageSpeed Insights and Search Console.
2. **Your own RUM**: real-user data you collect via `web-vitals` library or your CDN. Shows fresher data, lets you slice by page type, device, country.

Synthetic tools (Lighthouse, WebPageTest) are useful for diagnosing but not for scoring.

## LCP fixes (largest contentful paint)

On ecommerce, LCP is almost always:

- The hero image on home, PLP, and PDP.
- The H1 + first paragraph on blog/article pages.

The big wins:

1. **Preload the LCP image** with `<link rel="preload" as="image" fetchpriority="high">`:

```html
<link rel="preload" as="image" href="/products/leather-bag/hero.avif" fetchpriority="high" imagesrcset="/products/leather-bag/hero-400.avif 400w, /products/leather-bag/hero-800.avif 800w" imagesizes="(max-width: 768px) 100vw, 50vw" />
```

2. **Use Next.js `<Image>` with `priority`** on the LCP image:

```tsx
<Image
  src={product.heroImage}
  width={800}
  height={800}
  priority
  fetchPriority="high"
  alt={product.altText}
/>
```

3. **Serve modern formats**. AVIF beats WebP beats JPEG. Next.js Image handles this automatically.

4. **Don't lazy-load the LCP image**. `loading="lazy"` is for below-the-fold images only.

5. **Inline critical CSS for above-the-fold styles**. Avoid blocking stylesheet loads on the critical render path.

6. **Use edge rendering**. TTFB of ≤ 100ms from edge cache buys you most of the LCP budget.

## INP fixes (interaction to next paint)

INP measures the worst case among all interactions on a page. One slow filter click can ruin your INP for a whole session.

The big wins:

1. **Reduce client-side JS**. Use React Server Components where possible. Every kilobyte of client JS hurts INP.

2. **Use `startTransition` for non-urgent state updates**:

```tsx
import { startTransition, useState } from 'react';

function FilterButton({ filter }) {
  const [isPending, startTransition] = useTransition();
  return (
    <button onClick={() => startTransition(() => applyFilter(filter))}>
      {filter.label}
    </button>
  );
}
```

3. **Use `useOptimistic` for instant feedback**:

```tsx
import { useOptimistic } from 'react';

function Cart() {
  const [cart, addOptimistic] = useOptimistic(serverCart);
  return (
    <button onClick={() => {
      addOptimistic({ ...newItem });
      addToCartServerAction(newItem);
    }}>Add to cart</button>
  );
}
```

4. **Debounce inputs**. Search autocomplete should debounce at 150–250ms with `AbortController` to cancel in-flight requests:

```tsx
useEffect(() => {
  const controller = new AbortController();
  const timeout = setTimeout(() => {
    fetch(`/api/search?q=${query}`, { signal: controller.signal });
  }, 200);
  return () => {
    clearTimeout(timeout);
    controller.abort();
  };
}, [query]);
```

5. **Hoist regex literals out of event handlers** — recreating regex in a hot path costs measurable INP.

6. **Defer non-critical third-party scripts**. Marketing pixels, chat widgets, A/B test SDKs: load them with `strategy="afterInteractive"` or `lazyOnload`.

## CLS fixes (cumulative layout shift)

The big wins:

1. **Always set width/height on images**. Browsers reserve the correct space.

```html
<img src="/hero.avif" width="800" height="800" alt="..." />
```

2. **Reserve space for embedded content**. iframes, ads, video players need explicit dimensions or aspect-ratio containers.

3. **Avoid `font-display: swap` without font-fallback CSS**. The swap reflows text. Use [size-adjust](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/size-adjust) to match metrics or accept `font-display: optional`.

4. **Don't inject content above existing content**. Banner notifications, cookie consent, sale banners — render them in a position that doesn't shift the page.

5. **Skeleton loaders should match real content dimensions**. A skeleton that's smaller than the loaded content shifts the page.

## Page-type-specific notes

**Home page**

- Hero image is LCP. Preload it.
- Carousels are CLS landmines. Use CSS-only or pre-render the first slide.

**PLP (product list / category)**

- LCP is usually the first product card image.
- INP is filter clicks and pagination. Use `startTransition` aggressively.
- CLS is product grid reflow when filters apply. Reserve grid height.

**PDP**

- LCP is the main product image.
- INP is variant swap and add-to-cart. Optimistic UI is mandatory.
- CLS is product gallery thumbnails loading after the main image.

**Cart / Checkout**

- INP is critical here. A slow "place order" button costs orders.
- CLS from loading payment iframes (Stripe Elements, etc.). Reserve space.

## Tooling

| Tool                       | What it's good for                                       |
| -------------------------- | -------------------------------------------------------- |
| PageSpeed Insights         | Single URL diagnosis with real-user (CrUX) overlay        |
| Lighthouse                 | Synthetic measurement for dev workflows                   |
| WebPageTest                | Network-throttled, multi-location measurement             |
| Search Console → CWV        | Domain-level p75 over 28 days                            |
| Your own RUM (web-vitals)  | Real-time field data sliced by page, device, country      |

## How Ordiko handles CWV by default

Ordiko's storefront stack:

- Next.js 16 + React Compiler.
- `cacheComponents: true` + `experimental.ppr: "incremental"`.
- Edge rendering of static shells (TTFB ≤ 100ms).
- LCP image preloaded by default on PDP, PLP, home.
- Suspense boundaries around dynamic islands (cart, recently-viewed, personalized hero).
- `startTransition` + `useOptimistic` on filter and variant controls.
- 200ms debounced search with `AbortController`.

Typical real-user p75 on a default Ordiko PDP: LCP 1.0–1.8s, INP 80–160ms, CLS < 0.05.

## FAQ

**Do Core Web Vitals affect rankings?**
Yes, since 2021 — but as a tiebreaker rather than a primary signal. Two pages of equal content quality will rank in CWV order. Fixing CWV on a poorly-ranked page won't suddenly make it rank if the content is weak.

**Why is INP harder to fix than LCP?**
LCP is mostly a CDN and image-optimization problem with well-understood fixes. INP is a JavaScript execution problem that requires component-by-component analysis. Each interaction event can have a different bottleneck (filter click vs. cart-add vs. variant swap).

**What's a good INP target for PDP?**
Under 200ms p75 is 'good'. Under 100ms is achievable on modern PDPs with discipline (RSC, no heavy third-party scripts, debounced inputs). Above 500ms is 'poor' and likely impacts rankings.

**How does Ordiko handle CWV by default?**
Ordiko ships Next.js 16 Cache Components + PPR, which streams a static shell with the LCP image already preloaded and Suspense boundaries for dynamic content. Default INP comes in below 200ms on typical PDPs without bespoke optimization.
