Email Template Extensions
Email template extensions let your app ship branded HTML for the transactional emails LaunchMyStore sends on the merchant’s behalf — order confirmations, shipment notifications, password resets, and more. The template is stored as part of the merchant’s store and is selected at send time by event name. This replaces the platform’s built-in default HTML for any event the app overrides. Merchants can also save their own templates through the admin UI, with app-provided templates winning on conflict.How Email Templates Work
- Your app sends a template manifest at install time (or any time after, via the app-scoped REST API).
- LaunchMyStore upserts a template record, keyed by
(store, event, app). - When the merchant’s store fires the corresponding event (e.g. an order is placed), the send pipeline selects the active template for that store and event using the resolution rules.
- The chosen
htmlBodyis rendered with the full Aqua (Liquid) engine (interpolation, loops, conditionals, filters) and sent through the merchant’s configured email provider — the platform’s shared sender by default, or the merchant’s own SMTP if one is set. Custom templates only apply when the merchant has configured their own SMTP, to protect the platform’s shared sender reputation.
Architecture
Two separate channels connect your app to LaunchMyStore — only one of them carries email templates.
The merchant never types HTML into a browser. Your server POSTs the
template directly. The iframe is optional UI for triggering that POST
(e.g. a “Re-sync templates” button).
Two ways the POST happens
At install — LaunchMyStore reads theemailTemplates array from your
install manifest and upserts each entry. No separate auth needed because
the merchant just authorized the install.
appId is read from the bearer token — apps can never write rows
under another app’s appId.
Storage
Each template is stored as one record, uniquely keyed by(store, event, app). That key is what makes
one merchant + N apps + N events safely concurrent:
email-templates/{event}.json, so you
can inspect exactly what was deployed:
The bundle copy is never read at send time — it exists for developer
inspection (“what did I actually deploy?”) and tooling (CLI pull/sync).
To change a template, re-POST through the API; editing the deployed file
has no effect.
End-to-end read path (at send time)
SMTP Reputation Gate
Even when a template override exists, it only fires if the merchant has configured their own SMTP. On the platform’s shared sender, the send falls back to the built-in default template. Why this gate exists. Imagine 1,000 stores install the same buggy app. Without the gate, every order email from those stores would go through the platform’s shared sender with malformed/spammy HTML — and spam filters would start marking the platform’s sender address as untrustworthy. Every store on the platform would lose deliverability. With the gate, a bad template only fires on stores that configured their own SMTP. Damage is scoped to that one merchant’smail.yourstore.com reputation — not the platform’s.
If an override exists but the gate blocks it, the send falls back to the
default template — the most common reason a registered template “isn’t
working” is that the merchant hasn’t configured their own SMTP yet.
Supported Events
Until an event is “wired,” registering a template for it is a no-op at
send time — the template is stored, but the send pipeline continues to
use the built-in default HTML. Track the changelog for events moving to
Wired status.
Template Variables
Templates are rendered with the full Liquid engine —{{ var.path }}
interpolation, {% for %} loops, {% if %} conditionals, {% assign %},
and built-in filters (upcase, date, truncate, plus, times,
money_without_currency, etc.) all work. Missing values render as
empty strings.
Both the subject and htmlBody fields are rendered with the same
engine and context.
Variables available for digital_delivery
Sent once per digital product on the order, so a customer who buys three
digital items receives three emails — each naming its own product.
Use
{{ delivery_html }} rather than building the delivery yourself.
It renders the correct component for the product type — download buttons with
filenames, a monospace licence-code box, a copyable access link, or service
notes — already styled to survive Outlook, which ignores CSS gradients and
flexbox. Style everything around it however you like; drop this in where the
delivery should appear.Variables available for order_confirmation
Order — top-level fields about the order:
Line items — each item in
order.line_items exposes:
Customer:
Shop:
Helpers:
Iterating line items
When a customer orders multiple products, loop overorder.line_items
to render one row each:
<tr> rows. Inside the loop you
also have access to the standard Liquid forloop object:
Useful built-in filters
Template Manifest
Each entry underextensions.emailTemplates is one event override.
Fields
Resolution Rules
For each(storeId, event), the active template is selected as follows:
enabled = falserows are skipped entirely.- App-provided rows win over merchant-set rows. Rationale: the merchant explicitly installed the app that ships the template, so the override is opt-in.
- Within the same app bucket, newest
createdAtwins. Developers can iterate on their template without manual deletion.
REST API
Two parallel controllers — pick the one that matches your auth context.Merchant-scoped (Bearer JWT)
Used by the admin UI when a merchant edits a template directly.storeId
is resolved from the JWT.
App-scoped (OAuth Bearer)
Used by your app after install. TheappId field is forced to the
authenticated app’s id — apps cannot impersonate each other.
Required scopes: read_email_templates, write_email_templates.
Upsert example
Installing at App Install
The recommended flow is to ship your templates inline with the rest of your extension files during install. Add anemailTemplates array to
the extensions payload of POST /api/apps/install-extensions:
Complete Example: Order Confirmation Template
A branded order confirmation that uses all of the MVP-supported variables.See Also
- App Listing — declaring scopes for email-template access.
- Aqua Filters — full reference of the Liquid filters available in both theme rendering and email templates.
- App Bridge Overview — the iframe channel for merchant-facing admin UI, separate from this REST-based template flow.
- Webhooks — programmatic alternative if you want to send email yourself instead of overriding the built-in template.