All articles

shopify

Shopify theme app extensions, explained for merchants and developers

What Shopify theme app extensions actually are, how app embeds and app blocks work, and why they replaced script tags for every Online Store 2.0 theme.

The Pulsar team9 min read
Shopify theme editor sidebar showing an app embed toggle being enabled.

If you've installed a Shopify app in the last three years and noticed that it just worked — no copy-pasting a script tag into theme.liquid, no support ticket asking a developer to add an include — you have theme app extensions to thank. They're the boring infrastructure piece that quietly fixed most of what merchants used to hate about installing Shopify apps. This is a plain-English guide to what they are, the three surfaces they use, what they replaced, and why every serious app in 2026 ships one.

TL;DR

  • Theme app extensions (TAEs) are bundles of Liquid, CSS, and JS that an app ships into your theme without modifying theme files.
  • They come in three flavors: app embeds (global, like a tracking pixel), app blocks (slot into a section, like a reviews widget), and app sections (a whole new section type).
  • They replaced the old ScriptTag API and Asset API patterns that Shopify deprecated for Online Store 2.0 themes.
  • Merchants enable them with a toggle in the theme editor — no code, no copy-paste, and they survive theme updates.
  • Developers ship them through the Shopify CLI, versioned per app deploy. Pulsar is a working example of an app embed.
Shopify theme editor sidebar showing the App embeds panel with a Pulsar Inline toggle enabled.
The merchant-facing surface of a theme app extension: a single toggle in the theme editor's App embeds panel.

What a theme app extension actually is

A theme app extension is a directory inside your app's repo that contains Liquid templates, CSS, and JS. When the app is installed, Shopify makes those files available to the merchant's theme as if they were native theme assets — but they live on Shopify's CDN, not in the theme's file tree. The merchant never sees them in Edit code. They appear instead as togglable blocks in the Customize view of the theme editor.

Concretely: in the app's source, a TAE looks like this:

extensions/pulsar-inline/
extensions/
  pulsar-inline/
    blocks/
      pulsar.liquid          # the actual storefront code
    shopify.extension.toml   # metadata: type, name, target surfaces
    assets/                  # optional CSS/JS shipped alongside

When the developer runs shopify app deploy, Shopify uploads that directory and pins it to the current app version. The merchant's theme editor then exposes the block by name — in Pulsar's case, Pulsar Inline — and they enable it with a click.

Why Shopify introduced them (the 2022 reset)

Before Online Store 2.0 launched in mid-2021 and TAEs became the recommended pattern in 2022, apps that needed to run code on the storefront had two ugly options. Neither was good.

Option 1: the ScriptTag API

The app called the ScriptTag Admin API endpoint to inject a <script src="..."></script> tag into every page on the storefront. This worked, but it had real problems: every app added a render-blocking script, the merchant had no visibility into what was loading, the script lived on the app's servers (so an app outage = a broken storefront), and there was no UI for the merchant to turn it off short of uninstalling.

Option 2: editing theme.liquid directly

Apps would programmatically modify the theme's Liquid files via the Asset API — appending an include line to theme.liquid or to a section template. This was even worse: a theme update wiped the change, a different app's edit could clobber yours, and the merchant ended up with a theme.liquid full of mystery includes no one could explain.

The three surfaces

TAEs come in three shapes, picked based on where the app code needs to run. Every TAE you'll meet is one of these three.

1. App embeds

Global. Loaded on every page of the storefront. Used for things that aren't tied to one section — tracking pixels, chat widgets, A/B test scripts, theme-wide scanners. The merchant enables them from the theme editor's App embeds panel in the left sidebar.

Pulsar's pulsar-inline is an app embed: it scans every h1, h2, and p on the page for Pulsar syntax and rewrites the matches into styled spans. It needs to be global because the merchant might use Pulsar syntax in any section, so the scanner has to run everywhere.

2. App blocks

Slot into an existing section. The merchant opens a section (product info, image banner, custom liquid section, etc.), clicks Add block, and your app's block appears in the picker alongside the theme's native blocks. Used for product reviews widgets, size charts, trust badges, country selectors — anything that belongs inside a specific section.

3. App sections

A whole new section type. The merchant adds it like any other section. Used for full-width app-owned UI: subscription pickers that take over the product page, lookbook galleries, multi-step quizzes. Less common than embeds and blocks because most apps don't need that much real estate, but the cleanest option when they do.

Diagram showing the three theme app extension surfaces: app embed running globally, app block inside a section, app section as a standalone section.
The three surfaces. Pick the smallest one that does the job — embeds are easiest, sections are the most invasive.

TAE vs ScriptTag vs theme code edit

If you're still seeing apps in 2026 that ask you to paste code into your theme.liquid, this is what you're being asked to give up.

CapabilityTheme app extensionScriptTag APIManual theme code edit
Install effort for merchantOne toggleAutomatic but invisibleCopy-paste into theme.liquid
Survives theme updatesYesYesNo — wiped on update
Survives theme swapsYes (re-enable in new theme)YesNo — every swap requires re-paste
Editable from theme editorYesNoNo
Render-blocking riskAsync by defaultOften render-blockingWhatever you pasted
Sandboxed from theme codeYesNo (touches the DOM globally)No
Versioned per app releaseYesNo (live URL)No
Uninstall is cleanYesSometimes leaves orphansNo — code stays after uninstall
Status in 2026Current standardDeprecated for OS 2.0Avoid

What this looks like as a merchant

From the merchant side, the difference between installing a 2026 app and a 2019 app is night and day. Here's the modern flow:

  1. Install the app from the Shopify App Store. OAuth, redirected back to the admin.
  2. The app's onboarding tells you to open the theme editor and enable its embed or block.
  3. You open Online Store → Themes → Customize.
  4. In the left sidebar, click the App embeds icon (a puzzle piece). The app's embed is in the list with a toggle.
  5. Toggle it on. Hit Save. Reload your storefront. The app is live.

No code editor opened. No theme.liquid modified. If you swap themes, you re-enable the embed in the new theme and you're done — the app's code didn't live in the old theme, so swapping doesn't break it.

For a step-by-step walkthrough with screenshots, see how to install Pulsar step by step — the flow is identical for any modern app embed.

What this looks like as a developer

From the developer side, TAEs are a Shopify CLI workflow. You scaffold an extension, edit Liquid, and ship it with the rest of your app.

Scaffold

shopify app generate extension
# pick "Theme app extension"
# give it a handle, e.g. pulsar-inline

This creates an extensions/<handle>/ directory with a shopify.extension.toml, a blocks/ folder, and an assets/ folder. You write Liquid in blocks/. Each .liquid file in there becomes one app block or app embed, controlled by a {% schema %} tag at the bottom of the file.

Example: a minimal app embed schema

extensions/my-app/blocks/my-embed.liquid
<script>
  console.log("My app embed is live on", window.location.pathname);
</script>

{% schema %}
{
  "name": "My App Embed",
  "target": "head",
  "settings": [
    {
      "type": "checkbox",
      "id": "enabled",
      "label": "Enable my app",
      "default": true
    }
  ]
}
{% endschema %}

The target field is the part that makes this an embed: setting it to head, body, or section controls where it gets injected globally. Omit target and add a templates array instead and you get an app block that can be slotted into sections by the merchant.

Deploy

shopify app deploy

This pushes the extension up alongside your app config (scopes, webhooks, app proxy). Each deploy creates a new app version; merchants get the new TAE code the next time they reload the storefront, no theme republish required.

Terminal output from running shopify app deploy showing a theme app extension being uploaded.
`shopify app deploy` pushes the extension up alongside the app's config — a new app version pins this exact TAE code.

A real-world example: Pulsar Inline

Pulsar is the text-effects app this blog belongs to, and pulsar-inline is a textbook app embed. Here's the entire architecture in three sentences:

  • One Liquid fileextensions/pulsar-inline/blocks/pulsar.liquid — registers a global script that runs on every storefront page.
  • The script scans the DOM (default selectors: h1, h2, p) for a tiny custom syntax (@{red-blue}word@, $c{...}text$, etc.).
  • Matches get rewritten in-place into styled spans or custom elements (<pulsar-circle>, <pulsar-highlight>) that handle the SVG animations.

There is no theme code change. The merchant types Pulsar syntax into any rich text or heading field — product titles, section headlines, image banners — and it renders styled on the storefront. If they uninstall Pulsar, the embed goes away cleanly and their raw syntax just shows as plain text. No orphan scripts, no theme.liquid edits to undo. That's the whole pitch of TAEs in one example.

For a deeper look at the no-code editing flow this enables, see Shopify theme customization without code.

The Online Store 2.0 connection

Theme app extensions and Online Store 2.0 are not the same thing, but they're inseparable in practice. OS 2.0 (launched June 2021) was the architectural shift that made every theme template into a JSON file composed of sections and blocks. TAEs (made GA in early 2022) were the matching shift for apps — letting them participate in that section-and-blocks model as first-class citizens instead of bolt-on scripts.

If your theme is Dawn, Sense, Refresh, Crave, Studio, or any of Shopify's free themes from 2021 onward, you're on OS 2.0 and TAEs work everywhere. If you're on a paid theme from a third-party developer released in the last three years, same. If you're on a custom theme from 2018 that was never migrated, app embeds won't appear in your theme editor at all — that's the canary for needing a theme upgrade.

What TAEs don't fix

Worth being honest about the limits.

  • Performance is still on you as a dev. TAEs don't magically defer your script. If you ship a 200KB blocking JS file in your embed, the storefront pays for it.
  • Merchants still have to know to toggle the embed on. Plenty of apps install but stay invisible because the merchant never opened the theme editor. Good onboarding inside the admin UI is still required.
  • You can't reach across embeds. Each TAE is conceptually isolated. If two apps both want to wrap the same H1, the last-loaded one wins.
  • Schema constraints. Settings exposed to the theme editor have a fixed list of input types. Complex configuration still belongs in the embedded admin UI, not the theme editor.

FAQ

+How do I tell if an app is using a theme app extension or a script tag?
Open your theme editor → Customize → App embeds panel (puzzle-piece icon in the left sidebar). If the app appears there, it's a TAE. If it doesn't but the app is still doing stuff on your storefront, it's either using ScriptTag or — worse — it edited your theme files directly. Check theme.liquid for stray includes.
+Will a theme app extension survive when I switch themes?
The extension itself stays installed with the app — it doesn't live in the theme. But your enabled state is per-theme. After a swap, open the new theme's editor and re-toggle the embed on. Takes ten seconds.
+Why don't I see App embeds in my theme editor sidebar?
You're on an Online Store 1.0 theme. The App embeds panel only exists on OS 2.0 themes. Upgrade your theme (Dawn is the free reference) and the panel appears.
+Can a TAE slow down my storefront?
It can if the app ships heavy or blocking code, but the architecture makes it easier to avoid than ScriptTag ever was. TAEs default to defer/async loading, and merchants can disable any embed instantly from the theme editor without uninstalling the app.
+Do I need to be on a paid Shopify plan to use theme app extensions?
No. TAEs work on every Shopify plan, including the Starter plan, as long as your theme is Online Store 2.0.

Bottom line

Theme app extensions are the boring, correct way for apps to live inside your Shopify storefront. They replaced a decade of duct-tape patterns — injected script tags, programmatic theme edits, copy-pasted snippets — with a single toggle in the theme editor and a clean uninstall. If you're a merchant, look for App embeds support before installing anything new. If you're a developer, every new app you ship in 2026 should be TAE-first.

Pulsar is one example you can install in under two minutes to see the whole pattern end-to-end — install the app, toggle one embed, type some syntax into a headline, and watch a global script rewrite your storefront text without touching a single theme file.

About the author

The Pulsar team

Shopify text styling

Pulsar is the easiest way to stylize headlines in your Shopify store — colors, gradients, animated highlights and circles, no theme code required.

Install Pulsar — Free