Transactional Email
In This Article
- Handlebars Basics and Terminology
- Helpers
- Deviations from Standard Handlebars
- Additions to Standard Handlebars
- Choosing Handlebars as the Merge Language for Your Emails
Transactional Email supports Handlebars for customized content in your emails. Use Handlebars regardless of whether you're using templates in Transactional Email. We'll cover the basics of Handlebars, helpers implemented specifically for Transactional Email, and some deviations from and additions to standard Handlebars.
Handlebars Basics
- A handlebars expression is
{{
, some contents, followed by}}
.
Handlebars templates are made up of data, paths, helpers, partials, and comments:
- Data: Your content—anything not in a handlebars expression.
- Paths: How you inject content into templates. For example,
{{my.thing}}
looks in the merge values provided and gets thething
key in themy
hash table.
Escaping: If you have {{thing}}
in your template that you want to be viewed as template data instead of a path, use \
to escape it. So \{{thing}}
will print "{{thing}}" into the template, and \\{{thing}}
will print \
to the template, and then render the path "thing".
- Helpers: Help you do more complex things rather than printing a value escaped or unescaped. Helpers can be inline, where they operate only on template paths, or block, where they themselves can have template data, nested paths, and
else
branches. Helpers are generally either one or the other, and all helpers must be registered and defined by Transactional Email.
Helpers
Using helpers
Inline helpers are used as:
{{helperName arg1 arg2 arg3}}
Block helpers are used as:
{{#helperName arg 1 arg2}}
other stuff
{{else}}
else block - helper specific if it's supported and how it works
{{/helperName}}
Inline helpers available in Transactional Email
HelperName | Function | Example |
---|---|---|
upper | uppercase the text provided | {{upper "your text"}} results in: YOUR TEXT |
lower | lowercase the text provided | {{lower "your text"}} results in: your text |
title | title-case the text provided | {{title "your text is neat"}} results in: Your Text is Neat |
url | urlencode the text provided | {{url "http://yourawesomeurl.com"}} results in: http%3A%2F%2Fyourawesomeurl.com |
date | print the current date with a given format, defaults to d/m/Y | {{date "Y-m-d"}} results in: 2015-03-10 |
striptags | strip any HTML tags from the given data | {{striptags "<p>your text</p>"}} results in: your text |
Transactional Email also offers another helper, {{unsub}}
to add an automatic unsubscribe link to your emails. Generally, you would add the unsub helper in handlebars as {{unsub "http://redirecturl.com"}}
where you pass the URL directly in the helper and the URL must be enclosed in double quotes. For example:
<a href='{{unsub "http://redirecturl.com"}}'>Unsubscribe</a>
You can also pass the redirect URL as a merge_var
:
<a href='{{unsub redirect_merge_var}}'>Unsubscribe</a>
with the merge var defined as:
"global_merge_vars": [
{
"name": "redirect_merge_var",
"content": "http://yourdomain.com"
}
]
Note: When using the {{unsub}}
helper inside of an anchor tag, be sure to use single quotes around for the href='{{unsub }}'
.
Block helpers available in Transactional Email
Below are all helpers included with and documented by Handlebars with detailed examples.
The if helper
When using the {{#if}}
helper in Handlebars, any expression whose value is not false
, undefined
, null
, ""
, 0
, or []
will evaluate as true.
In your template, you might have something like:
<div class="entry">
{{#if user_name}}
<p>Thanks for registering! Your username is {{user_name}}.</p>
{{/if}}
</div>
And in your API call, you'd provide:
"global_merge_vars": [
{
"name": "user_name",
"content": "Mandrill_User1"
}
]
For the following result:
<div class="entry">
<p>Thanks for registering! Your username is Mandrill_User1.</p>
</div>
The unless helper
The {{#unless}}
helper was inspired from Ruby's unless conditional operator, and it works in the same way. The content inside the block will be displayed when the expression is evaluated to false, or unless it's true. It's equivalent to if not
.
In your template, you might provide:
<div class="entry">
{{#unless user_name}}
<p>You haven't chosen a username. Please enter a username to register.</p>
{{/unless}}
</div>
And in your API request:
"global_merge_vars": [
{
"name": "user_name",
"content": ""
}
]
For the following result:
<div class="entry">
<p>You haven't chosen a username. Please enter a username to register.</p>
</div>
The each helper
The {{#each}}
helper iterates over each item in an array. The keyword this
can be used to reference the current element being iterated.
In your template:
<div class="entry">
<ul>
<li style="list-style: none">{{#each browsers}}</li>
<li>{{this}}</li>
<li style="list-style: none">{{/each}}</li>
</ul>
</div>
In your API request:
"global_merge_vars": [
{
"name": "browsers",
"content": [
"Chrome",
"Firefox",
"Explorer",
"Safari",
"Opera"
]
}
]
The final result:
<div class="entry">
<ul>
<li>Chrome</li>
<li>Firefox</li>
<li>Explorer</li>
<li>Safari</li>
<li>Opera</li>
</ul>
</div>
Note: Whenever an expression evaluates to an array, Handlebars will iterate over each item in the array automatically. So the same results that were just displayed could have been achieved with the following template:
<div class="entry">
<ul>
<li style="list-style: none">{{#browsers}}</li>
<li>{{this}}</li>
<li style="list-style: none">{{/browsers}}</li>
</ul>
</div>
The with helper
The {{#with}}
helper allows you to shift the context for a section of a template which can be extremely helpful when accessing nested values. It is equivalent to using dot notation.
In your template:
<div class="entry">
<h2>{{incident}}</h2>
<p>Impact: {{impact}}</p>
<p>Created At: {{created_at}}</p>
<p>Updates: {{#with updates}} {{body}} {{/with}}</p>
<p>Updated At: {{updated_at}}</p>
</div>
In your API request:
"global_merge_vars": [
{
"name": "incident",
"content": "Error in connection"
},
{
"name": "impact",
"content": "none"
},
{
"name": "updates",
"content": {
"id": "9e86a19c-9f9b-447d-b4a8-81f9e71efd85",
"incident_id": "5a99c8c5-e63f-43f0-b375-df0152211bd8",
"body": "Testing global variables",
"status": "update",
"created_at": "2015-02-27T16:01:55+0000",
"updated_at": "2015-02-27T16:01:55+0000"
}
},
{
"name": "created_at",
"content": "2015-02-27T15:27:23+0000"
},
{
"name": "updated_at",
"content": "2015-02-27T16:02:18+0000"
}
]
Final result:
<div class="entry">
<h2>Error in connection</h2>
<p>Impact: none</p>
<p>Created At: 2015-02-27T15:27:23+0000</p>
<p>Updates: Testing global variables</p>
<p>Updated At: 2015-02-27T16:02:18+0000</p>
</div>
This could also be accomplished by using dot notation as in this template:
<div class="entry">
<h2>{{incident}}</h2>
<p>Impact: {{impact}}</p>
<p>Created At: {{created_at}}</p>
<p>Updates: {{updates.body}}</p>
<p>Updated At: {{updated_at}}</p>
</div>
Deviations from Standard Handlebars
- Some helpers aren't currently supported, including
lookup
,log
,helperMissing
, orblockHelperMissing helpers
. If you see a need for one of these, please let us know the use-case so we can re-evaluate support. - Path names are case-insensitive, so
{{MYTHING}}
and{{mYThing}}
and{{mything}}
will all print the same thing. - Partials are currently unsupported in Transactional Email Handlebars.
- Transactional Email Handlebars templates can be rendered in a text context (used for headers and message text parts). In text mode, all values are unescaped and double vs triple-staches don't matter.
Additions to Standard Handlebars
- Instead of only using
{{else}}
to mark an else block for a block helper, use an arbitrary number of{{elseif cond}}
blocks. These blocks will only run if the{{else}}
block would have run, and only if their condition is matched. - We've added a very simple "expression" value that can be used as well as numbers, strings, booleans, and paths as argument values, so
{{#if i < 5}}
will evaluate if the "i" path is less than the number 5.
Additional examples
Comparison expressions
In Transactional Email Handlebars, it's possible to compare values using back ticks to surround the comparisons. These can be very helpful when using the if
block helper.
In your template:
<div>
{{#if `purchases > 3`}}
<ul>
{{#items}}
<li>{{this}}</li>
{{/items}}
</ul>
{{/if}}
</div>
In your API request:
"global_merge_vars": [
{
"name": "items",
"content": [
"Computer",
"Monitor",
"Keyboard",
"1-Year Insurance",
"Mouse Pad",
"Mouse"
]
},
{
"total_purchases": 6
}
]
The result:
<div>
<ul>
<li>Computer</li>
<li>Monitor</li>
<li>Keyboard</li>
<li>1-Year Insurance</li>
<li>Mouse Pad</li>
<li>Mouse</li>
</ul>
</div>
Strings can also be used for comparisons, however you'll have make sure to enclose the string in double quotes as single quotes won't work:
In your template:
{{#if `operating_system == "OS X"`}}
<p>Click here for instructions to install on a Mac</p>
{{elseif `operating_system == "Windows"`}}
<p>Click here for instructions to install on a PC</p>
{{/if}}
In your API request:
"global_merge_vars": [
{
"name": "operating_system",
"content": "Windows"
}
]
The result:
<p>Click here for instructions to install on a PC</p>
HTML escaping
Handlebars HTML-escapes values returned by an {{expression}}
. If you don't want Handlebars to escape a value, use the "triple-stash", "{{{.
In your template:
<div>
{{{html_tag_content}}}
</div>
In your API request:
"global_merge_vars": [
{
"name": "html_tag_content",
"content": "This example<br>is all about<br>the magical world of handlebars"
}
]
The result:
This example
is all about
the magical world of handlebars
Choosing Handlebars as the Merge Language for Your Emails
Transactional Email supports Handlebars or merge tags for adding dynamic content to your emails. You can set Handlebars as the default merge language globally for your account, or on a per-message basis via our API or SMTP Integration.
Global account setting
- Go to Settings in your Transactional Email account.
- Click Sending Defaults in the top menu.
- From the Merge Language drop-down menu, choose Handlebars.
The Transactional API
To set the merge language to Handlebars on a per-message basis using the Transactional API, set the value of merge_language
to handlebars
in your messages/send or messages/send-template request.
The Transactional Email SMTP Integration
If you're using the Transactional Email SMTP Integration, add the X-MC-MergeLanguage
custom header to your SMTP message with a value Handlebars
(case-insensitive).
Once you've included the X-MC-MergeLanguage
header, use the X-MC-MergeVars
header to define the merge data (regardless of whether you've chosen the Handlebars or Mailchimp merge language).
Each header should be a JSON-formatted object, with name/value pairs separated by commas. For example, to assign a global value for "var1" (the merge tag *|VAR1|*
or the Handlebars expression {{var1}}
), Transactional Email expects to receive:
X-MC-MergeVars: {"var1": "global value 1"}
To set a recipient-specific value, use the name _rcpt
with the recipient's email address as the value, with the mergevar and value pairs, like this:
X-MC-MergeVars: {"_rcpt": "emailadress@domain.com", "fname": "John", "lname":"Smith"}
Note
-
Combining Handlebars with either mc:edit regions or merge tags in a single message isn't supported. You should pick Handlebars or mc:edit regions plus merge tags.
-
If you're exporting templates from your Mailchimp account to Transactional Email and using Handlebars as your default merge language in Transactional Email, we'll convert merge tags to Handlebars for you automatically.
-
If you've set a default merge language for your account on the Sending Defaults page but provide a different option in your API request or custom
X-MC-MergeLanguage
SMTP header, that option will override your default setting for the account.