Skip to content
← ALL WRITING

2026-04-23 / 10 MIN READ

Shopify site speed and Core Web Vitals: the 48-hour fix list

The 48-hour Core Web Vitals fix list for Shopify stores: the specific actions that move LCP under 2.5s and INP under 200ms without breaking the theme.

Core Web Vitals are still a ranking signal in 2026 through Google's page experience stack. More importantly, they are a conversion signal, which most operators feel before they feel the ranking effect. A store with an LCP of 4 seconds on mid-range Android is losing conversions the merchandising team never sees directly. Paid traffic gets more expensive. Returning-visitor retention softens. Nobody connects it to LCP because nobody is looking.

The thresholds that matter: LCP under 2.5 seconds, INP under 200 milliseconds, CLS under 0.1, all measured at the 75th percentile on mobile. If your store fails any of these, this is the 48-hour fix list I run against an inherited Shopify theme before doing anything else.

This is a tutorial-walkthrough. The sequence is ordered by leverage per hour of engineering time. The first items are nearly free. The last items require more care.

// CWV METER / 75TH PCT MOBILE
LCP / THRESHOLD 2.5s4.1s · FAIL
INP / THRESHOLD 200ms340ms · FAIL
CLS / THRESHOLD 0.10.22 · FAIL
Representative before/after numbers from a typical Shopify theme pass. Middle tick marks the threshold.

Step 1: measure honestly

Do not trust Lighthouse on your laptop. Lighthouse is a useful debugging tool but the scores vary wildly based on network throttling, the machine's CPU, and browser state. The number that matters is your 75th percentile real-user LCP and INP on mobile, which you get from:

  • Chrome User Experience Report (CrUX). Real Chrome users' data, aggregated. PageSpeed Insights surfaces this for any URL. This is the number Google uses for ranking.
  • Web Vitals library in your theme. Install the web-vitals npm package (or its CDN equivalent) and fire the metrics to your analytics. This gives you per-page, per-session data instead of aggregate.

For a 48-hour pass, start with PageSpeed Insights on your top three revenue URLs (usually homepage, best-selling PDP, and top collection page). Note the current LCP, INP, CLS, and the specific element each metric is blaming.

Step 2: preload the LCP image

This is the single highest-leverage fix on most Shopify themes. The LCP element on a PDP is almost always the hero product image. The LCP element on a homepage is usually the hero banner image. On a collection, it is the first product card image.

The fix is to preload that image so the browser fetches it before it parses the CSS that would otherwise tell it about the image.

<link rel="preload" as="image"
      href="{{ product.featured_image | image_url: width: 800 }}"
      imagesrcset="..." imagesizes="..."
      fetchpriority="high">

In Shopify Liquid on a PDP template, you add this in the <head> via the theme's content_for_header or a custom snippet called in the theme's layout. fetchpriority="high" is the hint that tells the browser this image is critical.

Before: LCP on a cold load is waiting for the CSS parse and the image fetch. Usually 3-4 seconds on mobile 4G. After: LCP drops to 1.5-2.2 seconds typically, because the image is downloading in parallel with the HTML and CSS.

This one change usually moves the page from failing LCP to passing LCP. Hours to ship: one, maybe two if the theme's head structure is complicated.

Step 3: lazy load everything else

Every image that is not the LCP image should lazy load. This is the opposite bet from preload: tell the browser to wait until the image is near the viewport.

<img src="..." loading="lazy" decoding="async" width="800" height="1000">

Critical details:

  • width and height attributes are mandatory. They prevent layout shift when the image loads (CLS). Use the actual dimensions or compute them from aspect ratio.
  • loading="lazy" is a browser-native attribute, no JavaScript required.
  • decoding="async" lets the browser decode the image off the main thread, improving INP.

Most Shopify themes ship with lazy loading on, but many have bugs: hero images also get loading="lazy" (never do this, it delays LCP), or images inside sliders that autoplay get lazy loaded in a way that breaks the slider.

Audit pass: open the theme's image snippet and confirm the LCP element is loading="eager" with fetchpriority="high", and every other image is loading="lazy".

Hours to ship: one to two, depending on how many image snippets the theme has.

Step 4: defer non-critical JavaScript

Shopify stores accumulate scripts. Meta Pixel, TikTok Pixel, Klaviyo, reviews app, live chat, heatmap tool, upsell app. Each one ships a chunk of JavaScript that runs on page load, blocks rendering, and tanks INP.

The fix is layered:

  • Identify load-bearing scripts. Meta Pixel and CAPI have to fire. Most others can wait.
  • Defer non-load-bearing scripts. Add defer or async to their <script> tags. Most third-party scripts support defer cleanly.
  • Delay-load anything that can wait. Live chat, reviews, heatmap. These can load on user interaction (first scroll, first click) via a thin loader script.

For Shopify apps installed through the admin, the theme editor often adds scripts to the <head> that you cannot easily defer without breaking the app. Work around this by moving the app's script tags into your theme's liquid and adding defer manually, or by removing apps that are not pulling their weight.

Every Shopify app that adds a tracking pixel costs 40-100ms of INP. Audit them like you would audit a dependency list: does each one still earn its cost?

Hours to ship: four to eight, depending on the app stack.

Step 5: inline critical CSS, defer the rest

The default Shopify Dawn-style theme loads all its CSS in a single blocking request in the <head>. This is fine for small themes and terrible for large ones. The fix is to inline critical CSS (the styles needed for above-the-fold render) and defer the rest.

This is a bigger engineering task than the previous steps. For a 48-hour fix list, the simpler version is:

  • Remove unused CSS at the theme level (if the theme has a CSS purge step, run it)
  • Split per-template CSS if the theme supports it (Dawn does)
  • Inline the critical CSS only on the PDP and homepage templates, not everywhere

Shopify themes that ship with a build step (Dawn forks, Horizon-style themes, custom theme builds) support this out of the box. Older themes with hand-authored CSS files need more work.

Hours to ship: eight to sixteen for a theme without an existing build step.

Step 6: INP-specific fixes

INP replaced FID as the Core Web Vitals responsiveness metric in March 2024. It measures the worst input latency across a session, which is harder to hit than FID and much more sensitive to JavaScript-heavy themes.

The common INP offenders on Shopify:

  • Cart drawer open animation. If the drawer fetches cart contents synchronously before animating, INP suffers. Fix: animate first, fetch in the background.
  • Variant selector change handlers. Some themes re-render the entire product card on variant change. Fix: update only the specific DOM nodes that changed.
  • Reviews widget render. Reviews apps that render 200 reviews synchronously tank INP. Fix: paginate, virtualize, or lazy-render reviews after first interaction.
  • Third-party chat widget. Almost every one of them hurts INP. Fix: delay-load until user interaction.

INP fixes tend to be localized (a specific interaction, a specific handler) rather than global. They take time to diagnose but are often small code changes once the offender is identified.

Hours to ship: four to sixteen depending on how many interactions are broken.

Step 7: CLS-specific fixes

CLS is usually the easiest to fix once you know where it is coming from. The three common offenders on Shopify:

  • Images without width/height attributes. Already covered in Step 3.
  • Ads or embeds that load after first paint. Set explicit container dimensions so the ad renders into a pre-allocated slot.
  • Font loading. Use font-display: swap and preload the critical font files so the fallback does not visibly resize.

For most Shopify stores that fail CLS, it is one of these three and the fix is short.

Hours to ship: two to four.

Step 8: measure again, honestly

After the fixes, wait 24-48 hours for real-user data to catch up, then re-measure with PageSpeed Insights CrUX data. The lab numbers (Lighthouse) should also improve, but CrUX is the number that matters for ranking and reflects what shoppers actually experience.

Target outcomes after a 48-hour pass:

  • LCP on PDP and homepage under 2.5 seconds at 75th percentile
  • INP under 200ms on the critical interactions (cart open, variant change, search)
  • CLS under 0.1 on every above-the-fold layout

If any of these are still failing after this list, the remaining work is theme-specific and usually requires deeper intervention. That is where the UX debt paydown sprint for inherited Shopify stores becomes the right framing.

Where this fits in the hub

Site speed is the invisible conversion tax. Every other pattern in the mobile-first DTC conversion pattern library assumes the page loaded. For the theme-level patterns that interact with site speed (PDP gallery, cart drawer), see PDP patterns that actually convert on mobile in 2026 and cart drawer versus cart page.

Are Core Web Vitals still a ranking factor in 2026?

Yes, through Google's page experience signals. More importantly, they are a conversion signal. A store with an LCP of 4 seconds on mid-range Android is losing conversions the merchandising team will not see directly.

What is the single highest-leverage fix for a Shopify store's LCP?

Preload the LCP image with fetchpriority="high". The LCP element is almost always the hero product image, and preloading it usually drops LCP from 3-4 seconds to under 2 seconds on mobile 4G.

What replaced FID in Core Web Vitals?

INP (Interaction to Next Paint) replaced FID in March 2024. INP measures the worst input latency across a session, which is stricter than FID and more sensitive to JavaScript-heavy Shopify themes.

How long does a 48-hour Core Web Vitals fix actually take?

Steps 1-4 (measurement, LCP preload, lazy loading, deferring JS) fit comfortably in 48 hours for most themes. Steps 5-7 (critical CSS, INP fixes, CLS fixes) often spill into a second sprint. The 48-hour label is the first-pass high-leverage work.

Should I use Lighthouse or CrUX data to measure progress?

Both, but CrUX is the number that matters. Lighthouse is a debugging tool; CrUX is Chrome's real-user data and is what Google uses for ranking. After fixes, wait 24-48 hours and re-measure with PageSpeed Insights CrUX data.

The reference theme

The DTC Theme Starter ships with LCP targets under 2 seconds, CLS under 0.05, and INP under 150ms out of the box. The preload pattern, lazy loading, and JS deferral are already in place. It is the reference implementation for brands who want to ship a performance-tuned Shopify theme without running this 48-hour pass from scratch.

Sources and specifics

  • Core Web Vitals thresholds: LCP 2.5s / INP 200ms / CLS 0.1 at the 75th percentile on mobile, per Google's published page experience guidelines.
  • INP replaced FID as a Core Web Vital in March 2024.
  • fetchpriority="high" attribute support: stable in Chromium-based browsers since 2023, Safari since 17.2 (December 2023), widely supported by 2024-2026.
  • loading="lazy" native attribute support: stable across all major browsers since 2021.
  • Chrome User Experience Report (CrUX) data is available via PageSpeed Insights, BigQuery public dataset, and the Chrome UX Report API.
  • Real-user performance measurement: web-vitals library (Google-maintained) is the standard tool for firing CWV metrics to your analytics.

// related

Let us talk

If something in here connected, feel free to reach out. No pitch deck, no intake form. Just a direct conversation.

>Get in touch