Skip to content
Docs

Reference

Temple fills variables, defaults and conditionals into email subjects, HTML and text at send time. Syntax, truthiness, escaping and where Temple runs.

Updated Oct 1, 2026

Temple is Emailit’s small template language for subject lines, HTML and plain text. It isn’t Liquid or Handlebars: it supports variables, nested paths, default values and if/else blocks, and nothing else. Templates store placeholders as you write them, and Temple fills them in when an email is sent through the API or an automation.

Syntax at a glance

Text
{{first_name}}                      Variable
{{user.name}}   {{items.0.sku}}     Nested property and list item
{{first_name|"there"}}              Default when the value is missing or null
{{#if plan}} … {{else}} … {{/if}}   Conditional, with an optional else

Temple has no loops, filters, helpers, partials or custom functions. The only operator is the | default.

Variables

Text
Hello {{first_name}}
  • Temple replaces {{first_name}} with the first_name value you provide. Spaces inside the braces are ignored, so {{ first_name }} works too.
  • Names are case-sensitive: {{First_Name}} doesn’t match first_name.
  • A missing or null value becomes an empty string. Unknown placeholders disappear instead of showing up in the email.
  • Values are converted to text. Numbers and booleans appear as written (42, true), and lists are joined with commas (["a","b"] becomes a,b). An object renders as [object Object], so point at one of its fields instead.

Nested properties and list items

Use dots to reach into objects, and numbers for list positions, starting at 0:

Text
{{user.name}}
{{order.items.0.sku}}
JSON
{
  "user": { "name": "Ada" },
  "order": { "items": [{ "sku": "A1" }, { "sku": "B7" }] }
}

Because the dot separates path segments, a key that itself contains a dot can’t be reached. Use keys without dots.

Default values

Add | and a fallback to use when the value is missing or null:

Text
Hi {{first_name|"there"}},
Your company: {{company|'Not set'}}

Double quotes, single quotes or no quotes all work. The default isn’t used for an empty string, 0 or false; those render as empty, 0 and false. A default can’t contain the } character.

Conditionals

Text
{{#if plan}}
Thanks for being on the {{plan}} plan.
{{else}}
You're on the free plan. Upgrade anytime from your dashboard.
{{/if}}
  • {{else}} is optional.
  • A condition is false when the value is missing, null, false, 0, an empty string "" or an empty list []. Anything else is true, including the string "0", the string "false" and an empty object.
  • A condition is a single variable path, such as plan or user.is_admin. There’s no ==, and, or, not or unless. To branch on a value, compute a boolean in your code and pass it, for example "is_pro": true.
  • Write {{else}} and {{/if}} exactly as shown, with no spaces inside the braces.
  • Temple processes conditionals first, then variables.

Escaping and special characters

Values aren’t HTML-escaped. Temple inserts values exactly as you pass them. A value such as Tom & Jerry or <b>Ada</b> goes into the HTML unchanged, so escape any user-supplied text in your code before you pass it. The same variables fill the subject, HTML and text, so an escaped value such as Tom &amp; Jerry also appears that way in the subject and text. If that matters, pass a separate, escaped variable for the HTML.

This also means you can pass ready-made HTML, such as a table of order lines that your code renders, as a single variable.

There’s no escape syntax for double braces. Temple treats anything between {{ and }} as a placeholder and removes it if there’s no value. Single braces, such as those in CSS, are unaffected. Values are inserted once and not parsed again, so to show literal double braces, put them in a variable:

JSON
{
  "html": "<p>Write {{example}} in your template to show the first name.</p>",
  "variables": { "example": "{{first_name}}" }
}

Where Temple runs

Where Temple runs? What you can use
Email API with a template Always The variables you pass
Email API with inline subject, html or text When variables has at least one key The variables you pass
Automations, Send email step On every send Contact fields, contact, payload and meta. See Automation emails.
Campaigns and campaign test sends No A fixed set of campaign merge tags. See Campaigns.
SMTP relay No Nothing. The message is sent as you built it.
Dashboard editors and previews No Editors insert placeholders, and previews show them unrendered.

API emails

Pass a template alias or tem_ ID, and a variables object. Fields you send in the request (subject, html, text) replace the template’s, then Temple renders the subject, HTML and text.

JSON
{
  "from": "Acme <hello@acme.com>",
  "to": "ada@example.com",
  "template": "welcome-email",
  "variables": {
    "first_name": "Ada",
    "plan": "Pro",
    "activation_url": "https://acme.com/activate?token=8f3k2",
    "cf": { "company": "Analytical Engines Ltd" }
  }
}

The dashboard editors insert {{cf.<key>}} for contact custom fields. In API sends, nothing is looked up from your contacts, so provide those values yourself under cf, as in the example. The same goes for {{unsubscribe_url}}: pass your own unsubscribe link if the template uses it.

You can also send inline content with variables and no template. See Send an email.

Automation emails

On every send, the Send email step renders the subject, HTML and text with Temple, whether they come from the template or from overrides on the step.

Contact automations put the contact’s fields at the top level, so these work:

  • {{email}}, {{first_name}} and {{last_name}}
  • {{custom_fields.<key>}} for custom fields, for example {{custom_fields.plan}}. The campaign form {{cf.plan}} doesn’t work here.
  • {{contact.*}}, the same contact as an object, for example {{contact.first_name}}

All automations also get {{payload.*}}, the data of the event that triggered the run, and {{meta.*}}, the run’s metadata. Email and event automations don’t have a contact at the top level, so use {{payload.*}} or set the recipient and subject on the step.

{{unsubscribe_url}} isn’t filled in automation emails.

Campaigns

Campaigns and campaign test sends don’t use Temple. They replace only these merge tags with the recipient’s details:

  • {{first_name}}, {{last_name}} and {{email}}
  • {{unsubscribe_url}}, the recipient’s unsubscribe link
  • {{cf.<key>}}, a contact custom field, for example {{cf.plan}}

Write them without spaces inside the braces. The tag names aren’t case-sensitive, but custom field keys must match exactly. Defaults (|) and {{#if}} blocks aren’t processed, and any other {{…}} text stays in the email as written. See Campaign merge tags.

SMTP

The SMTP relay accepts a finished message. There’s no template lookup and no Temple pass, so build the final HTML before you send, or use the API or an automation if you need variables.

Check templates before you publish

Emailit doesn’t reject a template or a send because of broken Temple syntax. Mistakes usually show up as missing text or leftover braces in the delivered email. Before you publish:

  • Check that every {{#if …}} has a matching {{/if}}, and every {{ has a closing }}.
  • Send the draft version to yourself by its tem_ ID with realistic variables, including missing and empty values, to see both sides of each condition. See Template versions.

Examples

A greeting with a fallback:

Text
Hi {{first_name|"there"}},

A block that depends on the plan:

Text
{{#if plan}}
Your plan: {{plan}}
{{else}}
Upgrade anytime from your dashboard.
{{/if}}

A subject with a nested value:

Text
Order {{order.number}} has shipped, {{user.first_name|"friend"}}

Was this page helpful?

Thanks for the feedback.

Thanks, we read every message.