A dark online retailer's back office at night, with one amber snap-off cable tag lit on a coil of grey cables beside a steel toolbox

Shopify's own help centre says it plainly: "Some apps add code to your online store theme that isn't automatically removed when you uninstall the app." On a store that has been through two agencies and a dozen app trials, that one sentence explains a good part of what an audit turns up.

So when a merchant asks us to take on a store someone else built, we do not start with the feature list. We start with an audit of what the storefront is actually running and where each piece came from. It is useful even if the merchant decides not to work with us afterwards, and it usually changes what the first piece of paid work should be.

Three kinds of code, and why the split matters

Everything a Shopify storefront loads comes from one of three places, and each one gets removed differently.

Theme code. Liquid, JavaScript and CSS in the theme files: layouts, sections, snippets, assets. It belongs to whoever edits the theme, and it stays until someone deletes it.

App-injected code. Modern apps ship as theme app extensions: app blocks and app embeds whose assets live on Shopify's side, not in your theme files. Shopify's documentation is explicit that "when merchants uninstall apps, blocks associated with the apps are automatically and entirely removed from online store themes." Older apps did it differently. Some registered a script tag through the Admin API, which Shopify injects into every storefront page without touching the theme. Others, or their install guides, pasted snippets straight into theme.liquid.

Orphaned leftovers. This is what the help centre sentence is about. When an app is uninstalled it loses access to the store at once, so it cannot clean up after itself. A snippet it pasted into the theme keeps rendering, and if it still calls the app's servers, it keeps making requests that nobody is reading the responses to.

The split matters because the fix is different for each. Theme code gets reviewed. An app embed gets switched off in the theme editor. A leftover gets deleted, but only once you have proved it is a leftover.

Diagram of three sources of Shopify storefront code, theme code, app-injected code and orphaned leftovers, all feeding one storefront page

Step one: compare what the theme references with what the page loads

The first pass is two lists and a diff. The first list is what the theme files ask for: pull the live theme with Shopify CLI, commit it untouched, and collect every external script it references.

shopify theme pull --live --path ./live-theme --store your-store.myshopify.com
cd live-theme && git init && git add -A && git commit -m "Live theme as found"
grep -rhoE 'src="https?://[^"/]+' layout sections snippets templates \
  | sort | uniq -c | sort -rn

The second list is what a real page load actually fetches. On the live storefront, with the cookie banner accepted the way a customer would, the browser's Resource Timing API gives it to you in a few lines:

const hosts = performance.getEntriesByType("resource")
  .filter((e) => e.initiatorType === "script")
  .map((e) => new URL(e.name).host);
console.table(hosts.reduce((acc, h) => ({ ...acc, [h]: (acc[h] || 0) + 1 }), {}));

Run it on the home page, a collection, a product and the cart, because apps scope themselves differently. Every host in the second list but not the first came from outside the theme files: an app embed or a script tag. Every host in the first list with no installed app behind it is a candidate leftover. Theme Check (shopify theme check) is worth running on the same pull for a quick read on the Liquid quality you are inheriting.

Step two: tie every script to an app, a person or nobody

Now the lists get owners. For each host we want one of three answers: an installed app that uses it, a person on the merchant's team who asked for it (an analytics tag, a chat widget), or nobody.

The installed apps list in the admin is the starting point, and the App embeds panel in the theme editor shows which embeds are switched on. Snippets named after an app that no longer appears in the admin are the classic leftover, usually rendered from theme.liquid so they run on every page. Search the pulled theme for the app's name and its script host, and read the app developer's uninstall instructions where they exist, because the developer knows where their code went better than anyone.

While the apps list is open, check billing too. Shopify notes that uninstalling an app does not cancel charges an app bills outside Shopify, so a store can still be paying for something it removed a year ago.

Nothing should be deleted at this stage. Removal belongs on a duplicate theme, one leftover at a time, once every script has an answer.

Why the slow store is often carrying scripts nobody uses

App scripts rarely know which page they are needed on. A review widget that matters on product pages loads on the home page, the blog and the cart as well. Add three or four apps nobody uses any more, each with its own script and its own third-party requests, and the store is slower on every page for features that do not exist.

Shopify's web performance report is the honest place to see this, because it uses real visitor data for loading speed, interactivity and visual stability, split by desktop and mobile. It also marks events such as app installs and theme updates as numbered lines on the graph, so you can often line up the week the store got slower with the app that arrived that week. For server-side Liquid cost, shopify theme profile profiles the rendering of a given page.

This is also why we are sceptical of a speed app as the first fix. An app that optimises scripts is one more script. Removing four that do nothing is usually the larger and cheaper win.

Two deadlines that make the audit urgent now

Two Shopify changes turn leftover scripts from untidy into broken.

Script tags are being switched off. Shopify's developer changelog says that from 1 October 2026 the scriptTagCreate and scriptTagUpdate mutations return an error, and on 1 March 2027 Shopify will stop injecting script tags into storefronts at all. Any app on the store that still depends on a script tag has until then to move to an app embed, or to a web pixel if it only tracks analytics. The audit tells you which of your apps that is, so you can ask the vendor now instead of finding a missing feature in March.

The Order status page has already changed. Script tags stopped running on the Order status page on 28 August 2025 for Plus stores and on 26 August 2026 for every other plan. On an inherited store, the conversion tracking someone pasted into that page years ago may have gone quiet with no error anywhere. If the marketing team's purchase numbers dropped in late August, check this before you check the ad accounts.

Step three: put the theme in Git before anyone changes it

The last step is the one that makes every later change safe, and it comes before any cleanup. On an inherited store the theme has usually been edited directly in the admin code editor, by several people, with no record of who changed what. A bad deploy on a store like that is an archaeology exercise.

Shopify's GitHub integration fixes most of this. It connects a theme to a branch, pulls every commit on that branch into the theme, and commits changes made through the admin back to the branch, batching edits made within about ten seconds into one commit. Shopify's own version control guidance recommends connecting your main branch and publishing that theme, and using other branches for campaigns and temporary customisations.

The order matters. The live theme goes in exactly as found, ugly parts included, as the first commit. Cleanups follow as separate commits on a branch, reviewed and merged. Merchandisers keep using the theme editor as before, and their changes land in the repository as commits too, so nothing they do gets overwritten by a deploy. From then on, a bad change is one revert.

What the audit answers

By the end, every script the storefront loads has an answer to three questions: is it theme code, is it injected by an app, or is it left over from an app uninstalled long ago. Add to that the apps still on a script tag, with 1 March 2027 next to them, and any tracking that relied on the old Order status page, and you have the list the first round of work should come from.

We run that first audit at a fixed price, in one of two sizes. The standard audit looks at the site as a whole and needs no access. The larger one, which we call Max, needs access to the Shopify account and goes through everything: the theme pull, the apps list and the billing check described above, plus the integrations connected to the store. Either takes from 24 hours to two days of work. What you get is a list: the infrastructure and UI/UX problems we found, each marked critical, medium or low priority. If you came with a specific goal, it is instead the fixed set of fixes that stands between the store and that goal.

The theme ends up where our Shopify work always happens: in version control with review, in the merchant's own repository where possible, not edited directly in the admin. Building features on a theme nobody fully understands is how the next team inherits the same mess, which is why the audit comes first.

If you have inherited a store and would rather know what it is running before you change it, talk to us.


Shopify behaviour and dates checked against Shopify's help centre on uninstalling apps, theme app extensions UX guidance, the script tag deprecation changelog, the Order status page script tag timeline, the web performance reports and the GitHub integration for themes in September 2026. How we take over a store is described on our Shopify development page.

Shopify Commerce Development

Have a project like this on your desk?

Send us a few lines about where things stand. We will read it, tell you what we would look at first, and whether we are the right people for it.

Talk to us about your case