Most Shopify stores don't decide to have twenty-eight apps installed. It happens one small decision at a time over two or three years: a reviews app added before a launch, an upsell tool trialed during a sale and never turned off, a countdown-timer app installed for one promotion in 2024 that's still running today, a backend integration a developer set up and left when the contract ended. Nobody sits down and audits the list, because nothing about it feels urgent until Core Web Vitals start slipping or the monthly Shopify bill looks larger than it should. This post is a framework for doing that audit properly — what to inventory, how to measure the real cost per app, and how to remove one without leaving broken code behind.
How a store ends up with thirty apps nobody remembers installing
App bloat isn't really a technical problem in its origin — it's an organizational one. Apps get installed by whoever had a reason to install them at the time: a marketing hire testing a new pop-up tool, an agency setting up a subscription flow for a launch, a founder copying what a competitor's store was using. Each individual decision was reasonable. Nobody who installed a countdown-timer app for a two-week flash sale was being careless; they just never had a reason to come back and remove it once the sale ended.
The problem compounds because Shopify makes installing an app trivially easy and removing one deceptively hard. Installing takes one click and an OAuth approval. Removing one safely means knowing what that app touched — theme files, checkout, metafields, webhooks, customer data — and whether anything else in the store now depends on it. Most teams don't have that information sitting anywhere, so the path of least resistance is to leave the app running rather than risk breaking something nobody fully understands anymore.
By the two- or three-year mark, a typical growing D2C store has accumulated apps across reviews and UGC, upsell and cross-sell, loyalty and rewards, email/SMS capture beyond Klaviyo or Attentive, currency conversion, size charts, sticky add-to-cart bars, trust badges, countdown timers, page builders, and at least one or two apps nobody on the current team can explain. Some are pulling their weight. A meaningful share are dead weight that's still billing monthly and still shipping JavaScript to every visitor.
The four ways an app actually touches your storefront
Before you can audit apps meaningfully, you need to understand that "installed" doesn't mean one thing on Shopify — apps attach to a store through a few distinct mechanisms, and the mechanism determines both the performance cost and how safely you can remove it.
The modern, Shopify-recommended path is theme app extensions, which come in two flavors. App blocks are pieces of an app that a merchant drags into a specific theme section — a size chart inside the product page, a review widget inside a specific template. They only work on Online Store 2.0 themes and require deliberate merchant placement, which is actually a good thing: the app only loads where you put it. App embed blocks are the other flavor — theme-wide additions like a chat launcher, an analytics pixel, or a cart drawer that get toggled on or off from Theme Editor → App Embeds without any code being written into your theme files. Both are sandboxed and, critically, both are meant to disappear cleanly when the app is uninstalled, because the code lives with the app, not inside your theme.
Then there's the legacy path: script tags and direct Liquid injection. Older apps — and some still shipping today — register a script tag via the ScriptTag API that Shopify injects into every storefront page, or worse, an app's install process literally writes a snippet into theme.liquid or adds asset files during setup. Shopify has been actively pushing developers away from this pattern for exactly the reason that matters to you: script tags load on every page regardless of whether they're needed there, and code written directly into theme files doesn't automatically get cleaned up when the app is removed. This is the single biggest source of orphaned code we cover further down.
Checkout is its own category. Shopify has been sunsetting checkout.liquid, Additional Scripts, and checkout-page script tags in favor of Checkout Extensibility — UI extensions and web pixels that run in a more controlled, sandboxed environment. If you're still running a store with legacy checkout customizations, that migration isn't optional anymore; Shopify has been enforcing removal of legacy checkout scripts on a hard deadline.
Finally, a fair number of installed apps have no storefront footprint at all. Inventory sync tools, accounting integrations, ERP connectors, and fulfillment apps often work entirely through the Admin API and webhooks — they never load a single line of JavaScript on your storefront. These apps can be expensive and worth auditing on cost grounds, but they're not the ones slowing down your product pages, and it's important not to lump them in with the ones that are.
Step one: build a real inventory, not a guess
You cannot audit what you haven't listed, and "I think we have around fifteen apps" is not an inventory. Start in Shopify admin under Settings → Apps and Sales Channels, which gives you the full list of everything currently installed, including apps with zero recent activity. For each one, record who installed it, roughly when, what it's billed at, and what job it was originally installed to do. A surprising number of teams discover apps here they genuinely don't recognize — usually leftovers from an agency engagement or a developer who's no longer involved.
For each app, you then need to classify how it actually touches the store, using the four categories above. Theme Editor → App Embeds will show you every app embed block currently active, which is often a shorter and more revealing list than the full app roster, because it shows you what's actually injecting itself into every page load right now. Cross-reference that against your theme code directly: search your theme's Liquid files and the theme.liquid layout file for snippet includes, script tags, and comments referencing app names — this is tedious but it's the only way to catch legacy injections that predate app embeds.
The other half of the inventory is usage, not just presence. Most apps have their own dashboard showing usage over the last 30 or 90 days — orders influenced, emails sent, widgets rendered, upsells accepted. Pull that number for every app on your list. An app billing you $79/month that shows zero attributed orders or zero rendered impressions in the last quarter is a different conversation than one clearly driving revenue, and you won't know which is which until you've actually looked.
Step two: measure what each app is actually costing you in load time
Once you know what's installed, the next question is what it's costing you in Core Web Vitals — specifically Largest Contentful Paint (LCP) and Interaction to Next Paint (INP), the two metrics Google actually uses for page experience ranking today. The honest way to measure this is app-by-app, not store-wide, because a single aggregate Lighthouse score tells you the store is slow without telling you which app is responsible.
Start with Shopify's own Theme Inspector for Chrome, a DevTools extension that profiles Liquid render performance directly against your live theme and shows a flame graph of what's consuming server response time — useful for catching apps that inject slow Liquid snippets or heavy API calls into the render path, not just client-side JS. Pair it with the Network tab in Chrome DevTools on an actual product page: filter by JS and CSS, sort by size and by load time, and you'll see exactly which script each request belongs to by its source domain or filename. Most apps are honest about their origin in the request URL, so this is usually enough to name names.
For a more structured before/after comparison, disable one app embed at a time in Theme Editor and run Lighthouse (either in Chrome DevTools or via PageSpeed Insights) against the same product page before and after. This isolates the marginal cost of a single app instead of measuring the combined weight of everything at once — a review widget alone might cost you 400ms of blocking time and a chunk of your JS payload, and you won't see that clearly in an aggregate score. Do this for your five or six busiest, highest-traffic template types — home page, collection, product, cart — since apps often load different scripts depending on the page.
Do this for every app that has a storefront footprint, and you'll come away with a real number next to each one: kilobytes shipped, milliseconds of blocking time, whether it's render-blocking or deferred. That number is what makes the next step a decision instead of a guess.
Step three: the keep, replace, or cut decision
With an inventory, usage numbers, and a performance cost per app, you're now in a position to actually decide, and the decision comes down to four questions asked in order for each app.
First: is anyone using it? Usage data from step one answers this directly. An app with real usage — orders influenced, meaningful conversion lift, active customer engagement — clears the first bar regardless of its performance cost, because the revenue case is what performance budgets exist to serve in the first place.
Second: does it overlap with something else you're already running? This is more common than most merchants expect. A store running both a native Shopify feature and a third-party app for the same job — email capture through both Shopify Forms and a dedicated pop-up app, upsells through both Shopify's native "Search & Discovery" recommendations and a third-party upsell app — is often paying twice and shipping duplicate scripts for the same outcome. When two apps do overlapping jobs, keep the one with better usage data and cut the other, don't keep both out of caution.
Third: could this be done with a native Shopify feature instead of a paid app at all? Shopify has quietly absorbed a lot of what used to require third-party apps directly into the platform — native bundles, native subscriptions through Shopify Subscriptions APIs, basic back-in-stock notifications, native product recommendations, form building through Shopify Forms, and increasingly capable theme-level customization through Online Store 2.0 sections. If a $30–$150/month app is doing something a free native feature now covers reasonably well, that's a straightforward cut even before you weigh performance cost.
Fourth, and only after the first three: what's the actual cost-to-value ratio once you factor in its performance tax? An app with modest but real usage and a heavy load-time cost might be worth replacing with a lighter competitor rather than cutting outright — the goal of this framework isn't to minimize app count for its own sake, it's to make sure every app still installed is earning the page weight and the subscription fee it costs you.
Step four: removing an app without leaving wreckage behind
This is the step most merchants get wrong, and it's the reason app removal projects sometimes make a store worse instead of better. Uninstalling an app through Shopify admin reliably removes the app's access and stops its billing, but it does not reliably remove everything the app left behind in your theme — and whether it does depends entirely on which of the four injection mechanisms that app used.
Apps built on modern theme app extensions — app blocks and app embed blocks — are the clean case. Because their code lives with the app rather than inside your theme's own files, uninstalling the app removes the block and it simply stops rendering; there's no orphaned code to hunt down. This is one of the real, practical reasons Shopify pushed developers toward this architecture, and it's worth checking Theme Editor → App Embeds immediately after any uninstall to confirm the toggle is actually gone, not just grayed out.
Apps that used the legacy path are where the damage happens. An app that wrote a snippet file into your theme, inserted an include statement into theme.liquid, or added its own section during setup does not remove any of that when you click uninstall — Shopify has no way to know which lines in your theme code belong to a third-party app versus your own custom work. That code stays in your theme, often still calling out to the app's now-disconnected API, sometimes throwing console errors on every page load, sometimes silently doing nothing but still adding parse weight to your Liquid render.
The fix is a manual check every time you remove an app that had any storefront presence: search your theme's code (Online Store → Themes → Edit Code) for the app's name, its script domain, or any snippet file with a name that references it, and remove what's left. It's also worth checking your theme.liquid layout file specifically, since that's the most common place legacy apps inserted themselves, and checking Settings → Notifications and any custom email templates, since some apps injected tracking pixels or code there too, outside the theme entirely. Do this within the same session as the uninstall — a month later, nobody remembers which app that stray snippet belonged to.
What app spend should look like as a percentage of revenue
Merchants ask this constantly and there's no single official benchmark from Shopify, so treat what follows as a sanity-check range rather than a rule. For a store doing healthy, sustainable growth, total app subscription spend — across everything from a $9/month utility to a $500/month enterprise integration — tends to land somewhere in the range of 1–3% of monthly revenue for stores that are running a reasonably lean, well-chosen stack. Stores well outside that range in either direction are usually telling you something.
Meaningfully above that range and still growing is often fine — a store leaning hard on a genuinely revenue-driving subscription or loyalty platform, or one running heavy personalization, can rationally spend more if the attribution data backs it up. The problem case is a store above that range where the usage data from your audit shows several apps with weak or no attributable impact; that's spend that isn't buying anything and is also very likely costing you page speed on top of the subscription fee. Meaningfully below the range is its own signal worth investigating too — sometimes it means a lean, well-run stack, but sometimes it means a store is under-invested in tools that would pay for themselves, like abandoned cart recovery or proper reviews and social proof.
The number that matters more than the percentage itself is the trend. App spend that's crept up steadily over two or three years without anyone revisiting the list is the actual pattern to watch for, independent of what percentage of revenue it currently represents — that's the compounding cost this whole framework exists to interrupt.
When to DIY this and when to hire someone
Everything in this framework is genuinely doable by a merchant or an in-house team with some technical comfort — none of it requires special access Shopify doesn't already give you, and for a store with a dozen or fewer apps and a developer or technically capable operator on staff, running this audit yourself over a few focused days is entirely reasonable. The Theme Inspector, Lighthouse, and Theme Editor's app embed list are all free, built-in tools; the work is mostly patient, methodical checking rather than specialized expertise.
Where it makes more sense to bring in outside help is scale and risk together. A store with thirty-plus apps accumulated across multiple team changes, a theme nobody fully understands anymore because three different developers have touched it over the years, or a checkout still running legacy scripts against an approaching deprecation deadline is a different situation than a tidy ten-app store doing routine housekeeping. At that point the risk of removing the wrong thing — breaking a checkout flow, losing tracking data, taking down a feature customers actually rely on — usually outweighs the time saved doing it in-house, especially if nobody on the team has done a theme-code audit like this before.
This is also, plainly, the kind of work Carryup does for Shopify stores as part of ongoing technical care — auditing an app stack, measuring real performance cost per app, and cleaning up the orphaned code left behind by apps that were removed without anyone checking the theme afterward. If you're looking at a long-neglected app list and unsure where to start, that's a reasonable point to ask for a second set of eyes rather than guessing your way through a theme you don't fully trust. For a first pass you can run yourself, the free Shopify store audit fingerprints installed apps from a store URL alone and separately flags render-blocking scripts on the homepage — a useful starting inventory before step one, though it won't attribute each script to its app.
If any of this sounds like your situation, talk to us. We'll tell you exactly where your revenue is leaking and what it would take to fix it. Explore Strategy & Consulting →

