The store was fast at launch. Then came a reviews app, a popup for email signups, a currency converter, a size chart, upsells, a chat widget and a few tracking pixels. Two years and twenty apps later, the product page pulls in dozens of scripts from more than a dozen domains, and nobody can say which app costs what.
Most advice about Shopify app speed impact stops at "uninstall apps you don't need." That's true, but it isn't an audit. This post walks through a repeatable third-party script audit: start with real-user data, list every external script, measure each app's cost without uninstalling anything, find code that removed apps left behind, and finish with a clear keep, replace or rebuild list.
Every script in this post was tested before publishing.
How Shopify Apps Actually Slow a Store
Apps reach your storefront in a few different ways, and each one affects speed differently:
- App embeds and app blocks. Modern apps use theme app extensions, which add scripts and styles through the theme editor. That's cleaner than editing theme code, but an app embed that's switched on usually loads on every page, whether the page needs it or not.
-
Code injected into the theme. Older apps edited
theme.liquid, added snippets or loaded scripts through the ScriptTag API. This code often stays behind after the app is uninstalled. - More third-party domains. Each new domain means another DNS lookup and secure connection before anything downloads. Twenty apps can easily mean fifteen extra domains.
-
Render-blocking resources. A synchronous script or stylesheet in the
<head>delays the first render, which pushes Largest Contentful Paint (LCP) back. - Main-thread work. Review widgets, personalization, popups and chat run JavaScript that competes with the shopper's taps and clicks, which hurts Interaction to Next Paint (INP).
- Late-loading widgets that push content down the page, causing Cumulative Layout Shift (CLS).
That's why app count alone is a poor measure. One heavy app can cost more than ten light ones. You need to measure.
Step 1: Start With Field Data, Not a Single Lab Score
Before opening DevTools, look at what real shoppers experience. Shopify's web performance dashboard in the admin shows the three Core Web Vitals, based on real user data from the past 30 days. Shopify reports the 75th percentile, notes that data can be delayed by up to 36 hours, and keeps 90 days of history.
Two habits make this dashboard far more useful:
- Keep an app change log. Write down the date you install, update or remove each app. When LCP or INP jumps, you can match the date to a change.
- Compare templates. Product pages usually carry the most apps, so check them separately from the homepage.
Then record a lab baseline in PageSpeed Insights for three URLs: the homepage, a collection page and a product page. If you're not sure what each section of the report means, this guide on how to read a PageSpeed Insights report explains lab vs field data and which numbers to act on.
Google's targets for a good experience are LCP of 2.5 seconds or less, INP of 200 milliseconds or less and CLS of 0.1 or less.
Step 2: Inventory Every Third-Party Script
Next, find out exactly what loads on your heaviest template.
A DevTools Console Snippet
Open a product page in an incognito window, so your own extensions don't interfere, then open DevTools, paste this into the Console and press Enter:
(() => {
const ownHosts = new Set([location.hostname, 'cdn.shopify.com']);
const rows = {};
for (const r of performance.getEntriesByType('resource')) {
const url = new URL(r.name);
let key = url.hostname;
// Theme app extension assets are served from Shopify's CDN under /extensions/
if (key === 'cdn.shopify.com' && url.pathname.startsWith('/extensions/')) {
key = 'app extension ' + url.pathname.split('/')[2].slice(0, 8);
} else if (ownHosts.has(key)) {
continue;
}
const row = (rows[key] ??= { source: key, requests: 0, scripts: 0, kb: 0 });
row.requests += 1;
if (r.initiatorType === 'script' || url.pathname.endsWith('.js')) row.scripts += 1;
row.kb += r.transferSize / 1024;
}
const table = Object.values(rows)
.map((row) => ({ ...row, kb: Math.round(row.kb) }))
.sort((a, b) => b.kb - a.kb || b.requests - a.requests);
console.table(table);
return table;
})();
It groups every resource by where it came from, skips your own domain and Shopify's theme assets, and labels theme app extension files separately, since Shopify serves those from its CDN under /extensions/. You get a table of sources ranked by size, with request and script counts.
One caveat: browsers report a transfer size of 0 for cross-origin files unless the server sends a Timing-Allow-Origin header. If a domain shows many requests but 0 KB, check its real size in the Network panel.
The Network Panel
The Network panel fills in the details. Filter to JS, sort by size and add the Initiator column. The initiator tells you which script requested each file, which is how you trace a chain of requests back to the app that started it. While you're there, note anything loaded in the <head> without async or defer, because those block rendering.
Match Domains to Apps
Now turn domains into app names. Clues include the app's name in the script URL, app proxy paths under /apps/, the extension labels from the snippet, and the list of app embeds in the theme editor under App embeds. Write the results in a simple table: domain, app, templates it runs on and what it does for the business.
Step 3: Measure Each App's Real Cost
The usual advice is to uninstall apps one at a time and retest. That's slow, risky on a live store and can lose settings or data. Instead, block each app's requests during a test and measure what changes.
Lighthouse With Blocked URL Patterns
Lighthouse can block requests matching a pattern, so you can measure your page as if an app weren't there. This script runs Lighthouse three times for a baseline, then three times with each domain blocked, and prints the median score for each:
#!/usr/bin/env bash
# Usage: ./app-cost.sh <url> <domain> [domain...]
# Median Lighthouse performance score with each app domain blocked.
URL="$1"; shift
CHROME_FLAGS="${CHROME_FLAGS:---headless=new}"
score() {
for i in 1 2 3; do
npx -y lighthouse "$URL" --only-categories=performance --output=json --quiet \
--chrome-flags="$CHROME_FLAGS" "$@" \
| jq '.categories.performance.score * 100 | round'
done | sort -n | sed -n 2p # median of three runs
}
base=$(score)
[ -z "$base" ] && { echo "Lighthouse failed, check Chrome is installed" >&2; exit 1; }
echo "domain,score_with_domain_blocked,points_gained"
echo "none (baseline),$base,0"
for domain in "$@"; do
blocked=$(score --blocked-url-patterns="*${domain}*")
echo "$domain,$blocked,$((blocked - base))"
done
Run it with your product URL and the domains from Step 2:
chmod +x app-cost.sh
./app-cost.sh https://your-store.com/products/example cdn.reviewapp.example widget.chatapp.example
The output is a small CSV. On a test page with one heavy, render-blocking third-party script, it looked like this:
domain,score_with_domain_blocked,points_gained
none (baseline),72,0
127.0.0.1:8802,100,28
The points_gained column is the cost of that app: how much your Lighthouse performance score improves when its requests are blocked. You need Node.js, jq and Chrome installed. If Chrome refuses to start in a container or CI job, set CHROME_FLAGS="--headless=new --no-sandbox".
Three runs and a median help, but lab scores still move between runs. Treat small differences of a few points as noise, and pay attention to large, consistent gaps.
DevTools Request Blocking
For quick checks without a script, use Chrome DevTools request blocking. Right-click a request in the Network panel, choose Block request domain, reload and run a Lighthouse report from the DevTools Lighthouse panel. It's manual, but good for confirming a suspicion.
Read the Results Against Shopify's Own Bar
Shopify gives you a useful benchmark. Its Built for Shopify performance requirements state that an app "must not reduce the storefront Lighthouse performance score by more than ten points." If blocking one app's requests raises your score by more than ten points, that app fails the standard Shopify sets for its own featured apps, and it's a clear candidate for action.
Step 4: Hunt Down Leftover App Code
Removing an app that uses theme app extensions also removes its app embeds and blocks. Older apps are a different story. If they edited your theme directly, their snippets, script tags and assets often stay behind after you uninstall, still loading on every page.
Pull a copy of your live theme with the Shopify CLI:
shopify theme pull --store your-store.myshopify.com --path ./theme-audit
cd theme-audit
Then search for traces of removed apps and list snippets that nothing uses any more:
# 1. Search for traces of a removed app. Replace "oldreviews" with the
# app's name, CDN domain or snippet prefix.
grep -rniE "oldreviews|cdn\.oldreviews\.io" layout sections snippets templates assets config 2>/dev/null
# 2. List snippet files that nothing renders or includes any more
for f in snippets/*.liquid; do
name=$(basename "$f" .liquid)
if ! grep -rqE "(render|include)[[:space:]]+['\"]${name}['\"]" layout sections snippets templates blocks 2>/dev/null; then
echo "unused snippet: $f"
fi
done
On a sample theme, the output looks like this:
layout/theme.liquid:1:<head>{% render "oldreviews-init" %}<script src="https://cdn.oldreviews.io/w.js"></script></head>
unused snippet: snippets/sizechart-app.liquid
The first line shows a removed reviews app still loading its script and rendering its snippet from the main layout. The second is a snippet that nothing references, which is usually safe to delete, although it doesn't affect speed while it sits unused.
Remove leftovers safely:
- Duplicate your live theme in the admin.
- Remove the leftover code in the duplicate only.
- Preview it, test key pages and run your Lighthouse script against the preview URL.
- Publish the duplicate once everything works.
Check the app developer's uninstall instructions too. Many vendors document exactly which files and lines to remove.
Step 5: Keep, Replace or Rebuild
With costs measured, sort each app into one of four buckets.
Keep
Apps that clearly earn money or save time and cost little in speed. Leave them alone, but keep them on your quarterly list.
Configure
Many expensive apps can be made cheaper without removing them:
- Turn off app embeds on templates that don't need them, if the app supports it.
- Load widgets below the fold only when they scroll into view.
- Load chat only after the shopper clicks a chat button, and show a lightweight placeholder until then.
- Reserve space for widgets with fixed heights, so they don't shift the layout when they appear.
Replace
Some apps duplicate features Shopify now includes, or have lighter alternatives. Check whether native features cover the job before paying in speed for an app.
Rebuild
Simple features like badges, size charts, announcement bars and basic upsell blocks are often easier to build directly into the theme with Liquid and a few lines of JavaScript. For more complex needs, a lean custom app built on theme app extensions loads only what your store actually uses. That's where custom Shopify app development pays off: you get the feature without a vendor's one-size-fits-all script.
Prevent App Bloat Next Time
- Test before installing. Install new apps on a duplicate theme first and run your Lighthouse script before and after.
- Prefer well-built apps. Apps with the Built for Shopify badge have to meet the ten-point storefront requirement, and apps using theme app extensions are easier to remove cleanly.
- Audit quarterly. Rerun the snippet and the script every three months, and after any big theme update.
- Keep an app inventory. List each app, its domains, the templates it runs on, what it costs and who on your team owns the decision.
Apps aren't the only cause of a slow store. Large images, heavy themes and fonts matter too, and this breakdown of other reasons a website is slow covers what to check next.
Frequently Asked Questions
Do Shopify apps slow down my store?
Many do, but not all equally. Apps that add scripts, styles or widgets to your storefront can delay loading, slow interactions and shift layouts. Apps that only work in the admin, like inventory or reporting tools, usually have no storefront impact. Measuring each app tells you which ones actually cost speed.
How many Shopify apps is too many?
There's no fixed number, because one heavy app can slow a store more than ten light ones. Instead of counting apps, measure each one's cost. Shopify's own Built for Shopify standard says an app shouldn't lower the storefront Lighthouse score by more than ten points, which is a useful benchmark.
Do uninstalled Shopify apps still slow down my store?
They can. Apps built with theme app extensions remove their embeds when uninstalled, but older apps that edited theme code directly may leave snippets, script tags or assets behind. Search your theme code for the app's name and domain, then remove leftovers on a duplicate theme first.
How do I find which app is slowing down my Shopify store?
List third-party scripts with your browser's DevTools, match each domain to an app, then measure each app's cost by blocking its requests during a Lighthouse test. Compare the score with and without each app. The apps with the biggest difference are your priorities.
Does Shopify store speed affect SEO and conversions?
Speed is part of the page experience Google considers, and Core Web Vitals are a common way to measure it. Speed also affects how shoppers behave, because slow product pages lose attention and sales. Faster stores generally see better engagement, though content, products and pricing still matter most.
Which types of Shopify apps are usually the slowest?
Apps that load large scripts on every page tend to cost the most. Page builders, review widgets, popups, live chat, personalization tools and some upsell apps are frequent culprits. The specific app and how it's configured matter more than the category, so always measure rather than assume.
Wrapping Up
A real Shopify app audit has five steps. Start with field data, inventory every third-party script, measure each app's cost by blocking it, clean up leftover code and decide what to keep, configure, replace or rebuild. Run it once and you'll know exactly where your speed goes. Run it every quarter and app bloat never builds up again.
If your audit shows a few apps doing simple jobs at a high speed cost, it may be time to rebuild app features as lightweight custom code.
Top comments (0)