Guide · Shopify

Shopify theme speed
optimization

Shopify's CDN is fast. Most Shopify themes aren't. The platform handles the infrastructure — but the theme decides how much JavaScript loads, how images are served, and whether the browser has to wait for a third-party script before painting anything useful.

Where the milliseconds go

Render-blocking scripts

Scripts loaded in <head> without defer or async block the browser from rendering anything until they've downloaded and executed. Theme JavaScript, analytics tags, and chat widgets are common offenders. Every synchronous script in <head> adds directly to Time to First Byte of content.

Third-party app scripts

Every Shopify app that injects a script tag adds weight. Review apps, loyalty apps, size guide apps, chat widgets — each one brings its own JavaScript bundle, its own CSS, sometimes its own font. A store with 8 apps installed can easily add 500KB of script weight before the theme's own code runs.

Unoptimized LCP images

Largest Contentful Paint is usually the hero image or the first product image. If it's served at full resolution with no width hint, the browser downloads 3000px of image for a 600px slot. Shopify's image CDN resizes on-the-fly — but only if the theme requests the right size.

Unused theme JavaScript

Dawn ships a full Web Component system. Impulse, Prestige, and other popular themes ship even more. If the store doesn't use a video hero, quick-add modals, or predictive search — that JavaScript still loads. Tree-shaking isn't something Shopify themes do; you remove features explicitly or live with the weight.

What to fix first

01

Audit third-party scripts

Run the store through WebPageTest or Chrome DevTools Network tab. Sort by initiator and size. Third-party domains you don't recognize are app scripts. For each one, decide if the app's value justifies the weight — most stores have 2–3 apps they installed and forgot. Remove them from Shopify admin, not just from the theme.

02

Fix the LCP image

The hero image needs loading="eager" (not lazy), a fetchpriority="high" attribute, and a sizes attribute that matches the actual rendered width. Use Shopify's | image_url: width: 1200 filter to request an appropriately sized version. Add a <link rel="preload"> in <head> for the critical image.

03

Defer non-critical scripts

Analytics, chat widgets, and review widgets should load after the page is interactive. Add defer or load them on DOMContentLoaded or on user interaction. A live chat widget that fires on idle instead of on page load doesn't affect LCP or TBT — and users who need it will still get it.

04

Lazy-load below-the-fold images

Every image below the hero should have loading="lazy". Shopify's | image_tag filter doesn't add it by default — pass loading: 'lazy' as an option or add the attribute manually. A collection page with 24 products loading 24 images eagerly burns bandwidth on images the user may never scroll to.

05

Remove unused theme sections and features

If the theme ships with a video background hero and you're using a static image hero, the video player JavaScript still loads. Comment out or remove the feature's script block. On a custom or heavily modified theme this is straightforward; on a marketplace theme, note what you've changed so updates don't reintroduce it.

Related