help1
shopify app scriptsshopifypage speedapp embed block

ScriptTag vs App Embed Block vs App Block: A Shopify Speed Shootout

Shopify app scripts load globally by default. Here's how the three theme app extension mechanisms actually compare - and which one to push for.

help1 Team
ScriptTag vs App Embed Block vs App Block: A Shopify Speed Shootout

Quick Answer: ScriptTag and App Embed Block both load on every page; only App Block can be scoped to a specific template. If an app's UI doesn't need to follow the visitor across the whole store, push the vendor toward an App Block, and treat the App Embed toggle as your real lever for the chat widgets and trackers that won't migrate.

Open Chrome DevTools on your store's homepage. Switch to the Network tab, filter by JS, and hit reload. On a store with eight apps installed, you're going to see somewhere between thirty and eighty .js files requested before the page finishes painting. Sort by size. Most of them are coming from apps the homepage has no use for: a subscription tool's checkout helper loading next to a review widget's star renderer next to a chat launcher's poller. None of those pages need any of those scripts.

That's the surface symptom. The mechanism behind it has three different names and three different fixes, and they get conflated all the time. I'm going to lay them out side by side, because I keep telling merchants the same things in chat and I'd rather just point at this.

The three injection mechanisms

When merchants ask why an app loads where they didn't put it, they're running into one of these. The names are Shopify's, not mine.

MechanismPer-page scopeMerchant activationWhat it's used for
ScriptTag (legacy API)None - loads on every storefront pageAutomatic on app installOlder review apps, upsell tools, anything written before 2022
App Embed BlockNone - loads on every page when toggled onManual toggle in the theme editor, easy to missChat widgets, cookie banners, sticky bars, trackers
App BlockPer template or per section, set by the merchantManual placement on the page that needs itProduct page widgets, custom sections, inline content

The headline number is in the middle column. Two out of three of these are global. The third is the only one that respects "don't load on the blog."

The reason shopify app scripts feel like ambient noise on every page comes down to which of these three mechanisms the vendor chose. ScriptTag is the oldest. An app registers a URL, Shopify drops it into a Liquid object called content_for_header, and that object is required to appear in the <head> of every theme. Shopify's own developer docs warn against parsing or modifying it: "the contents are subject to change, which can change the behaviour of your code." For our purposes, every ScriptTag is a passenger on every page request. There is no "load on PDP only" flag.

App Embed Blocks are the modern replacement for floating UI: the chat bubble, the GDPR banner, the sticky add-to-cart. They live in Online Store > Themes > Customize > App Embeds, and the merchant sees one toggle per app. Toggle on, the app loads on every page. Toggle off, the app loads nowhere. There is no "load on these templates" option. None of the App Embed apps I've audited expose one.

App Blocks are the per-page kind. They behave like sections: the merchant adds the block to a specific template (a product page, a collection page, a custom landing page), and the block's script only loads on the templates where the block appears. This is the one that actually matches what merchants want when they say "I only need this on product pages."

If you scan your store and find an app that lives in two places at once - it has a section block you can drop in and an embed toggle in App Embeds - that's a hybrid. Some vendors split tracking from UI: the embed handles analytics globally, the block handles the visible widget per page. You can usually turn the embed off and keep the block, but you'll lose the analytics piece.

Per-page scope: who can actually be told no

This is the criterion that decides everything else. I rank the three:

  1. App Block. Yes. Native and reliable.
  2. App Embed Block. All-or-nothing. You can turn the whole embed off for the whole site, but you can't restrict it to product pages.
  3. ScriptTag. No. The only documented workaround is to capture content_for_header into a Liquid variable and chain remove filters to strip specific script URLs per template. It works in principle. In practice the URLs contain version hashes that change every time the vendor deploys, so your filter dies silently on the next app update. Shopify's Theme Check flags the modification as a warning. I tell merchants not to lean on this unless they're maintaining the theme themselves and have a habit of re-checking after updates.

So when you look at your store's Network tab and see twenty scripts that shouldn't be on the homepage, your realistic outcomes are: an App Block app you can move around to specific pages, an App Embed you can disable globally if you can live without it, and a ScriptTag app that you can either remove or replace with something newer.

If you're trying to weigh whether the speed gain from disabling an embed is worth losing whatever the app does, help1's chat is the kind of conversation we have constantly: the first fifteen minutes are free and that's usually enough to walk through your specific app list. We can also run our diagnostic app against your store first so we're both looking at the same script load before the chat starts.

Setup friction: the activation gap most merchants miss

There's a gotcha in the App Embed flow that bit me twice before I started watching for it. With ScriptTag, the app activates on install: you click Install, you grant scopes, the script appears on every page. No theme editor visit, no further action. With App Embed Block, the install isn't finished until the merchant visits the theme editor, finds the embed toggle, flips it on, and clicks Save. Most app onboarding flows hand the merchant a link to the right screen, but a non-trivial number bury it in an email or skip it entirely.

The consequence is a real and confusing failure mode: the app appears installed in the Apps list, the merchant sees it everywhere in admin, and the storefront is generating zero activity from it. I once spent forty minutes wondering why a merchant's loyalty widget wasn't firing for any session before I noticed the embed toggle was off. The app's own dashboard reported "active" because the OAuth handshake had completed. There is no signal anywhere in admin that the embed isn't actually running.

If you've migrated to an app version that uses an embed and your data has gone quiet, this is the first thing to check. Online Store, Themes, Customize, App Embeds. Find the relevant app. Toggle on, save, reload the storefront, watch the Network tab. If the script appears, you're fine. If it doesn't, the toggle didn't save, which sometimes happens on first try.

App Blocks have a similar but more obvious gap: the merchant has to actually add the block to the page. Vendors usually communicate this better, because the block is visible (or visibly absent) in the editor preview.

ScriptTag, for all its global-load sins, is the lowest-friction install. It just works. That's part of why it took ten years to deprecate, and part of why I'd bet on App Embed adoption out-running App Block adoption as older apps modernize.

Cost over a year: not the line on the invoice

The monthly cost of the apps is on the invoice. The cost I'm interested in is the cost of the speed penalty they impose, because that one doesn't show up anywhere a merchant sees by default.

The data point I keep going back to: across one developer's 2026 scrape of about 10,000 Shopify stores, average mobile PageSpeed sat around 54 out of 100, and stores with ten or more apps installed averaged about 39. The same scrape pinned rough per-app mobile drags around 11 to 12 points for Hotjar, 10 to 11 for Afterpay, 9 to 10 for Klaviyo, 9 for Shogun. Those numbers vary by theme and by which other apps are present. The shape is what matters: each app you add pays a real cost on the storefront, and most of that cost is being paid on pages that don't use the app.

I had a merchant in chat last month with seven apps and a 12-second mobile LCP on their product page. Their paid campaign showed about 5,000 impressions, 700 recorded page loads, and zero conversions. The Meta pixel looked fine on the side they could see. Shopify analytics looked like the store was dead. The actual problem was that ad-click visitors were bouncing before any analytics script fired - the LCP exceeded their patience window, and the "broken pixel" they were debugging was a slow homepage.

Shopify app scripts from analytics and chat vendors are designed to load early on purpose. A chat widget that defers until interaction is a chat widget that misses every visitor who bounces in three seconds. A Klaviyo script delayed by two seconds doesn't track the half of mobile bounces that happen inside two seconds. The product's value and its speed penalty are inseparable. That's why generic "just lazy-load it" advice from web performance posts breaks down on Shopify.

The takeaway from this column: any reduction in shopify app scripts that load on a given page is real money on the LCP side. But the apps you most want gone are usually the ones you can't safely defer. Which leaves removing them entirely, or restricting them to where they earn their keep.

What the August 2026 ScriptTag deprecation does and doesn't fix

I want to flag this one because the community framing of it is misleading. Shopify is sunsetting parts of the ScriptTag API. The headline date for non-Plus stores is August 26, 2026. A lot of merchants, and some Shopify support reps, treat this as a general storefront cleanup that will force apps to migrate to per-page extensions and improve speed.

It doesn't.

The deprecation applies specifically to ScriptTags on the Thank You page and the Order Status page, the post-purchase confirmation flow. ScriptTags injected on product pages, collection pages, the homepage, and the blog aren't affected. Shopify's developer documentation is explicit about this scope. Storefront ScriptTags continue without a published deadline. Apps that use ScriptTag only for storefront injection have no external pressure to migrate.

So if you're hoping the August 2026 date is going to do the speed audit for you, it isn't. Apps that get pushed off ScriptTag onto Embed will move from "global load via legacy API" to "global load via modern API." The performance posture is the same. The compliance posture is different. The only place you'll see a real change is whether tracking pixels still fire on your order confirmation page, which is a real issue for ad attribution but not the cleanup most merchants think they're getting.

If a vendor tells you their app is specifically migrating to App Block, that's a different conversation and a real win. Push for it.

The merchant lever you actually have

Of the three mechanisms, the App Embed toggle is the only one that gives a non-developer merchant immediate control. Open the theme editor, pop into App Embeds, and anything you don't need running on every page (including the About page and the blog) gets turned off and saved. Reload the storefront. Look at the Network tab. The scripts should be gone.

The common candidates I'd flip off first: chat widgets you're not actively staffing, GDPR consent apps in jurisdictions you don't sell to, exit-intent popups that fire identically on the cart and the blog, sticky bar apps you forgot were installed, A/B testing tools that aren't running an experiment right now.

A caveat: some embed apps include both a visible widget and a tracking layer. Turning the embed off kills both. If the tracking is the part you actually care about, ask the vendor whether they offer a tracking-only embed, or whether they expose the same data through the Customer Events pixel API instead - the API runs in a sandboxed worker and doesn't pay the main-thread cost an embed does.

For ScriptTag apps with no migration path, the call is uglier. You either accept the global load, replace the app with one that uses theme app extensions, or remove the feature. A small percentage of merchants have the Liquid skills to maintain the content_for_header filter workaround. Most don't, and shouldn't.

I have not benchmarked any of this on Shopify Plus stores past about a hundred thousand orders a month, so the embed activation gap I described may behave differently when there's a development team between the install and the merchant. The mechanism is identical; the failure mode probably just gets caught earlier in QA.

What I'd actually pick

If I'm advising a merchant on a new install, my order of preference is: an app that ships as an App Block first, an app that ships only as an App Embed Block second (with the assumption I'm going to turn the embed off on most non-purchase pages), and an app that still uses ScriptTag last. If two apps do the same job and one is App Block and the other is ScriptTag, the App Block one almost always wins on speed even if it costs a few dollars more.

If I'm advising on an existing store with a Network tab full of unknown .js files, the order I work through is: turn off embeds that aren't earning their keep, replace ScriptTag apps that have a modern equivalent in the App Store, then look at the App Block apps to see if any of them are placed on templates that don't need them. The first pass is usually the biggest LCP win, and most of the time it's a five-minute job to flip the toggles and check the result.

Shopify app scripts aren't going to get measurably better at the platform level until vendors stop reaching for App Embed by default and start shipping App Block versions of features that don't need to follow the visitor across the whole store. Until they do, the embed toggle in your theme editor is the cheapest performance lever in your admin.

Still stuck? Talk to an expert.

Our vetted Shopify experts can fix this issue for you in a live session. $39 per session. Your first 15 minutes are free.