Why Shopify Speed Problems Are Almost Always Theme and App Problems
Shopify's infrastructure is fast. Shopify's CDN (Fastly) is enterprise-grade. The bottleneck in a slow Shopify store is almost never the platform — it's the theme code and the app bloat layered on top of it.
A stock Shopify store running Dawn (Shopify's reference theme) will score 85-95 on Google PageSpeed Insights. The same store after adding 15 apps, a page builder, and a premium theme with 400KB of JavaScript will score 35-50. The degradation is predictable and preventable.
This guide covers the technical interventions that actually move the needle on Shopify performance.
Diagnosing the Problem:Where to Look First
Before touching code, measure. The three diagnostic tools:
Google PageSpeed Insights (PSI): Run your homepage, a key collection page, and a product page. PSI gives you the LCP, CLS, and INP scores that determine your Core Web Vitals status in Google Search Console.
Chrome DevTools network tab: Load a page with Network tab open. Sort by size. Identify the largest JavaScript files and the longest waterfall chains — these are your highest-impact optimization targets.
Shopify's built-in online store speed report: In your Shopify admin, navigate to Online Store → Themes → Speed. This gives you a relative speed score and identifies specific apps contributing to slow load times.
The Liquid Optimization Layer
Liquid (Shopify's templating language) performance issues are usually the result of inefficient template code, not the language itself.
Avoid N+1 query patterns in Liquid:
{% comment %} BAD: triggers a separate API call for each product {% endcomment %}
{% for product in collection.products %}
{% assign current_product = all_products[product.handle] %}
{% endfor %}
{% comment %} BETTER: use the collection object directly {% endcomment %}
{% for product in collection.products %}
{{ product.title }}
{% endfor %}
Minimize Liquid object calls in loops: Every time you access a deeply nested Liquid object in a loop, there's a processing cost. Cache complex object references before loops:
{% assign featured_image = product.featured_image %}
{% for variant in product.variants %}
{% if variant.featured_image %}
{% assign featured_image = variant.featured_image %}
{% endif %}
{% endfor %}
Lazy load non-critical sections: Shopify's section rendering API allows you to load sections asynchronously after the initial page render. Move below-the-fold sections (recently viewed, recommendations, reviews) to deferred loading.
JavaScript Optimization:The Biggest Win
JavaScript is the primary performance bottleneck on most Shopify stores. The intervention hierarchy:
1. Audit and remove unused apps: Every Shopify app injects JavaScript, CSS, and sometimes iframes into every page — even pages where the app does nothing. Audit your installed apps and remove anything you're not actively using. Each removed app is typically 50-200KB of eliminated payload.
2. Defer non-critical scripts:
For scripts that don't affect above-the-fold content, add defer or async attributes, or move them to the bottom of <body>. In Shopify themes, this means editing theme.liquid.
3. Eliminate render-blocking third-party scripts:
Chat widgets, heatmap tools, and marketing pixels are frequently render-blocking. Load them via Google Tag Manager with trigger conditions ("on page load" or "dom ready") rather than synchronously in the <head>.
4. Replace heavy apps with native Shopify features: Shopify's native functionality is increasingly comprehensive. Native metaobjects, sections, and Shopify Functions have replaced the need for many apps. Replacing an app with native functionality eliminates its JavaScript payload entirely.
Image Optimization:The Easiest Win
Shopify's CDN handles image format conversion automatically — if you use Shopify's Liquid image_url filter correctly.
{% comment %} This serves WebP automatically to supported browsers {% endcomment %}
{{ product.featured_image | image_url: width: 800 | image_tag: loading: 'lazy', width: 800, height: 600 }}
Key practices:
- Always specify
widthin theimage_urlfilter — this prevents Shopify from serving the original master image - Use
loading: 'lazy'for below-the-fold images; never for the LCP image (above-the-fold hero) - Set explicit
widthandheightattributes on all images to prevent CLS (Cumulative Layout Shift)
Core Web Vitals:Specific Fixes
LCP (Largest Contentful Paint) — target under 2.5s:
- Ensure your hero image is NOT lazy-loaded (it's the LCP element on most pages)
- Add
fetchpriority="high"to your hero image tag - Preload the hero image in
<head>:<link rel="preload" as="image" href="hero-image.webp">
CLS (Cumulative Layout Shift) — target under 0.1:
- Set explicit dimensions on all images, embeds, and ad slots
- Reserve space for dynamically injected content (app banners, notification bars)
- Avoid injecting content above existing page content after load
INP (Interaction to Next Paint) — target under 200ms:
- This is the new Core Web Vital replacing FID in 2024
- Primary causes: heavy JavaScript event listeners, long tasks on the main thread
- Profile with Chrome DevTools Performance panel; identify and optimize long tasks
At Verdant Mindset, we perform technical Shopify performance audits as part of our Shopify development services.
A sticky cart or a size chart isn't worth $10/month and an external JavaScript that wrecks your PageSpeed — you write them natively in the theme, server-side. At the interface, code is king, not the app.
Scale Your Ecosystem
30-min discovery call — no cost, no pitch. We audit your digital architecture and deliver a clear operational plan.
- 01Short message with your business context
- 02Reply within 24h with a discovery-call proposal
- 03Operational plan + scope recommendation
FAQ.PROTOCOL

