Guide · Performance

Shopify Theme Performance: Core Web Vitals in Practice

How to improve Shopify theme performance — LCP, CLS, and INP — with practical fixes that actually move the needle.

Published
14 February 2025
Reading time
10 min
Sections
4

01Where Shopify themes actually lose points

Shopify themes lose Core Web Vitals performance in predictable places: large unoptimized hero images (LCP), layout shifts from late-loading images and fonts (CLS), slow third-party scripts (INP and LCP), and excessive app scripts injecting themselves into the page.

The first step is measuring: PageSpeed Insights on real product pages and the homepage. Many Shopify stores have homepage scores that look acceptable but product pages with poor LCP because the product image isn't preloaded. Measure the pages that matter — the ones customers actually land on from ads and search.

02Fixing LCP: hero images and product images

The Largest Contentful Paint element is usually the hero image (homepage) or the main product image (product pages). For LCP images: add loading="eager" and fetchpriority="high" to the above-the-fold image, and add a in the .

Shopify's CDN serves WebP automatically when the browser supports it (use the image_url filter with format: 'webp'). Ensure your image sizes are appropriate — a hero image displayed at 800px wide shouldn't be served at 2400px wide.

For the product image carousel: only the first image needs loading="eager". All subsequent images should be loading="lazy". This single change can improve LCP by 300-500ms on product pages.

03Fixing CLS: fonts and images

Layout shift comes from two main sources in Shopify themes: images without explicit width/height attributes that cause reflow when loaded, and web fonts that cause text to reflow when they swap in.

For images: always set width and height attributes matching the aspect ratio (they don't need to be the exact pixel dimensions — the browser uses them to reserve space). In Liquid, you can calculate these from the image object.

For fonts: use font-display: optional or font-display: swap in your @font-face declarations. optional is more aggressive — if the font doesn't load before first render, the system font is used permanently. This eliminates CLS from font swap entirely, at the cost of occasionally showing the fallback font.

04Third-party scripts: the biggest culprit

Shopify app scripts are the biggest CWV killer that's hardest to fix cleanly. Each installed app can inject JavaScript into every page, and most apps load eagerly regardless of whether they're needed.

Audit installed apps: check Google Tag Manager's Coverage report (or use WebPageTest's waterfall) to see which scripts are loading and how long they take. Uninstall apps that are no longer used — many stores have 2-3 apps installed but not actively configured that are still injecting scripts.

For analytics: load Google Analytics / GA4 asynchronously. Defer non-critical scripts (chat widgets, heatmap tools) using defer or loading them after user interaction. A setTimeout` of 3-5 seconds before loading chat widgets is a practical compromise between analytics accuracy and performance.

More guides

All guides →
B2B Commerce · 14 minThe Complete Shopify B2B Setup GuideMigration · 11 minShopify Migration Checklist: WooCommerce & MagentoApps & Extensions · 9 minShopify Functions: What They Are and When to Use Them