100% Working Shopify Speed Score Optimization

100% Working Shopify Speed Score Optimization (Get 90+ on Shopify)

Reaching 90+ on Shopify's mobile PageSpeed score is achievable for most stores, but it requires working through every layer in the right order. Scores above 90 on mobile are not about tricks or optimization apps promise in their marketing copy. They come from correctly sized and formatted images, minimal JavaScript, lean CSS, deferred non-critical resources, and a Liquid template that generates fast server responses. This guide shows exactly what pushes stores into the 90+ tier and what keeps most stores stuck below 60.

30%
Score weight of Total Blocking Time - the single most impactful metric to fix
25%
Score weight of Largest Contentful Paint - target under 2.0s for 90+
<150ms
TBT target on mobile simulation for stores aiming at 90+ PageSpeed
28 days
Time for real improvements to appear in Shopify's admin speed score via CrUX data

What Shopify Speed Scores Actually Measure

Shopify PageSpeed score metric weights infographic showing a circular gauge at 90 plus in green and a horizontal bar chart with six weighted metrics: Total Blocking Time at 30 percent weight as the largest bar in dark blue, Largest Contentful Paint at 25 percent in blue, Cumulative Layout Shift at 15 percent in medium blue, First Contentful Paint at 10 percent in light blue, Speed Index at 10 percent in teal, and Interaction to Next Paint at 10 percent in cyan, with Good target values labeled next to each bar
Shopify PageSpeed Score Metric Weights - Total Blocking Time carries 30 percent of the score, making JavaScript reduction the single highest-impact optimization category. Fix TBT first, then LCP, then CLS.

Before chasing a number, understand what the number represents. Shopify's speed score in your admin and Google PageSpeed Insights are related but not identical.

Shopify's Online Store Speed Score

Found in Online Store > Themes, this score is based on real user data collected by Google's Chrome User Experience Report (CrUX) over the past 28 days. It reflects how real visitors on real devices in real conditions experienced your store. This score moves slowly - a change you make today will not fully appear for up to four weeks. Do not use it to test individual changes.

Google PageSpeed Insights Score

A lab score generated by running Lighthouse against your URL using a simulated mid-range Android device on a throttled 4G connection. Reproducible within a range (typically plus or minus 5 to 8 points between runs) and responds to changes within minutes. Use PageSpeed Insights for testing individual changes. Use the Shopify speed score and Google Search Console Core Web Vitals for understanding real user experience.

The PageSpeed score is a weighted average of six performance metrics. Understanding this weighting changes how you prioritize fixes. Total Blocking Time is the dominant metric - it measures the total time that render-blocking JavaScript occupied the main thread between FCP and Time to Interactive. Reducing JavaScript has more impact on the overall score than any other single category of fix.

Metric Score Weight Good Target 90+ Target
Total Blocking Time 30% <200ms <150ms
Largest Contentful Paint 25% <2.5s <2.0s
Cumulative Layout Shift 15% <0.1 <0.05
First Contentful Paint 10% <1.8s <1.5s
Speed Index 10% <3.4s <2.5s
Interaction to Next Paint 10% <200ms <150ms

Where Shopify Stores Lose the Most Points

Scores 20 to 45 (Most Common Starting Point)

Dominant problems are almost always App Script bloat and unoptimised images. Stores in this range typically have 15 or more installed apps loading scripts globally, hero images above 500KB, no lazy loading on collection page images, and multiple render-blocking scripts in the head. Fixing just images and removing the most impactful app scripts typically moves stores to the 55 to 65 range.

Scores 45 to 65

Foundational issues are partially addressed but not complete. Common remaining problems: a few heavy apps still loading globally, fonts loading without preconnect or font-display swap, JavaScript libraries like jQuery or Swiper loading when native alternatives would work, and no critical CSS implementation. Addressing these moves stores into the 65 to 75 range on mobile.

Scores 65 to 80

The foundational work is largely done. Points are being lost to more specific issues: render-blocking third-party scripts that are hard to defer, suboptimal resource loading sequence, LCP image lacking fetchpriority high, and CSS that could be partially inlined. Total Blocking Time is often the remaining dominant issue. Addressing TBT through script deferral, JavaScript splitting, and critical CSS inlining moves stores into the 80 to 90 range.

Scores 80 to 90 (Targeting 90+)

The remaining points require precise work: the LCP image preloaded with correct srcset hints, all non-critical CSS loading asynchronously, every scroll listener using passive true, no layout-triggering CSS animations, variant data pre-rendered into JavaScript objects, and Liquid templates generating minimal TTFB. The difference between 85 and 92 is often 3 to 4 specific diagnostics each costing 2 to 4 points.

Fixing the Highest-Impact PageSpeed Audit Issues

PageSpeed Insights groups its diagnostics into Opportunities (estimated time savings) and Diagnostics (issues affecting performance but without direct time savings estimates). Fix Opportunities first - they have the most direct score impact.

1
Eliminate Render-Blocking Resources
This diagnostic appears on almost every Shopify store. Render-blocking resources delay FCP and increase TBT, which directly reduces your score on the highest-weighted metric. Fix render-blocking CSS with the preload-then-swap pattern and inline critical CSS. Fix render-blocking JavaScript by adding defer to all non-critical scripts.
<head>
  <style>
    /* Critical above-fold styles inlined here - 8 to 15KB */
    body { margin: 0; font-family: system-ui, sans-serif; }
    .site-header { position: sticky; top: 0; z-index: 10; background: #fff; }
    .hero { min-height: 400px; background: #f5f5f5; }
  </style>

  <link
    rel="preload"
    href="{{ 'theme.css' | asset_url }}"
    as="style"
    onload="this.onload=null;this.rel='stylesheet'"
  >
  <noscript><link rel="stylesheet" href="{{ 'theme.css' | asset_url }}"></noscript>
</head>
2
Properly Size Images
Every image served larger than its display size wastes download time. PageSpeed lists specific images with their current size and potential savings. Use Shopify's image_url filter with explicit widths and WebP format, plus a srcset for responsive delivery.
<img
  src="{{ product.featured_image | image_url: width: 800, format: 'webp' }}"
  srcset="
    {{ product.featured_image | image_url: width: 400, format: 'webp' }} 400w,
    {{ product.featured_image | image_url: width: 800, format: 'webp' }} 800w
  "
  sizes="(max-width: 768px) 100vw, 50vw"
  width="{{ product.featured_image.width }}"
  height="{{ product.featured_image.height }}"
  loading="lazy"
  alt="{{ product.featured_image.alt | escape }}"
>
3
Reduce Unused JavaScript
The Coverage tab in Chrome DevTools shows the percentage of each JavaScript file that executes during page load. Files with low usage percentages are candidates for conditional loading or removal. For app scripts: restrict to relevant page templates using Liquid conditionals. For library scripts (jQuery, Swiper): replace with native alternatives.
4
Serve Images in Next-Gen Formats
Every JPEG or PNG image in your PageSpeed audit is a conversion opportunity. Shopify's CDN converts to WebP automatically when you use format: 'webp' in the image_url filter. This one change to your Liquid templates fixes this diagnostic across all images simultaneously.

Optimizing the Key Metrics for 90+

Ideal Shopify page load sequence timeline showing 10 numbered steps: step 1 HTML document received with TTFB under 400ms, step 2 Critical CSS renders immediately, step 3 LCP image begins downloading with preload and fetchpriority high, step 4 First Contentful Paint occurs with a green checkmark, step 5 Body font loaded via preloaded WOFF2, step 6 Theme JavaScript loads deferred, step 7 LCP image fully rendered with a green checkmark, step 8 Page becomes interactive and TBT stops, step 9 Below-fold images lazy load on scroll, step 10 Non-critical scripts load at idle, with color coding from blue for critical path to gray for deferred resources
Ideal Shopify Page Load Sequence - every deviation from this order costs points. A render-blocking script between steps 1 and 3, a large non-preloaded LCP image, or non-deferred app scripts executing before step 8 each reduce your score on the highest-weighted metrics.
Total Blocking Time (30% weight)

Target: under 150ms for 90+. TBT is the sum of all long task durations (tasks over 50ms) that occur between FCP and Time to Interactive. Fix by deferring all non-critical JavaScript, splitting large JavaScript files into smaller modules, replacing synchronous app scripts with deferred alternatives, removing unused JavaScript, and replacing JavaScript behavior with CSS where possible.

Largest Contentful Paint (25% weight)

Target: under 2.0s for 90+. Fix sequence: identify the LCP element (PageSpeed tells you exactly which element), add fetchpriority="high" and loading="eager" to that element, add a preload hint in the head, ensure the image is WebP and sized to display width, add preconnect for Shopify's CDN, and reduce TTFB through Liquid optimization.

Cumulative Layout Shift (15% weight)

Target: under 0.05 for 90+. Fix sequence: add explicit width and height to every img tag, add font-display swap to all custom fonts, reserve space for dynamic content (announcement bars, app widgets), fix any embed or iframe without declared dimensions, and use transform instead of top/left for CSS animations.

Interaction to Next Paint (10% weight)

Target: under 150ms for 90+. Fix sequence: add { passive: true } to all scroll and touch event listeners, break up long-running JavaScript functions using setTimeout chunking, load app scripts only on pages where they function, replace synchronous event handlers with debounced versions, and initialize non-critical features with requestIdleCallback.

How to Improve the Load Sequence

The load sequence is the order in which resources download and render. An optimal sequence loads the minimum content needed to show something to the visitor as fast as possible, then progressively loads everything else.

<head>
  <!-- 1. Preconnects and preloads first -->
  <link rel="preconnect" href="https://cdn.shopify.com" crossorigin>
  <link rel="preload" as="image" href="{{ lcp_image_url }}">
  <link rel="preload" as="font" href="{{ font_url }}" crossorigin>

  <!-- 2. Critical CSS inlined -->
  <style>/* Critical styles */</style>

  <!-- 3. Full stylesheet preloaded asynchronously -->
  <link rel="preload" href="{{ 'theme.css' | asset_url }}" as="style"
    onload="this.onload=null;this.rel='stylesheet'">

  <!-- 4. Theme JavaScript deferred -->
  <script src="{{ 'theme.js' | asset_url }}" defer></script>

  <!-- 5. Analytics via GTM - async, independent -->
  <script async src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXX"></script>
</head>
Use WebPageTest.org's filmstrip view to see exactly what your page looks like at 100ms intervals during loading. A well-optimized sequence shows content appearing early (FCP at 0.8 to 1.5 seconds) and stable (no layout shifts after initial render). A blank screen at 1.5 seconds that should be showing your hero image indicates the LCP image is loading too late - pointing directly to a missing preload hint or competing high-priority download.

Testing with GTmetrix

GTmetrix provides a different view of performance than PageSpeed Insights. Using both gives you a more complete picture.

Long Initial Rows

The first 5 to 10 rows of the waterfall are your critical path. If any of these show long wait times (thin bars that extend far right before the download begins), you have a render-blocking resource or high TTFB issue.

Late-Starting Image Downloads

If your LCP image request starts at 1.5 seconds into the waterfall, it was not preloaded. The browser discovered it late during CSS parsing or JavaScript execution. Add a preload hint in the head.

Parallel External Script Loads

Rows showing simultaneous downloads from multiple external domains (connect.facebook.net, static.klaviyo.com, cdn.hotjar.com) represent your third-party script overhead. Consolidating through GTM reduces these rows to one.

GTmetrix test configuration for Shopify: Test location: a server geographically distant from you (to measure CDN impact). Browser: Chrome. Connection: 4G LTE (matches PageSpeed mobile simulation). Adblock: disabled (your real visitors see ads). Run three GTmetrix tests and compare with three PageSpeed tests - the waterfall findings complement each other even though the scores differ.

Realistic Benchmarks for Shopify Stores

Shopify mobile PageSpeed score targets by store type table showing five rows: Simple store with 1 to 10 products and 0 to 3 apps showing realistic target of 85 to 92 and achievable with full optimization of 90 plus in green; Standard store with standard theme and 5 to 10 apps showing 68 to 78 and 80 to 87 in blue; Feature-rich store with 10 to 15 apps and video content showing 55 to 68 and 72 to 82 in yellow; Large catalog with many variants and 15 plus apps showing 45 to 60 and 65 to 75 in orange; Enterprise store with complex customizations showing 40 to 58 and 62 to 72 in red
Shopify Mobile PageSpeed Score Targets by Store Type - a 75 on mobile from a well-managed 12-app store is genuinely excellent performance. Set your target based on your store's complexity, not an arbitrary number.
What 90+ on mobile actually requires: Total page weight on mobile under 800KB for the homepage, JavaScript under 200KB total transfer, no more than 3 to 4 external script domains, LCP under 1.8 seconds, CLS under 0.05, TBT under 150ms, and TTFB under 300ms consistently. Most Shopify stores with a typical app stack and standard themes are not at 90+ on mobile - and that is not a failure. A mobile score of 70 to 80 with all Core Web Vitals in the Good range represents genuinely excellent performance.

Iterative Improvement Strategy

Reaching 90+ is not a single optimization session. It is a series of targeted improvements, each measured before moving to the next.

1
Run three PageSpeed tests. Record average score and metrics.
2
Identify the Opportunity with the largest estimated savings.
3
Implement the fix on a development theme. Push to live theme or test on development theme preview.
4
Wait 15 minutes for Shopify's CDN cache to clear. Run three PageSpeed tests. Record new scores and document the change and the improvement. Repeat.

Expected progression for a typical store starting at 35 on mobile:

Optimization Expected Score Gain
Image optimization (WebP, correct sizing, lazy loading) +12 to 18 points
App audit and heavy script removal +8 to 15 points
JavaScript deferral and critical CSS +6 to 12 points
LCP image preload and fetchpriority +4 to 8 points
Font optimization and CLS fixes +3 to 6 points
Advanced prioritization and TBT reduction +3 to 8 points

Avoiding Fake Optimizations

The lazy loading mistake that hurts LCP: Adding loading="lazy" to your LCP image is one of the most common optimization mistakes. It appears in optimization guides, is easy to implement, and actively worsens the metric you are trying to improve. Your LCP image must use loading="eager" and fetchpriority="high". Check every theme update you apply, as theme updates sometimes change image attributes.
Score Gaming Without Real Improvement

Some services detect the PageSpeed bot's user agent and serve a stripped-down version of your store. This inflates your lab score without helping real visitors. Google has countermeasures for detected bot-targeting, and this approach can result in penalization. Real improvements show up in both lab and field data. Fake optimizations show up only in lab data.

Optimization Apps That Add to the Problem

A PageSpeed optimization app that loads its own JavaScript bundle on every page is working against itself. Evaluate any speed app by testing your PageSpeed score before and after installation on a development theme - not by reading its marketing claims. The data tells the truth regardless of what the app claims.

Getting to 90+ Final Checklist

Foundation

  • All images converted to WebP using format: 'webp'
  • All images sized to maximum display width
  • Explicit width and height on every img tag
  • loading="lazy" on all below-fold images
  • loading="eager" and fetchpriority="high" on the LCP image
  • All unused apps uninstalled (not just disabled)
  • All remaining app scripts restricted to relevant page templates
  • All non-critical theme JavaScript using defer

TBT Reduction (Highest Weight)

  • No synchronous scripts in the head without defer or async
  • Third-party tracking consolidated into Google Tag Manager
  • GTM configured with page-specific triggers (not All Pages for every tag)
  • JavaScript Coverage shows no file below 30% usage on this page
  • Scroll and touch event listeners using { passive: true }
  • Long tasks under 50ms in Chrome DevTools Performance recording
  • No jQuery loaded if theme or app code does not require it

LCP and CSS

  • LCP image preload hint in head with imagesrcset and imagesizes
  • Preconnect to Shopify CDN in head with crossorigin
  • TTFB under 400ms (check with WebPageTest)
  • Critical CSS inlined in style tag in head
  • Full stylesheet loading asynchronously via preload-then-swap
  • font-display: swap on all @font-face declarations
  • No CSS animations using top, left, width, height (use transform only)

Verification

  • TBT under 200ms in PageSpeed mobile test (ideally under 150ms)
  • LCP under 2.5 seconds (ideally under 2.0 seconds)
  • CLS under 0.1 (ideally under 0.05)
  • INP under 200ms in PageSpeed mobile test
  • Tested on real mid-range Android device
  • Scores tested with cold cache (WebPageTest First View)
  • Lab scores validated against Search Console field data after 28 days

Summary

Reaching 90+ on Shopify's mobile PageSpeed requires solving every layer of the performance stack in the right order. Images first, then JavaScript, then CSS, then LCP prioritization, then TBT reduction, then CLS elimination. Each layer you fix unlocks more improvement from the next.

The score is a means to an end, not the end itself. The real goal is a store that loads in under 2 seconds on a real phone, responds instantly to taps, and never shifts layout while loading. A store that achieves those things scores above 90 almost automatically.

Avoid fake optimizations that game the score without improving real user experience. Validate every improvement against real user data in Search Console. And set realistic targets based on your store's complexity - a 75 on mobile from a well-managed 12-app store is genuinely excellent performance, even if it is not 90.

For stores looking to systematically work through each optimization layer with Shopify-native tooling, Ecom: Page Speed Expert handles image optimization, script management, and performance monitoring without adding the kind of script overhead that other optimization apps introduce. Work through the checklist. Test every change. The 90+ score is not a secret - it is the result of doing the fundamentals completely.
Back to blog

Frequently Asked Questions


Yes, for stores with straightforward requirements. A store with 3 to 5 apps, optimized images, and a lean theme can reach 90 to 95 on mobile. A store with 15 apps, video content, and a feature-rich theme can typically reach 65 to 75 with full optimization — which is excellent performance even if it is not 90+. Set your target based on your store's complexity, not an arbitrary number.


PageSpeed Insights runs a Lighthouse test from Google's infrastructure. Server response times vary with server load. CDN cache state varies between tests. The mobile simulation network conditions have natural variance. Running three tests and averaging gives you a reliable number. A single test can vary by 5 to 10 points in either direction from the "true" score.


Possibly. Check what metric improved. If TBT dropped dramatically because you deferred a large synchronous script, a 15-point jump is realistic — TBT carries 30 percent of the score weight. Validate by running three tests to confirm it is stable, then check WebPageTest to confirm the waterfall shows the change you intended.


Core Web Vitals in the Good range (LCP under 2.5s, INP under 200ms, CLS under 0.1) is the right business target because these directly affect SEO rankings and user experience. The PageSpeed score is a useful proxy for these metrics but is not itself a ranking signal. A store with a 72 PageSpeed score and all Core Web Vitals in Good will rank the same as a 92 PageSpeed store with identical Core Web Vitals. Prioritize the vitals; the score follows.


For a developer familiar with Shopify: 3 to 6 days of focused work covering image optimization, app audit, script deferral, critical CSS, and LCP prioritization. For a store owner without developer access: 2 to 4 weeks working through each layer with tool assistance. For stores with complex custom code or deeply integrated apps: 2 to 4 weeks of developer time. The work compounds — foundational fixes unlock the impact of advanced fixes, so the order matters as much as the fixes themselves.