smplx.
Shopify SEO

Core Web Vitals for Shopify: Performance as a Ranking Factor

smplx. Team··13 min

Introduction: Why Performance Is Now a Ranking Factor

Since May 2021, Core Web Vitals have been an official ranking factor for Google. This means: a fast store ranks better than a slow one, even if the content is identical.

Even more importantly: Conversion rate and Core Web Vitals are directly correlated. Studies show:

  • Every second of delay costs you 7% in conversions
  • A store with "good" Core Web Vitals converts 24% better than a store rated "poor"
  • Mobile performance is critical: 65% of e-commerce traffic comes from mobile

For Shopify stores, this is particularly important because:

  1. Many apps slow down performance
  2. Third-party scripts (analytics, tracking, marketing) quickly become unmanageable
  3. Mobile-first indexing favors fast mobile pages

At smplx., we brought stores like Bekateq from 4.2 seconds down to 2.1 seconds LCP – increasing their conversion rate by 18%.

In this article, we'll show you how to master Core Web Vitals.

1. Understanding the Three Core Web Vitals

LCP (Largest Contentful Paint) – Perceiving Speed

What is LCP? LCP measures how quickly the largest visible content loads. This is typically:

  • A product image
  • A hero banner
  • A text block

Benchmark:

  • Green (good): < 2.5 seconds
  • Orange (needs improvement): 2.5 – 4.0 seconds
  • Red (poor): > 4.0 seconds

How Google measures LCP:

User starts the page
     ↓
[0s] White
[0.5s] Logo appears
[1.2s] Text becomes visible
[2.0s] HERO IMAGE LOADS ← This is your LCP
[2.5s] Additional elements load

LCP is therefore not the time until the page is fully loaded, but until the largest element is visible.

INP (Interaction to Next Paint) – Feeling the Response

What is INP? INP measures the time between user action and visual response:

  • User clicks on filter button
  • [Delay] ← This is INP
  • Filters are applied

Benchmark:

  • Green: < 200 milliseconds
  • Orange: 200 – 500 ms
  • Red: > 500 ms

Typical INP problems in Shopify:

  • Filter/sort buttons respond slowly
  • Product options (color, size) change with delay
  • Add-to-cart button freezes
  • Search suggestions take too long

CLS (Cumulative Layout Shift) – Feeling the Stability

What is CLS? CLS measures how much the layout unexpectedly shifts. Every movement is frustrating:

Example of bad CLS:

User sees price: €89.99
User wants to click
[Currency symbol loads] ← Layout shifts by 0.05 units
User clicks too early or misses

Benchmark:

  • Green: < 0.1
  • Orange: 0.1 – 0.25
  • Red: > 0.25

Main causes of CLS in Shopify:

  • Images without defined height
  • Embedded ads/pop-ups
  • Lazy-loaded images
  • Fonts still loading

2. Optimizing LCP: The Hero Image Strategy

Problem: Hero Images Are Often Too Large

A typical hero image on Shopify:

  • Size: 2-5 MB (uncompressed)
  • Format: JPG
  • Resolution: 1920x1200px

This can mean 4-6 seconds LCP, especially on mobile.

Solution: WebP + Responsive Images

Step 1: Use WebP format

WebP is 25-35% smaller than JPG, with the same quality.

<!-- Shopify Section Code -->
<picture>
  <source srcset="{{ 'hero.webp' | asset_url }}" type="image/webp">
  <img src="{{ 'hero.jpg' | asset_url }}" alt="Hero Banner" loading="eager">
</picture>

Step 2: Define responsive image sizes

<img
  src="{{ hero_image | img_url: '800x600' }}"
  srcset="{{ hero_image | img_url: '400x300' }} 400w,
          {{ hero_image | img_url: '800x600' }} 800w,
          {{ hero_image | img_url: '1200x900' }} 1200w"
  sizes="(max-width: 600px) 400px,
         (max-width: 1024px) 800px,
         1200px"
  alt="Hero"
  loading="eager">

This ensures:

  • Mobile gets the 400px image (instead of 1920px)
  • Tablet gets the 800px image
  • Desktop gets the 1200px image

Result: LCP from 4.2s to 2.1s (typical for Bekateq-type optimizations)

Step 3: Preload Critical Resources

Add to the theme's <head>:

<link rel="preload" as="image" href="{{ 'hero.webp' | asset_url }}" imagesrcset="{{ 'hero-400.webp' | asset_url }} 400w, {{ 'hero-800.webp' | asset_url }} 800w" imagesizes="(max-width: 600px) 400px, 800px">
<link rel="preload" as="font" href="{{ 'font.woff2' | asset_url }}" type="font/woff2" crossorigin>

Preload tells the browser: "This resource is important, load it immediately."

3. Preventing CLS: Layout Stability

Most Common CLS Mistakes in Shopify and Solutions

Mistake 1: Images without defined aspect ratio

<!-- WRONG: Browser doesn't know how much space to reserve -->
<img src="product.jpg" alt="Product">

<!-- RIGHT: With CSS Aspect Ratio -->
<img
  src="product.jpg"
  alt="Product"
  width="400"
  height="400"
  style="aspect-ratio: 1;">

Mistake 2: Lazy-loaded images without container

/* WRONG: No space reserved */
.product-image {
  width: 100%;
  /* Height missing! */
}

/* RIGHT: Padding-bottom trick */
.product-image-container {
  position: relative;
  width: 100%;
  padding-bottom: 100%; /* 1:1 Aspect Ratio */
}

.product-image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

Mistake 3: Fonts loading and changing the layout

/* WRONG: Fallback font causes shift */
body {
  font-family: 'Roboto', sans-serif;
}

/* RIGHT: Load Roboto without shift */
@font-face {
  font-family: 'Roboto';
  src: url('roboto.woff2') format('woff2');
  font-display: swap; /* Show fallback, replace later */
}

With font-display: swap, the page is displayed immediately with the fallback font, and Roboto loads in the background.

Mistake 4: Ads and pop-ups injected (Google Ads, Intercom, etc.)

// WRONG: Ad is injected, shifts layout
<div id="ad-container"></div>
<script>
  // Ad loads afterwards
  loadAd();
</script>

// RIGHT: Container with fixed height
<div id="ad-container" style="height: 250px; overflow: hidden;"></div>
<script>
  loadAd(); // Fits into the container
</script>

4. Optimizing INP: Fast Interactions

The INP Problem in Shopify

The biggest INP killer in Shopify is too much JavaScript:

  1. Too many apps installed

    • Each app injects JavaScript
    • 10 apps = potentially 500KB+ extra JavaScript
  2. Heavy event listeners

    • Product options (variant selection) are often slow
    • Filter application takes too long
  3. Render-blocking scripts

    • Analytics, tracking code blocks page render

Solution: Optimize JavaScript

Step 1: Fewer apps

Audit your installed apps:

Admin > Apps and Channels > Apps and Sales Channels

Questions:

  • Do I really need this app?
  • Can another app take over 2-3 functions?
  • Does the app cause noticeable performance losses?

Effect: Each removed app saves 10-50KB of JavaScript.

Step 2: Load third-party scripts asynchronously

<!-- WRONG: Blocks page render -->
<script src="analytics.js"></script>

<!-- RIGHT: Load asynchronously -->
<script async src="analytics.js"></script>

<!-- RIGHT: Load deferred (after page load) -->
<script defer src="analytics.js"></script>

Step 3: JavaScript code splitting

If your theme has a lot of custom JavaScript, split it up:

// WRONG: Everything in one large bundle
// main.js = 250KB (product page, checkout, etc. all in one)

// RIGHT: Split by page
// products.js = 80KB (product page only)
// checkout.js = 60KB (checkout only)
// common.js = 50KB (on all pages)

Step 4: Event listener optimization

For variant selector (often very slow):

// WRONG: Event listener on EVERY variant button
document.querySelectorAll('.variant-btn').forEach(btn => {
  btn.addEventListener('click', updatePrice); // Modifies DOM
  btn.addEventListener('click', updateImage); // Modifies DOM
  btn.addEventListener('click', updateInventory); // Modifies DOM
});

// RIGHT: Event delegation + batched updates
document.addEventListener('click', (e) => {
  if (e.target.matches('.variant-btn')) {
    const updates = {
      price: calculatePrice(),
      image: getImage(),
      inventory: getInventory()
    };
    // All updates in one render step
    updateDOM(updates);
  }
});

5. Case Study: Bekateq – From 4.2s to 2.1s LCP

Bekateq is a B2B e-commerce store for large-scale distribution with 24 product templates and high performance requirements.

Starting point:

  • LCP: 4.2 seconds
  • CLS: 0.18 (orange)
  • INP: 280ms (orange)

Problems identified:

  1. Hero images were 3-4 MB JPGs, responsive images were missing
  2. 12 apps installed, many tracking every page view
  3. No lazy loading on product images
  4. Variant selector triggered complete DOM re-render

Implemented optimizations:

  1. LCP: WebP conversion + responsive image sizes → LCP drops to 2.1s
  2. CLS: Aspect ratio definition on all images → CLS drops to 0.05
  3. INP: 3 redundant apps uninstalled, event listeners optimized → INP drops to 140ms

Results:

  • Visibility: +34%
  • Organic traffic: +47%
  • Conversion rate: +18%
  • Bounce rate: -22%

6. Shopify-Specific Performance Bottlenecks

Apps and Their Performance Impact

Heavy apps (>100KB JavaScript):

  • Product review apps
  • Live chat tools
  • Inventory management
  • Advanced analytics

Alternative: Use native Shopify features where possible.

Third-Party Scripts

The biggest performance killers:

1. Google Tag Manager (GTM): +50KB
2. Facebook Pixel: +40KB
3. Intercom / Live Chat: +100KB
4. Zendesk: +80KB
5. Affiliate Tool: +60KB

Solution: Defer and conditionally load scripts

<!-- Load chat only on product pages -->
<script>
  if (window.location.pathname.includes('/products/')) {
    const s = document.createElement('script');
    s.src = 'chat.js';
    document.body.appendChild(s);
  }
</script>

7. Monitoring Core Web Vitals in Shopify Admin

Using Google PageSpeed Insights

  1. Go to PageSpeed Insights
  2. Enter your store URL
  3. See analyses for mobile and desktop

Important: PSI uses FieldData (real users) from Chrome users. This means values can change daily.

Search Console Report

In Google Search Console (configured for your store):

  1. Open the "Core Web Vitals" report
  2. See how many pages are in the green, orange, and red range
  3. Click on a problem to see affected URLs

Example:

  • 85% of pages have "good" Core Web Vitals → Good
  • 10% of pages "need improvement" → Work on it!
  • 5% of pages are "poor" → Fix urgently

Custom Monitoring with Web Vitals Library

You can also measure Core Web Vitals yourself:

// Embed in theme
<script>
  // Measure LCP
  const observer = new PerformanceObserver((list) => {
    const entries = list.getEntries();
    const lastEntry = entries[entries.length - 1];
    console.log('LCP:', lastEntry.renderTime || lastEntry.loadTime);
  });
  observer.observe({entryTypes: ['largest-contentful-paint']});

  // Measure CLS
  let clsValue = 0;
  const clsObserver = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      if (!entry.hadRecentInput) {
        clsValue += entry.value;
      }
    }
    console.log('CLS:', clsValue);
  });
  clsObserver.observe({entryTypes: ['layout-shift']});
</script>

8. Setting Performance Budgets

What Is a Performance Budget?

A performance budget is a "ceiling" that you must not exceed:

LCP Budget: 2.5 seconds
CLS Budget: 0.1
INP Budget: 200ms
JS Bundle Size: 250KB
CSS Bundle Size: 50KB
Total Image Size: 500KB

Benefit: If a new app is too heavy, it gets rejected.

Enforcing the Budget

  1. For new apps: "Will this app push LCP over 2.5s?" → No? → Install
  2. For new features: "Will this custom code cause CLS?" → No? → Code it
  3. Reviews: Check every 3 months whether the budget is being maintained

9. The smplx. Performance Optimization

Shopify Performance Audit & Optimization (from 6k €):

  • Comprehensive Core Web Vitals analysis (LCP, CLS, INP)
  • Image optimization & WebP conversion
  • JavaScript minification and code splitting
  • Lazy loading implementation
  • App audit and recommendations
  • Custom performance fixes
  • Google PageSpeed optimization

Ongoing Performance Monitoring (from 1.5k €/mo):

  • Monthly Core Web Vitals reports
  • Performance regression detection
  • App performance testing
  • Quarterly optimization recommendations

This investment pays for itself quickly through higher conversions.

10. Performance Quick Wins (Immediately Implementable)

  1. Compress images: Use TinyPNG or Shopify's native image editor
  2. Enable lazy loading: loading="lazy" on product images
  3. Render-blocking JavaScript: Use async/defer
  4. Cache favicon: Save many small requests
  5. Browser caching: Shopify does this automatically, check headers

Conclusion: Performance Is No Longer a Nice-to-Have

Core Web Vitals are now part of the Google ranking algorithm. A slow store is penalized not only by users but also by Google.

The good news: Many optimizations are relatively simple and have massive ROI:

  • Better rankings
  • Higher conversion rates
  • Better user experience
  • Lower bounce rate

Next steps:

  1. Open PageSpeed Insights and check current values
  2. Search Console > Core Web Vitals Report
  3. Identify top 3 problems
  4. Prioritize by impact (LCP > CLS > INP)

If you need comprehensive performance optimizations, contact the smplx. team. We optimize Shopify stores daily and know exactly which levers deliver the most performance gains.

Contact: hello@smplx.de | Coesfeld, NRW