HTML templates support a small template language for repeating content: cart rows in an abandoned cart email, product recommendation grids, conditional sections. This reference covers all of it. Single-value personalization is covered separately in the merge tags reference.
Loop over cart items
In automation emails triggered by store events, line_items contains the products from the triggering cart or order:
{% for item in line_items %}
<img src="{{ item.image }}" width="90" alt="">
<p>{{ item.name }} × {{ item.quantity }}</p>
<p>{{ item.line_total }} {{currency}}</p>
{% endfor %}
Available fields on each item:
| Field | Value |
|---|---|
item.name | Product name |
item.quantity | Quantity |
item.price | Unit price |
item.line_total | Price × quantity |
item.url | Product page URL |
item.image | Product image URL |
item.currency | Currency code (from the event or your store settings) |
Missing product images, URLs and currencies are filled in from your synced product catalog automatically when possible.
Loop over your catalog
products contains recent in-stock products from your connected store, for recommendation sections:
{% for item in products limit:4 %}
<a href="{{ item.url }}">
<img src="{{ item.image }}" width="140" alt="">
<p>{{ item.name }}</p>
<p>{{ item.price }}</p>
</a>
{% endfor %}
limit:N caps how many products render. Without it, up to 8 products are used. Catalog items support the same fields as cart items, including item.currency with the product's store currency.
Conditional sections
Wrap content in {% if %} so a missing value does not leave a broken layout:
{% if item.image %}
<img src="{{ item.image }}" width="90" alt="">
{% endif %}
Conditions check whether the field has a value. They work on item fields inside loops and on merge tags outside them.
Where this works
- HTML editor templates and automation emails written as HTML
- Templates saved in Templates and picked on a Send Email step
The drag-and-drop block editor has its own product blocks and does not need this syntax.
Previews render with real products
Wherever a template is previewed (the Templates page, the preview dialog, the side panel in the automation builder, the campaign workspace), loops and tags are rendered with sample products from your connected store, so you see the real result instead of raw code. Without a connected store, neutral placeholder products are used.
Common mistakes
{% for item in line_items %}outside a store-triggered automation renders nothing - there is no cart in a newsletter- Typos in
{% endfor %}or{% endif %}leave raw syntax visible in the email; the preview will show this immediately - Use
item.inside loops:{{ name }}alone will not resolve to the product name