A store I audited last spring had eleven apps showing as installed in the admin. The theme grep returned references to nineteen vendors. Eight of them had been uninstalled, some more than once. The product page was loading scripts from CDNs that belonged to apps the marketing team had no memory of trialing.
That gap is what this checklist closes. Check historical theme edits and separately configured integrations alongside Shopify's app lifecycle cleanup. An uninstall does not prove that every reference to a vendor has disappeared from the storefront.
The 6-category checklist
Run this in order. Pre-flight first, then the six categories. The whole pass takes me about forty-five minutes per app on a moderately clean theme, longer if the app has been installed and uninstalled multiple times.
Pre-flight (five minutes, before clicking Uninstall):
- Screenshot every active App embed in the theme customizer. The admin loses this list the moment the app is gone.
- Note the vendor's CDN domain. Inspect a PDP, find the scripts loading from the vendor, write the domain on a sticky note. You will grep for it later.
- Export anything the app owns: review content, customer notes, segment definitions, custom metafield values. Most vendors offer a CSV export inside their dashboard. After the uninstall, that dashboard is read-only or gone.
- List the vendor's metafield namespace. Admin → Settings → Custom data shows app-owned namespaces if the app declared them via the Metafields API.
The six categories:
- Scripts (hardcoded
<script>tags inlayout/theme.liquid, plus Web Pixels API entries) - Theme blocks and sections (app embed blocks, section overrides, block schema additions)
- Snippets and assets (
snippets/app-*.liquid, orphan JS, CSS, fonts inassets/) - Metafields (app-owned namespaces and the values still attached to products, customers, orders)
- Customer-account templates (
customer.json,customers/account.json, login overrides, portal links) - Webhooks and notifications (Admin → Notifications, subscription topics in the app's former scope)
Each category has its own grep pattern and its own removal step. Most apps touch three or four of the six. Reviews apps and loyalty apps touch all six.

Why each category matters
Scripts
The orphans here are the expensive ones. A hardcoded <script src="https://cdn.vendor-foo.com/widget.js"> in theme.liquid keeps loading on every page until you delete the line. Browser caches help repeat visitors, but every new visitor pays the round trip. I have measured 180kb of orphan vendor JavaScript on a single PDP that the operator had no idea was loading.
Review Customer events for separately configured custom pixels as well as installed app integrations. Determine who owns each entry and whether its event path is still required before changing it. A merchant configured pixel and an app managed integration can have different cleanup paths.
Theme blocks and sections
Check the app's theme blocks and embeds against the current installation state. Modern app extensions and historical handwritten Liquid have different lifecycles. The cleanup evidence is the resulting theme and network behavior.
Section overrides are messier. Some apps modify your existing sections by injecting their CSS class names or data attributes directly into the Liquid. A reviews app might add <div class="reviews-vendor-widget" data-product-id="..."> inside sections/main-product.liquid. The block keeps trying to mount, the JavaScript that animated it is gone, and you end up with empty wrappers shifting layout on first paint.
Snippets and assets
The app's snippet files are the easiest to find and the safest to delete once you confirm nothing references them. The trap is naming. Some vendors prefix every file with their brand (snippets/judge-me-widget.liquid). Others use generic names (snippets/reviews.liquid) that you might confuse with a snippet you wrote yourself. Read the file before deleting, every time.
Orphan JS in assets/ is harmless until something accidentally references it. Orphan CSS is also harmless, just dead weight. Fonts are the trap: some apps upload them with names like assets/Montserrat-Regular.woff2, and your own theme might be loading the exact same font from the exact same path. Confirm the file's MD5 matches what you expect before deleting.
Metafields
Inventory the vendor's metafield definitions and values before removing them. Record ownership, resource type, and the access settings. Confirm which data remains after uninstall rather than assuming every definition has the same lifecycle.
Trace any remaining metafield reads in the theme or an API consumer. Storefront API visibility depends on the definition's access settings. Save data you need to retain, then remove only the confirmed obsolete definition or values. The metafield schema migration playbook covers a deliberate change when live consumers still depend on those fields.
Customer-account templates
This is the category that surprises operators when I show it to them. Many subscription apps, loyalty apps, and review apps modify the customer account portal by editing templates/customers/account.json, templates/customers/account.liquid, or the newer customer.json templates. They add a section that links to their hosted portal, embeds an iframe, or injects a script that fetches the customer's loyalty balance.
When the app is uninstalled, the section is still there. It tries to mount, the underlying API is dead, and your customer sees a broken loyalty card or a redirect loop into a vendor portal that returns 404. I have seen customer-account pages that took eighteen seconds to render because three orphan iframes were waiting on dead endpoints.
Webhooks and notifications
Shopify deletes webhook subscriptions associated with the uninstalled app. Review merchant managed notification webhooks and independently configured integrations separately. Use the owner, endpoint, and configuration evidence to decide whether a remaining endpoint is obsolete. An API query under one app's credentials is not a complete inventory of every integration on the store.
The Shopify uninstall payload reference documents the automatic cleanup. Keep the vendor domain in the review so manually configured endpoints can be identified without treating all app subscriptions as persistent.
The grep-and-remove ritual
One pattern, run six times per app. I do this in a theme branch, never against the live theme.
# 1. Get the theme locally
shopify theme pull --store mystore.myshopify.com --theme [theme-id]
# 2. Define the vendor signature once
VENDOR="judgeme" # or whatever you grepped from the script tag
VENDOR_CDN="cdn.judge.me" # the domain you noted in pre-flight
# 3. Grep across the whole theme for both signals
rg -i "$VENDOR" .
rg -i "$VENDOR_CDN" .
# 4. For each category, narrow the search
rg -n "<script" layout/theme.liquid # category 1: scripts
rg -i "$VENDOR" sections/ blocks/ # category 2: blocks
ls snippets/ | grep -i "$VENDOR" # category 3: snippets
ls assets/ | grep -iE "$VENDOR|\.woff|\.woff2" # category 3: assets
rg -i "$VENDOR" templates/customers/ # category 5: customer
Categories 4 and 6 are not in the theme repo. Metafield definitions are in Admin → Settings → Custom data, or via the Admin GraphQL metafieldDefinitions query. Webhook subscriptions are in Admin → Notifications, plus the GraphQL webhookSubscriptions query for app-created subscriptions.
Confirm before deleting, every time. Run the inverse grep against your templates/, sections/, layout/, and snippets/ to make sure nothing live still references the file you are about to remove. The deletion itself is one line; the confirmation is what saves you from a broken cart on a Tuesday afternoon.
# Before deleting snippets/judge-me-widget.liquid:
rg -F "render 'judge-me-widget'" .
rg -F "include 'judge-me-widget'" .
# Both empty? Safe to delete.
Commit the cleanup as its own theme version with a descriptive message. If something breaks, you can roll back to the previous version in seconds. If the cleanup is mixed in with a feature commit, the rollback is painful.
Why uninstall-then-reinstall accumulates
Repeated installs can leave older handwritten theme changes behind. Inspect the actual files and references after each removal, because the residue depends on how that app version integrated with the theme.
I worked on a store where the same reviews app had been installed three times over twenty months. Different team members each tried it, decided it wasn't right, uninstalled it, then a year later someone else tried it again. The vendor had renamed their snippet between version 1 and version 2 of the app, and again between version 2 and version 3. The theme had three different snippets/<vendor>-widget.liquid files, two of them with broken Liquid syntax that referenced a Liquid object the vendor had since deprecated. None of them were live. All three were loading. The newest one rendered the widget. The two older ones each made a 404 fetch against the vendor's CDN on every PDP.
The compounding effect is worst on apps that change names, change hosting domains, or change snippet conventions between major versions. Reviews apps and subscriptions apps are the worst offenders because they tend to ship breaking changes. Tracking apps are usually cleaner because their footprint is just a script tag.
If you reinstall an app you previously uninstalled, run the cleanup audit before the reinstall. Do not skip this step. The reinstall will not reset what the previous uninstall left behind.

What happens if you skip the audit
Four flavors of cost, in roughly the order they hurt.
Page weight creep. Orphan scripts add up. I have seen 400kb of orphan JS on a PDP, accumulated over eighteen months of app churn. The operator's Core Web Vitals had been drifting for a year and nobody could explain why. The audit traced it to seven uninstalled apps still loading scripts. This is the same accumulation pattern I describe in the Shopify app page weight audit, where the cleanup pass usually finds more dead weight than the live weight from currently-installed apps.
Security surface. A script from an uninstalled vendor is a script from a vendor you no longer have a contract with. If their CDN gets compromised or their domain expires and is bought by an attacker, that attacker now executes arbitrary code on every page load on your store. The exposure is silent. You will not know until something happens.
Compliance drift. Consent management vendors apply consent flags to the apps you tell them about. Your active app list is what you tell them about. The orphans are off the consent radar. An EU visitor lands on a PDP, the orphan tracker fires before the consent banner resolves, and you are out of compliance without realizing it.
Analytics noise. Orphan tracking pixels still fire. They might be firing into a vendor account you no longer pay for, which means the data goes nowhere useful, or they might be double-counting events your active stack is already capturing. Either way, the data quality drops by an amount you cannot easily measure without doing the audit you have been avoiding.
Use the removal sequence for the per app steps. The Shopify app stack decisions hub explains where that cleanup fits in the broader app inventory.
This is one of the modules in the DTC Stack Audit that finds the most surprises. Operators expect to discuss their live apps. They are usually unprepared for the conversation about the apps they thought were gone.
“A script from an uninstalled vendor is a script from a vendor you no longer have a contract with. The exposure is silent until it isn't.
”
The removal sequence after the inventory
The six categories above tell you what to inspect. Removal order matters too, especially when the app still controls a customer portal or owns data you need to export.
Before uninstalling, capture the active App embeds, export the app's data, and record its CDN domains and customer URLs. Keep that evidence with the theme change. A vendor name alone can miss an older domain or a snippet that uses a generic filename.
Work through this sequence on a preview theme:
- Disable the app's embeds while you can still identify them in the editor.
- Find its Liquid snippets and trace every
renderorincludereference before removing a file. - Inspect section and block overrides for vendor classes and data attributes.
- Check JavaScript assets against the references that load them.
- Review CSS and font assets separately. A file another section uses stays until that dependency is replaced.
- Remove confirmed orphan script tags from
layout/theme.liquidand other layouts. - Review merchant managed notifications and integrations that point at the vendor.
- Test customer account links, including subscription management, with the replacement path in place.
The 180KB orphan script described earlier is the reason I check the network after the code search. In the earlier cleanup notes, two scripts belonged to vendors the store had already uninstalled. Finding a short installed app list did not reveal the remaining requests.
Shopify automatically removes webhook subscriptions associated with an uninstalled app. The remaining check concerns separately configured notifications and other integrations. Review the documented app uninstall cleanup before assuming an app subscription still exists.
Finish with a new network capture and a customer journey through product, cart, checkout, and account pages. Save the before and after captures so the removal has evidence beyond a successful theme upload.
Sources and specifics
- Pattern observed across mid-market DTC Shopify stores with 18+ months of app churn, audited 2024 through 2026.
- The 45-minute-per-app figure reflects a moderately clean theme; complex themes with long edit histories run longer.
- The 400kb orphan JavaScript figure is from a single PDP audit; typical residue is 80 to 250kb across two or three uninstalled apps.
- Metafield definitions persist via the Shopify Admin Metafields API; uninstall does not invoke the deletion endpoint for app-owned definitions.
- Webhook retry behavior documented in Shopify's Admin API reference: failed webhook deliveries retry for up to 48 hours before being abandoned.
- The removal sequence covers the per app steps. For page weight context, see the Shopify app page weight audit. The full audit is packaged in the DTC Stack Audit product.
