Skip to main content

Theme Block Extensions

Theme blocks are Liquid-based UI components that merchants can add to their storefront themes. They appear in the theme editor alongside native blocks, allowing merchants to position and configure them visually.

How Theme Blocks Work

  1. Your app installs block files (.aqua template + .schema.json schema)
  2. Blocks appear in the merchant’s theme editor under “App Blocks”
  3. Merchants drag blocks into sections and configure settings
  4. LaunchMyStore renders your block using the Liquid template engine

Block File Structure

Each theme block requires two files:

Creating a Theme Block

1. Write the Liquid Template

Theme blocks use .aqua files with standard Liquid syntax:

2. Define the Schema

The schema controls what settings appear in the theme editor:

Top-level Schema Fields

The schema JSON accepts the following top-level keys:

Available Targets

The target field determines which page types your block can be added to:
You can target multiple page types by specifying an array: "target": ["product", "collection"]

Setting Types

Basic Inputs

Selection Inputs

Range & Toggle

Visual Pickers

Resource Pickers

Installing Theme Blocks

Blocks are deployed by the install pipeline when your app is installed on a store. POST /api/apps/install-extensions is a server-to-server endpoint gated by the platform’s internal API key (no CORS) — the backend calls it during install with inline block content; it is not called directly from a browser with a merchant access token. (The only browser-accepted variant is a fromCatalog: true catalog copy, which requires the merchant to own the target store.)

Per-app CSS/JS

There is no extension_asset_url filter. Apps ship CSS/JS in one of two ways:

1. Inline <style> / <script> in the .aqua template

For small, dynamic CSS that depends on block.settings.*, inline a <style> tag inside the template (as shown in the example above). This is the recommended approach for block-scoped styles.

2. Bundled assets (per-merchant disk copy)

Files in extensions.assets[] are downloaded and stored under extensions/{domainSlug}/{appHandle}/assets/. They’re publicly served at the same path, so reference them as absolute URLs:
__domainSlug is the merchant’s store identifier and is the same path segment the host uses when copying your bundled assets onto disk.

3. App embeds (page-wide scripts)

For scripts that should load on every page (analytics, chat widgets, review widgets that scan the page), use an app embed instead of a block. See App Embeds — embeds support scriptSrc, inlineHtml, and stylesheetUrl and are injected by the host into the rendered HTML.
Block manifests accept stylesheetUrl and scriptUrl fields, but the host does not currently inject them when the block renders. If your block needs external CSS/JS, declare it as an app embed (option 3) or inline it in the .aqua template (option 1).

Theme assets (different from extension assets)

For files inside the merchant’s theme (the theme’s assets/ folder), use the standard Liquid filters:
  • {{ 'foo.css' | asset_url }} — theme asset CDN URL
  • {{ 'foo.png' | asset_img_url }} — theme image asset
  • {{ 'foo.svg' | inline_asset_content }} — inline SVG content
  • {{ 'foo.pdf' | file_url }} — theme file CDN URL

Snippets

Create reusable components as snippets:
Then render the snippet from your block:

Accessing Data

Block Settings

Access settings via block.settings:

Global Objects

Standard Liquid theme global objects are available:

Metafields

Access your app’s metafields:

Best Practices

Avoid complex logic in Liquid. Pre-compute values in your backend and store them in metafields.
Use proper heading levels, ARIA labels, and semantic elements for accessibility.
Prefix class names with your app handle to avoid style conflicts with the theme.
Use defer or dynamic imports for JavaScript to avoid blocking page render.
Respect the merchant’s theme colors and fonts where possible. Use CSS custom properties.
Test your blocks with multiple themes to ensure compatibility with different layouts.
A complete example showing a featured products carousel: