Shopify Speed Optimization: The App Scripts Are the Problem, Not the Theme
I ran four well-known Shopify stores through PageSpeed Insights. Third-party scripts, not the theme, tracked every failing vital. Here is the triage order.

I measured four Shopify product pages through the PageSpeed Insights API on September 25, 2026. The slow ones were not slow because of the theme:
- JavaScript tracked responsiveness: Allbirds shipped 1.7 MB of JavaScript from 7 third-party script origins and passed INP at 190 ms. Brooklinen shipped 4.0 MB from 44 origins and sat at 459 ms. Kylie Cosmetics, 4.5 MB from 38 origins, was at 312 ms.
- Every store passed LCP except the one whose hero image was not in the HTML: Brooklinen's product image is injected by JavaScript, so Chrome cannot discover it early. Field LCP was 4.73 s against a 2.5 s threshold. The other three were between 1.06 s and 1.85 s.
- The HTML undercounts the apps: Counting <script src> tags found 1 to 15 third-party origins per page. The browser loaded 7 to 44, because tag managers and app embeds inject the rest at runtime.
- Triage in this order: Remove or defer app scripts, then fix the LCP image, then fonts and app-block layout shifts, then the theme. Shopify's own docs call removing third-party scripts the highest-impact fix.
"shopify speed optimization" gets 170 US searches a month at a keyword difficulty of 19 (DataForSEO, US, September 2026). Every page ranking for it lists tips; none of them measured a store.
Every Shopify speed guide I found lists the same tips and measures nothing. I ran four well-known stores through the PageSpeed Insights API on September 25, 2026, counted their scripts, and read Shopify's own docs. This guide reports the numbers and the triage order they point to. Try CrawlRaven free: 1 site, no credit card →
The short answer: count the scripts before you blame the theme
A merchant on r/shopify wrote in October 2025: "I've already compressed images and tried implementing lazy loading, but it's not moving the needle much." The first reply opened with three words: audit your apps. That thread now ranks third organically for "shopify speed optimization", above every agency guide.
The reply is right, and I wanted numbers behind it. So I ran product pages from Allbirds, ColourPop, Kylie Cosmetics and Brooklinen through the PageSpeed Insights API on mobile on September 25, 2026, and read each run's network log.
Shopify speed optimization, in the right order, is: remove or defer the app scripts, then fix the hero image, then fonts and app-injected layout shifts, and only then the theme. Every store that failed a Core Web Vital failed it for a reason on that list.
Key Takeaways
- →JavaScript weight tracked responsiveness: 1.7 MB of JavaScript passed INP at 190 ms. 4.0 MB and 4.5 MB sat at 459 ms and 312 ms. Third-party code cost 0.8 s to 10.2 s of main-thread time across the four lab runs.
- →The hero image decided LCP: Three stores passed LCP between 1.06 s and 1.85 s. Brooklinen, at 4.73 s, was the only one whose product image was not in the HTML.
- →The HTML hides most of the apps: script src tags showed 1 to 15 third-party origins per page. The browser loaded 7 to 44.
What four Shopify product pages measure on mobile
I took one live product page from each of four recognisable stores and called the PageSpeed Insights API with the mobile strategy. Each response carries Chrome UX Report field numbers for real visitors and a throttled Lighthouse lab run. Field numbers are what Google uses, so they come first.
| Store, product page | LCP | INP | CLS | TTFB | Verdict |
|---|---|---|---|---|---|
| Allbirds | 1.06 s | 190 ms | 0.00 | 356 ms | Passes all three |
| ColourPop | 1.65 s | 169 ms | 0.19 | 211 ms | CLS needs improvement |
| Kylie Cosmetics (origin) | 1.85 s | 312 ms | 0.04 | 434 ms | INP needs improvement |
| Brooklinen | 4.73 s | 459 ms | 0.04 | 806 ms | LCP poor, INP needs improvement |
Chrome UX Report, 75th percentile, mobile, PageSpeed Insights, September 25, 2026. Kylie Cosmetics had no page-level data, so its row is the origin-level number. The thresholds come from web.dev: LCP within 2.5 seconds, INP of 200 milliseconds or less, CLS of 0.1 or less.
The same four pages, read from the Lighthouse network log, is where the apps show up:
| Store | JavaScript transferred | Third-party script origins | Third-party main-thread time | Lab blocking time | Heaviest third parties |
|---|---|---|---|---|---|
| Allbirds | 106 files, 1.7 MB | 7 | 0.8 s | 600 ms | Google Tag Manager 835 KB, Attentive 832 KB |
| ColourPop | 202 files, 2.4 MB | 36 | 2.4 s | 1,570 ms | Okendo 471 KB, Attentive 406 KB, Tolstoy 385 KB, Signifyd 260 KB |
| Kylie Cosmetics | 262 files, 4.5 MB | 38 | 5.7 s | 3,830 ms | Google Tag Manager 1,157 KB, Google Ads 425 KB, Forter 400 KB, Yotpo 320 KB |
| Brooklinen | 137 files, 4.0 MB | 44 | 10.2 s | 6,230 ms | Google Tag Manager 673 KB, Yotpo 414 KB, Dynamic Yield 317 KB, OneTrust 287 KB |
Origins exclude the store's own domain and cdn.shopify.com. Read the two tables together:
- Responsiveness followed JavaScript. Allbirds at 1.7 MB passed INP. Kylie Cosmetics at 4.5 MB and Brooklinen at 4.0 MB did not. Lab blocking time ran 600 ms, 1,570 ms, 3,830 ms and 6,230 ms, the same order as third-party main-thread time.
- One script can dominate. On ColourPop, Signifyd's fraud script cost 1,096 ms of main-thread time by itself. On Kylie Cosmetics, Google Tag Manager cost 2,276 ms and the Facebook pixel 602 ms.
- The only poor LCP was not an oversized image. Brooklinen's product image is inserted by JavaScript. Lighthouse flagged it as not discoverable in the initial document, with a 14.9 s resource load delay in the lab run.
- CLS came from injected content. ColourPop's 0.19 was the only failing CLS, on a page where review, video and chat widgets render after load.
Four Shopify product pages on mobile: field vitals vs JavaScript load
Field data vs lab data: why Lighthouse says 15 seconds and Chrome users say 1
The lab LCP values in these runs were 14.9 s, 16.6 s, 29.7 s and 44.0 s. Real Chrome users saw 1.06 s to 4.73 s. Both are true: Lighthouse simulates a mid-range phone on a slow connection and loads every script, popup and video, so a 5 MB to 17 MB page looks catastrophic.
Shopify's lab vs field guide draws the line the same way: field data to decide what to fix, lab data to debug why. The lab LCP breakdown is the useful part:
- Allbirds: 3,300 ms of element render delay after a 58 ms image download. Something painted over the image after it arrived; an Attentive popup loaded 832 KB on this page.
- Brooklinen: 14,902 ms of resource load delay, because the browser did not know the image existed until JavaScript ran. The page also pulled 8.7 MB of video.
The script count in the HTML is not the script count in the browser
I also fetched each product page's HTML with a desktop browser user agent and counted script tags, the way an audit tool does, then compared that with what the browser loaded:
| Store | Script tags in HTML | With a src | Third-party origins in HTML | Third-party origins loaded |
|---|---|---|---|---|
| Allbirds | 69 | 25 | 1 | 7 |
| ColourPop | 156 | 48 | 15 | 36 |
| Kylie Cosmetics | 115 | 38 | 7 | 38 |
| Brooklinen | 100 | 30 | 10 | 44 |
Allbirds' HTML names one third-party script host; the browser loaded seven, because Google Tag Manager and the Attentive embed fetch the rest. The static count tells you which apps wrote to the theme; the runtime count tells you what the visitor pays for.
What Shopify's Web performance dashboard measures
The single speed score is gone; its old help URL now redirects to the Online Store index. What Shopify offers today is the Web performance dashboard, and it is a field-data report:
- Three metrics, no composite score. LCP, INP and CLS, each graded Good, Moderate or Poor against the thresholds Google uses.
- Real visitors, 75th percentile. Real user data from the past 30 days, shown for the 75th percentile, so it matches Search Console.
- Delayed and short-lived. Data can lag by up to 36 hours and only 90 days are kept, so screenshot it before a change.
- Needs a public store. The page says to deactivate private mode first, so password-protected stores get nothing.
It tells you a vital is failing; PageSpeed Insights tells you which script or image caused it. Shopify's companion page, Improving your online store performance, leads its own checklist with apps and third-party code.
Why app scripts are the problem: script tags, app embeds and leftover code
Three mechanisms put app JavaScript on a Shopify storefront, and they clean up after themselves to very different degrees:
- Script tags (legacy). The ScriptTag resource injects a remote script into every storefront page and is "automatically removed" on uninstall. It is being retired: per the deprecation schedule, no creates or updates after October 1, 2026, and no injection from March 1, 2027.
- Theme app extensions (current). App blocks and app embed blocks, which replaced script tags in 2021. Shopify's extension guidelines state that on uninstall, blocks are "automatically and entirely removed" from themes.
- Code written into the theme. Snippets and inline scripts an app or a freelancer pasted into theme.liquid. Shopify's Help Center is blunt: "Uninstalling an app doesn't automatically remove its code from your theme."
The third category is why stores accumulate scripts for years. Shopify's third-party script guide calls it "death by a thousand cuts": a pixel here, an app that stopped being used there, and the code still executes on every page load.
The triage order: scripts, then images, then fonts, then the theme
This is the order the measured stores would need, and the order that costs least: step 1 is uninstalls, step 4 is a rebuild. Pick the pages first, though. A speed fix on a page with no clicks helps nobody.
One plug, here. CrawlRaven joins Search Console, GA4 and a 200-point crawl into one ranked plan, so a failing INP on a collection page earning 400 clicks a month outranks a perfect score on a page nobody visits. Speed findings sit beside duplicate collection URLs and thin product copy, ranked by what each fix is worth.
Lifetime licences launched at $49 for 3 sites. Lifetime pricing steps up as licenses sell, so check the pricing page for the current batch. See pricing.
Scripts, then images, then fonts, then the theme
Step 1: Inventory and remove app scripts
- List what the HTML loads. Paste a product URL into the free Shopify app script checker, which lists every external script the page references, grouped by host.
- List what the browser loads. Run the same URL through PageSpeed Insights and open the "3rd parties" insight. On these stores the runtime count was 2 to 7 times the static one.
- Rank by main-thread time, not bytes. Shopify's worst-offenders guide says a handful of scripts cause most of the damage. On ColourPop, one 260 KB fraud script cost more main-thread time than 964 KB of Shopify's own code.
- Uninstall what nobody can name a purpose for. Then open theme.liquid and the snippets folder and delete the leftovers. Admin-only apps can stay.
- Move pixels out of script tags. Use Shopify's web pixels, or a tag manager that fires each tag only where needed. Google Tag Manager cost 758 ms of main-thread time on Allbirds and 2,276 ms on Kylie Cosmetics.
- Load widgets on interaction. Chat, reviews and video can wait until the visitor taps them; Shopify documents the pattern under load JavaScript on user interaction.
Do not install a speed app to fix app bloat. Shopify's page on fake performance apps describes services that serve Lighthouse a lighter page than customers get; most were removed from the App Store and the trick is now sold as a freelance service.
Step 2: Fix the LCP image and let Shopify's CDN handle formats
On a product page the LCP element is almost always the main product image. Shopify's essential practices table rates three fixes high impact:
- Never lazy-load it. The docs call this "one of the most common and damaging performance anti-patterns in Shopify themes": loading="lazy" or a data-src loader hides the image from the preload scanner. All four stores got this right.
- Add fetchpriority="high", once. Images start at low priority until layout finishes; the hint removes that wait. ColourPop and Kylie Cosmetics set it; Allbirds and Brooklinen did not.
- Keep the image in the HTML. Brooklinen's arrives by JavaScript, and its field LCP is 4.73 s. Render the gallery in Liquid, first image as a plain img tag.
Formats are not your job. Shopify's image_url filter takes width, height, crop, format, quality and pad_color parameters, and the CDN "automatically detects which image formats are supported by the client (e.g. WebP, AVIF, etc.)" and picks one. That is why none of the four pages contained a .webp URL. The CDN never upscales.
Your job is the size. Use image_tag with srcset and sizes so a phone downloads a 600-pixel file, not the desktop one. Lighthouse estimated 1,478 KiB of image savings on Allbirds; 498 KB of it came from popup creatives served from an app's own host, outside Shopify's CDN.
The gap between the LCP image finishing its download and the browser painting it. Popups, cookie banners and fade-in animations add to it; Shopify has a page on popups hijacking LCP.
Step 3: Fonts, app blocks and the layout shifts they cause
CLS on a Shopify product page comes from two places: fonts swapping in late and widgets pushing content down after load. Both are cheap to fix:
- Set font_display explicitly. Shopify's font swapping guide notes the font_face filter adds no font-display descriptor unless you pass one, so Chrome hides text for up to 3 seconds. Pass font_display: 'swap', or use system fonts.
- Serve fonts from Shopify, not Google Fonts. The font picker serves from /cdn/fonts/ on your domain. Allbirds loaded four files from fonts.gstatic.com; ColourPop's Attentive popup loaded six of its own.
- Reserve space for app blocks. Review stars and trust badges render after the page does. Shopify's guide says to add Custom CSS on the parent section targeting .shopify-app-block with a min-height.
- Size every media element. One of ColourPop's recorded shifts and two of Kylie Cosmetics' came from a media element with no explicit size.
Step 4: Only now, the theme
After steps 1 to 3, measure again. If a vital still fails, check three theme-side causes before a swap:
- Content rendered by JavaScript. Shopify's essential practices say to render product info, hero content and navigation in Liquid, because client-side rendering "delays LCP and harms SEO". This is Brooklinen's problem.
- Nested Liquid loops. Products times variants times options grows with the catalogue and is, per the same page, the most common cause of high TTFB. Brooklinen's 806 ms field TTFB is the one number a theme edit, not an uninstall, would move.
- Too many sections. Shopify's Help Center warns that high numbers of sections lower performance.
If you do swap, know the bar. The Theme Store requirements set a minimum average Lighthouse performance score of 60 across product, collection and home page, desktop and mobile, on Shopify's benchmark dataset. Your store carries your apps on top of that.
What each fix moves
The matrix below is the shortcut for a store with one failing metric. Read across from the metric to the fixes that move it.
Match the fix to the metric that is failing
- INP failing: remove and defer scripts, load widgets on interaction, delete leftover snippets. High on INP, medium on LCP through render-blocking requests.
- LCP failing: eager hero with fetchpriority, srcset through image_tag, nothing covering the hero, content rendered in Liquid. All high in Shopify's essential practices.
- CLS failing: reserve space for app blocks and size media (high), then fonts (medium).
- TTFB high: flatten nested Liquid loops. A theme swap is medium on everything, because the apps come with you.
Why the numbers did not move after the fix
I uninstalled six apps and the dashboard is unchanged. Two waits are stacked: the dashboard lags up to 36 hours, and the 75th-percentile window covers 30 days of visits. Confirm the change in a fresh lab run today, then read the field number in a month.
The scripts are still in the waterfall after uninstall. Either the app wrote into the theme and the snippet is still there, or a tag manager is still firing its tag. Search the theme code for the host name, then audit the container.
- Lighthouse improved, real users did not. Check for a speed app or freelancer snippet that detects testing tools. A genuine fix shows pixels painting sooner in the filmstrip.
- LCP passes on the homepage, fails on collections. Different LCP element, usually the first product card image, often lazy-loaded by the grid. Apply the eager and fetchpriority rules to the first row.
- INP is fine in the lab and poor in the field. Lighthouse cannot measure INP because nobody taps the page. Trust the field number and cut the scripts that run on interaction: chat, variant pickers, cart drawers.
Shopify speed optimization FAQs
Measuring speed
How do I check Shopify store speed? Start with the Web performance dashboard in the admin, then run product and collection URLs through PageSpeed Insights for the diagnosis. The homepage is rarely the page that matters.
What is a good Shopify speed score? There is no single score any more. Pass LCP 2.5 s, INP 200 ms and CLS 0.1 on your money pages, at the 75th percentile.
Apps and scripts
Does uninstalling an app remove its code? Script tags and theme app extension blocks go automatically. Code written into theme files stays. Check theme.liquid after every uninstall.
What happens to script tags? No creates or updates after October 1, 2026; Shopify stops injecting them on March 1, 2027. Ask your app vendors now.
Images, fonts and themes
Should I lazy load images on Shopify? Below the fold, yes. Never the hero or main product image; load that one eagerly with fetchpriority="high".
Will a faster theme fix it? Not while the apps stay. The Theme Store floor is a 60 average Lighthouse score before your apps. Audit scripts first, then decide.
Where speed sits in the Shopify SEO plan
Speed is one finding among many on a Shopify store, and rarely the biggest (our Shopify SEO guide ranks it sixth of nine levers). Duplicate collection-path URLs and blank collection copy usually cost more rankings than a 300 ms INP. Fix speed on the pages that earn clicks, then move on.
- Before this: the Shopify SEO audit walks the duplicate URL and app-side problems that sit ahead of speed.
- Alongside this: the Shopify SEO checklist has a page-speed section this guide expands, and our Shopify SEO app roundup weighs each app's storefront footprint.
- While you are in the images: run the store through the image alt checker; resized product images usually need alt text too.
- Background: the page speed and Core Web Vitals glossary entries, and SaaS SEO vs ecommerce SEO on why templates multiply every decision.
Sources
- PageSpeed Insights API, mobile strategy, September 25, 2026, for product pages on allbirds.com, colourpop.com, kyliecosmetics.com and brooklinen.com. Field values are Chrome UX Report 75th percentile; lab values are Lighthouse 13.5. HTML script counts from the same pages fetched with a desktop Chrome user agent on the same day.
- web.dev: Web Vitals (LCP, INP and CLS thresholds)
- Shopify Help Center: Web performance dashboard and Improving your online store performance
- Shopify.dev theme performance: Performance best practices, Audit and remove third-party scripts, Finding your worst JavaScript offenders, Never lazy-load the LCP image, Mark the LCP image with fetchpriority, Serve correctly sized images, Reduce CLS from font swapping, Reserve space for app-injected content, Fake performance apps, Lab vs field data
- Shopify.dev apps: ScriptTag resource, Storefront script tag deprecation, Theme app extension UX guidelines
- Shopify.dev: image_url Liquid filter and Theme Store requirements
- r/shopify: What's the fastest way to increase site speed on Shopify? (October 2025)
- Keyword volume and difficulty: DataForSEO Labs, United States, September 2026. SERP observations: DataForSEO SERP API, United States desktop, September 25, 2026.
Frequently asked questions
How do I check my Shopify store speed?
Use field data first. Shopify's Web performance dashboard in the admin shows LCP, INP and CLS for your real visitors over the past 30 days at the 75th percentile. PageSpeed Insights shows the same Chrome UX Report numbers for any public URL, plus a Lighthouse lab run for diagnosis. Test product and collection pages, not just the homepage.
What is a good Shopify speed score?
Shopify no longer shows a single speed score. The Web performance dashboard grades each Core Web Vital against Google's thresholds: LCP of 2.5 seconds or less, INP of 200 milliseconds or less, and CLS of 0.1 or less, at the 75th percentile of visits. A store that passes all three on its money pages is in good shape.
Why is my Shopify store so slow on mobile?
In the four stores I measured, mobile responsiveness tracked JavaScript weight from apps. The store with 1.7 MB of JavaScript passed INP; the stores with 4.0 MB and 4.5 MB did not. Tag managers, review widgets, popups and fraud tools each add main-thread work. Slow LCP came from a hero image the HTML did not reference.
Do Shopify apps slow down your store?
Apps that run on the storefront do. Shopify's own guidance calls auditing and removing third-party scripts the highest-impact optimization for responsiveness. Admin-only apps add nothing to the page. On ColourPop's product page, 35 third-party entities cost 2.4 seconds of main-thread time in the lab run; one fraud-prevention script alone cost 1.1 seconds.
Does uninstalling a Shopify app remove its code?
Only partly. Shopify removes script tags and theme app extension blocks automatically when an app is uninstalled. Code an app wrote into your theme files stays. Shopify's Help Center says uninstalling an app does not automatically remove its code from your theme, and you may need the developer's removal instructions. Check theme.liquid and snippets after every uninstall.
What is happening to Shopify script tags?
Shopify is retiring them. Apps cannot create or update script tags after October 1, 2026, and Shopify stops injecting them into storefronts on March 1, 2027. Theme app extensions replaced them in 2021, and app embed blocks are the replacement developers are told to use. An app still relying on a script tag stops working that day.
Should I lazy load images on Shopify?
Below the fold, yes. Never on the hero or main product image. Shopify's performance docs call lazy-loading the LCP image one of the most common and damaging anti-patterns in themes, because it hides the image from the browser's preload scanner. Load that one image eagerly with fetchpriority set to high, and lazy load everything further down.
Does Shopify serve WebP images automatically?
Yes. Shopify's image_url filter documentation says the CDN detects which formats the visitor's browser supports, such as WebP and AVIF, and selects one for optimal quality and size. You will not see .webp in the URL. Your job is to request the right width through srcset, since the CDN never upscales an image beyond its original size.
Will a faster theme fix my Shopify speed?
Not if the apps stay. A theme swap changes the theme's own CSS, JavaScript and Liquid, but every app embed and tag manager script comes back on the new theme. The Theme Store's floor is only a 60 average Lighthouse performance score, so a listed theme is not automatically fast. Measure after the script audit, then decide.
Which Shopify pages should I speed up first?
The pages that earn clicks. A collection page ranking on page one for a commercial query is worth more than a homepage nobody searches for. Read Search Console clicks against each page's Core Web Vitals and start where both traffic and a failing metric meet. Speed fixes on pages with no traffic move nothing.
15+ years of growing SaaS websites through SEO | Author, 200-Point Audit Checklist
Aditi has spent 15+ years helping SaaS companies scale organic traffic through technical SEO and content strategy. She is the author of the CrawlRaven 200-Point Audit checklist used by agencies and in-house teams to systematically improve search performance.