Dev.to WebDev 🛠 Dev 👁 0 📖 4 min read

How I Optimized a Shopify Store to Score 95+ on Mobile PageSpeed (Real Case Study)

Most Shopify stores struggle with poor mobile performance. Out of the box, even modern Shopify 2.0 themes can score under 40 on Google PageSpeed Insights (Mobile) once apps, tracking scripts, and oversized product media

Most Shopify stores struggle with poor mobile performance. Out of the box, even modern Shopify 2.0 themes can score under 40 on Google PageSpeed Insights (Mobile) once apps, tracking scripts, and oversized product media get added.

As a full-stack Shopify developer who has delivered 350+ commercial projects, slow load times are the #1 complaint I hear from e-commerce store owners. Every 1-second delay in page load can drop conversion rates by up to 7%.

In this article, I’ll break down the exact technical blueprint I used to take a client's production Shopify store from a 34 Mobile Performance Score to a 96+, without removing essential features or tracking apps.

1. The Starting Benchmark: Why Most Shopify Stores Fail

Before making changes, we ran an in-depth audit using Google PageSpeed Insights and WebPageTest:

  • Mobile Score: 34 / 100
  • First Contentful Paint (FCP): 2.9s
  • Largest Contentful Paint (LCP): 5.8s (Failing Core Web Vitals)
  • Total Blocking Time (TBT): 940ms
  • Cumulative Layout Shift (CLS): 0.32

The culprits were classic e-commerce bottlenecks:

  1. Render-blocking third-party scripts loaded in theme.liquid.
  2. Hero banner images lacking responsive srcset and fetchpriority="high".
  3. Multiple unoptimized CSS files and unused legacy plugins.
  4. Zombie app snippets left behind after apps were uninstalled.

2. Step 1: Purging "Zombie" Liquid Snippets & App Bloat

When merchants uninstall apps from the Shopify App Store, apps frequently leave behind orphaned Liquid includes, tracking pixels, and CSS files in the theme codebase.

In layout/theme.liquid, we audited all {% render %} and {% include %} tags:

{%- comment -%} 
BEFORE: Unused legacy apps executing on every page 
{% render 'old-review-widget-header' %}
{% render 'uninstalled-upsell-tracker' %}
{%- endcomment -%}

Removing dead snippets alone eliminated 18 external HTTP network requests and shaved 380 KB of uncompressed JavaScript from the initial document head.

3. Step 2: Optimizing LCP (Largest Contentful Paint)

The hero banner on the homepage was the primary LCP element. It was being lazy-loaded by default, delaying its render until long after JavaScript finished parsing!

The Rule for E-Commerce Images:

  • Above-the-fold (Hero/Main Banner): Eager load, high fetch priority, no lazy loading.
  • Below-the-fold (Product Grids, Reviews, Footer): Lazy load with native loading="lazy".

Here is the optimized Liquid pattern used for the hero image:

{%- if section.index == 1 -%}
  {{ section.settings.image | image_url: width: 1500 | image_tag:
    widths: '375, 550, 750, 1100, 1500',
    sizes: '100vw',
    loading: 'eager',
    fetchpriority: 'high',
    decoding: 'async',
    class: 'hero-banner__image',
    alt: section.settings.image.alt | escape
  }}
{%- else -%}
  {{ section.settings.image | image_url: width: 1200 | image_tag:
    widths: '375, 550, 750, 1100',
    sizes: '(min-width: 768px) 50vw, 100vw',
    loading: 'lazy',
    decoding: 'async',
    class: 'content-image'
  }}
{%- endif -%}

Result: LCP dropped from 5.8s down to 1.8s immediately.

4. Step 3: Eliminating Cumulative Layout Shift (CLS)

CLS kills user experience when elements jump around while assets download.

We fixed layout shifts with two key changes:

  1. Explicit Aspect Ratios on Image Containers: Always declare explicit width and height attributes or use CSS aspect-ratio:
   .product-card__media {
     aspect-ratio: 1 / 1;
     overflow: hidden;
     background: #f4f4f4; /* placeholder color prevents visual jumping */
   }
  1. Announcement Bar Height Reservation: Dynamic announcement bars or countdown timers often push the entire navbar down when they mount. Reserving a min-height via CSS prevents the layout from reflowing.

Result: CLS plummeted from 0.32 down to 0.01 (well within Google's "Good" green threshold).

5. Step 4: Deferring Third-Party Scripts with requestIdleCallback

Analytics tags, chat widgets (Gorgias, Zendesk), and review stars (Klaviyo, Yotpo) don't need to load during the critical 1.5-second rendering window.

Instead of inserting them as synchronous scripts in <head>, we delayed non-critical scripts until the browser's main thread becomes idle:

function loadNonCriticalScripts() {
  const scripts = [
    'https://static.klaviyo.com/onsite/js/klaviyo.js?company_id=YOUR_ID',
    // other third-party services
  ];

  scripts.forEach((src) => {
    const script = document.createElement('script');
    script.src = src;
    script.async = true;
    document.body.appendChild(script);
  });
}

// Execute when browser is idle or after first interaction
if ('requestIdleCallback' in window) {
  window.requestIdleCallback(loadNonCriticalScripts, { timeout: 3000 });
} else {
  window.addEventListener('load', () => setTimeout(loadNonCriticalScripts, 2000));
}

This reduced Total Blocking Time (TBT) from 940ms down to 85ms, liberating the main thread for smooth scrolling and instant touch responsiveness.

6. The Final Results

After testing the optimizations on production:

Metric Before Optimization After Optimization Status
Mobile Performance 34 / 100 96 / 100 🟢 Passed
Desktop Performance 68 / 100 99 / 100 🟢 Passed
LCP (Largest Contentful Paint) 5.8s 1.6s 🟢 Good
FCP (First Contentful Paint) 2.9s 0.9s 🟢 Good
TBT (Total Blocking Time) 940ms 85ms 🟢 Good
CLS (Cumulative Layout Shift) 0.32 0.01 🟢 Good

Key Takeaways for Developers

  • Audit your Liquid assets: Don't trust theme uninstalls; check theme.liquid manually for leftover app code.
  • Master fetchpriority="high": Always use eager loading and high priority for your primary hero image.
  • Control third-party execution: Never let non-essential tracking scripts block the primary rendering thread.

Need Help Optimizing Your Shopify Store?

I am a Shopify & Laravel Full-Stack Developer specializing in custom theme builds, Vue.js storefronts, and conversion-rate optimization.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.