Email templates in the UniSignIn block editor are personalised with merge tags. A merge tag is a value, a condition or a loop between double braces, such as {{profile.first_name}}. Tags work in text blocks, button and image URLs, the subject line, the preheader, sub-templates, Raw HTML blocks and link parameters.
This page is the full reference. For the editor itself, see Email Templates.
<p>Hi {{profile.first_name}},</p>
<p>Your order {{order.number}} has {{order.items.size}} items.</p>
<img src="{{order.items[0].image}}" alt="{{order.items.first.name}}">
[0] for the first item of a list..size (or .length) gives the number of items in a list or characters in a text. .first and .last give the first and last item of a list.{{{article.body_html}}}.{{! a comment }} is left out of the email.Give a value a fallback with the default filter:
<p>Hi {{profile.first_name | default:"there"}},</p>
The fallback is used when the value is missing, empty or null. A value with a fallback is never reported as missing.
{{#if profile.plan == "pro"}}
<p>Thanks for being a Pro member.</p>
{{else if profile.plan == "trial"}}
<p>Your trial ends soon.</p>
{{else}}
<p>Upgrade to Pro today.</p>
{{/if}}
{{#unless profile.email_verified}}
<p>Please verify your email address.</p>
{{/unless}}
| Operator | Meaning |
|---|---|
== and != | Equal and not equal. "5" equals 5. |
>, >=, < and <= | Compare numbers, or text alphabetically. A missing value counts as 0 against a number. |
contains | Text contains a word, ignoring case, or a list contains an item. |
and or && | Both are true. |
or or || | Either is true. |
not | The opposite, e.g. not profile.vip. |
A value on its own is true unless it is missing, empty, 0, false or an empty list, e.g. {{#if order.discount}}. Compare with text in quotes, numbers, true, false or null.
The same conditions work in a block's Show this block when setting, without the braces: profile.plan == "pro" and profile.country != "US".
{{#each order.items}}
<p>{{@number}}. {{name}}: {{qty}} × {{price | currency:"GBP"}}</p>
{{else}}
<p>Your basket is empty.</p>
{{/each}}
{{name}}. Use {{this}} for the item itself, such as a list of words. Fields outside the item, such as {{profile.first_name}}, still work.as, e.g. {{#each content_lists.top_stories as story}}…{{story.title}}…{{/each}}.limit, e.g. {{#each order.items limit 3}}. Use both as {{#each list as item limit 3}}.{{else}} is shown when the list is empty or missing.{{@key}} gives the key.| Variable | Value |
|---|---|
@index | Position from 0. |
@number | Position from 1. |
@first | True for the first item. |
@last | True for the last item. |
@key | The key when looping over an object, otherwise the position. |
{{#with}} reads several fields of one object without repeating its name. {{else}} is shown when the object is missing or empty.
{{#with order.shipping}}
<p>{{name}}<br>{{street}}<br>{{city}}</p>
{{else}}
<p>Collect in store.</p>
{{/with}}
A sub-template is a named piece of HTML, set up in the editor. Include it with {{>:
{{#each order.items}}
{{> line_item}}
{{/each}}
{{> article_card content_lists.top_stories.first}}
{{> name}} renders the sub-template with the current data, e.g. the current item of a loop.{{> name path}} renders it with the value at path._ and -, starting with a letter.The Data list block writes the loop for you. In sub-templates and Raw HTML blocks, {{theme.accent}}, {{theme.on_accent}}, {{theme.text}}, {{theme.muted}}, {{theme.line}}, {{theme.tint}}, {{theme.card}}, {{theme.page}}, {{theme.font}} and {{theme.radius}} insert the email's design settings.
A filter changes a value. Add it after a |, with arguments after a :, separated by commas. Filters can be chained and run from left to right:
{{profile.city | default:"your area" | upper}}
{{price | times:qty | currency:"EUR"}}
Arguments are text in quotes, numbers, or other values such as qty.
| Filter | Example | Result |
|---|---|---|
default | {{profile.first_name | default:"there"}} | there when empty |
upper | {{"news" | upper}} | NEWS |
lower | {{"NEWS" | lower}} | news |
capitalize | {{"hello world" | capitalize}} | Hello world |
title | {{"hello world" | title}} | Hello World |
truncate | {{description | truncate:60}} | Cut to 60 characters, ending in …. Default 80. |
replace | {{"a-b-c" | replace:"-"," "}} | a b c |
urlencode | {{"a b&c" | urlencode}} | a%20b%26c, for use in a URL |
json | {{order | json}} | The value as JSON |
| Filter | Example | Result |
|---|---|---|
number | {{1234.567 | number}} | 1,234.57. Up to 2 decimals by default. |
number | {{1234.5 | number:2}} | 1,234.50 |
currency | {{37.5 | currency:"GBP"}} | £37.50. Default USD. |
round | {{3.14159 | round:2}} | 3.14. Default 0 decimals. |
percent | {{0.256 | percent:1}} | 25.6%. Default 0 decimals. |
plus | {{10 | plus:5}} | 15 |
minus | {{10 | minus:5}} | 5 |
times | {{12.5 | times:2}} | 25 |
divided_by | {{10 | divided_by:4}} | 2.5. Dividing by 0 gives 0. |
Currencies use the English format, e.g. €1,234.50, ¥1,235 or CHF 70.20.
| Filter | Example | Result |
|---|---|---|
size | {{order.items | size}} | Number of items, or characters in a text |
first | {{tags | first}} | The first item |
last | {{tags | last}} | The last item |
join | {{tags | join:" / "}} | news / sport. Default , . |
plural | {{count}} {{count | plural:"item","items"}} | 1 item, 3 items. Without the second word, s is added. |
| Filter | Example | Result |
|---|---|---|
date | {{published_at | date:"MMM D, YYYY"}} | Oct 8, 2026. This is also the default. |
date | {{published_at | date:"dddd D MMMM [at] HH:mm"}} | Thursday 8 October at 09:30 |
Dates are read from ISO text such as 2026-10-08T09:30:00Z, or a Unix timestamp in seconds or milliseconds, and shown in UTC. Include Z or an offset in your dates.
| Token | Output |
|---|---|
YYYY, YY | 2026, 26 |
MMMM, MMM, MM, M | October, Oct, 10, 10 |
DD, D | 08, 8 |
dddd, ddd | Thursday, Thu |
HH, H | 24-hour clock, 09, 9 |
hh, h | 12-hour clock, 09, 9 |
mm, ss | Minutes and seconds |
A, a | AM or PM, am or pm |
[text] | The text as written |
| Filter | Example | Result |
|---|---|---|
mix | {{brand.color | mix:"#FFFFFF",0.9}} | A light tint of the brand colour. 0 keeps the first colour, 1 gives the second. Default 0.5. |
Which values a tag can read depends on the email.
| Data | Example | What it holds |
|---|---|---|
profile | {{profile.first_name}} | The recipient's profile attributes, read when the email is sent. The field picker lists your attributes. |
content_lists | {{#each content_lists.top_stories}} | Your content lists, read when the email is sent. Each item has title, url, image, description, author, category and published_at. |
links.unsubscribe | <a href="{{links.unsubscribe}}"> | Unsubscribes the recipient in one click, after a confirmation page. In test emails and system emails, it opens the email preferences page. |
links.preferences | <a href="{{links.preferences}}"> | The recipient's email preferences page. |
campaign | {{campaign.name}} | The campaign sending the email: id, name and run_date, the date of the send, e.g. 2026-10-12. Empty in emails not sent by a campaign, so add a fallback such as {{campaign.name | default:"email"}}. |
Tags also work in link parameters, e.g. utm_campaign set to {{campaign.name | default:"email"}} once in Email Settings tags every campaign's links with its own name.
Other keys are read from the root, e.g. {{order.number}}. In the editor, they come from the sample data under Event payload (JSON), used for the preview and test sends. Don't use a top-level key called profile in sample data; profile attributes replace it.
System emails use the same syntax in the block editor. Their data is listed in the field picker, and fields marked as required must be in the email.
| Data | Example | What it holds |
|---|---|---|
user | {{user.first_name}} | The reader's email, first_name, last_name, full_name and display_name. |
app | {{app.display_name}} | The project, e.g. display_name, domain, logo, privacyUrl and tosUrl. |
brand | {{brand.color}} | The project's email branding: color, button_text, background, logo, footer_text and footer_links. |
signin | {{signin.temp_password}} | Sign-in values, such as the passcode, the reset or verification link and subscription_manage_url. |
subscription | {{subscription.renew_at}} | The plan in subscription and renewal emails. |
invoice | {{#each invoice.items}} | The order, items and totals in the Invoice email. |
countdown | {{countdown.header}} | The event in the Countdown Reminder email. |
A newsletter row with a fallback, a condition, a loop and filters:
<p>Hi {{profile.first_name | default:"there"}},</p>
{{#if content_lists.top_stories.size > 0}}
<h2>Top stories</h2>
{{#each content_lists.top_stories as story limit 5}}
<p>
<a href="{{story.url}}">{{story.title}}</a><br>
{{story.description | truncate:120}} · {{story.published_at | date:"MMM D"}}
</p>
{{/each}}
{{else}}
<p>No new stories this week.</p>
{{/if}}
<p><a href="{{links.preferences}}">Email preferences</a></p>
Identity, consent, audience, and subscription insights for publishers. A few emails a month, no spam.