To use dynamic content to personalize the messages you send with Iterable, use Handlebars. With Handlebars, you can display, format, reference and reason about user profile fields and event data in message templates.
In this article
-
Getting started with Handlebars
- Definition: merge parameter
- Sample user profile data
- Sample event data
- Using Handlebars in HTML source
- Referencing user profile and event fields with Handlebars
- Fields containing spaces or a period, or starting with a number
- Fields containing HTML
- Handlebars helpers and block helpers
- Helpers
- Block helpers
-
Working with strings
- Regular expression matching (#ifMatchesRegexStr)
- Contains a substring (#ifContainsStr)
- Checking equality and alphabetical order (#ifEq, #eq, #lt, #lte, #gt, #gte)
- String length (length)
- Capitalize first letter of a string (capitalizeFirst)
- Capitalize first letter of each word in a string (capitalize)
- Capitalize entire string (upper)
- Lowercase entire string (lower)
- Display default value if no value exists for a parameter (defaultIfEmpty)
- Render HTML contained within a field
- Remove all instances of a specified string (cut)
- Replace all instances of a string (replace)
- Get substring by index (substring)
- Abbreviate string to a specified length (abbreviate)
-
Convert to lowercase, remove numbers and special characters, and convert spaces to hyphens (slugify)
- Replace newlines (#breaklines)
- URL encoding (#urlEncode)
- Write the provided argument as a JSON string (toJson)
- Write the provided argument as a URL encoded JSON string (toUrlEncodedJson)
- Base64-encode a merge parameter (#base64)
- Generate a SHA1 HMAC (hmacSHA1)
- Generate a SHA1 hash (sha1, #sha1)
- Generate an MD5 hash (md5, #md5)
- Generate a SHA256 hash (sha256, #sha256)
- Pad a parameter (center)
- Working with numbers (longs and doubles)
-
Working with lists/arrays
- Show item at index (square brackets)
- Iterating over all values (#each)
- Concatenate values in an array into a single string (join)
- Check for an item (#ifContains)
- Minimum value in list (#minInList)
- Maximum value in list (#maxInList)
- Size (size)
- Comparing two arrays (#eq, eq, #neq, neq)
- First and last items (@first, @last)
- Working with objects
- Working with dates
- Conditional and boolean logic
- Other Handlebars helpers
- JSON-LD
- Want to learn more?
Getting started with Handlebars
This section provides an overview of using Handlebars expressions in Iterable to reference, manipulate, and reason about data stored on a user profile or an event.
Definition: merge parameter
Wrapping the name of a user profile or event field in double curly braces creates a merge parameter. When using merge parameter, data from the relevant user profile or event is merged at send time into the template or URL being modified, customizing and personalizing it as necessary.
Sample user profile data
To view a sample user profile, navigate to Audience > Contact Lookup and search for an existing Iterable user profile. The user profile will look similar to this:
Projects that use userId
as a unique identifier can also use this field to
load data for a user—this includes userID-based projects and hybrid projects.
Read Project Types and Unique Identifiers
to learn more.
Sample event data
To view sample events saved by an Iterable project, navigate to Insights > Logs > Events.
Using Handlebars in HTML source
In an Iterable message template, you can add Handlebars expressions directly in the WYSIWYG editor or in its HTML source. When editing the HTML source, it is generally a good idea to comment out any Handlebars expressions that do not output a value.
In rare circumstances, the WYSIWYG editor can get confused by the presence of Handlebars expressions in the HTML source, which can lead to errors. Since the WYSIWYG editor ignores comments in the HTML source, commenting out Handlebars expressions can resolve this issue.
For example, do not enter this Handlebars expression in a message template's HTML source:
Instead, enter:
If you're entering a Handlebars expression that outputs a value (for example,
an expression like {{email}}
that outputs the value of a user profile
field), do not comment it out. Commenting out such an expression would
prevent its value from rendering in the template.
It is safe to comment out Handlebars expressions such as conditionals, looping constructions, closing statements, etc., that do not output any value. For these expressions, there is no risk of preventing a necessary value from rendering in the message template.
The rest of this document displays uncommented Handlebars expressions. That is, it displays them as they should be entered in the WYSIWYG editor, not the HTML source. When editing the HTML source of a message template, adjust the Handlebars expressions as demonstrated in the above example.
Referencing user profile and event fields with Handlebars
The most basic Handlebars expressions simply output the value of a field from a user's profile or the campaign's triggering event. To create this kind of simple Handlebars expression, wrap the name of your desired event or user profile field in double curly braces like this:
For example, this Handlebars expression outputs a user's email address:
Event and user profile field names are case-sensitive.
At send time, if the campaign's triggering event or API call contains a field with the same name as a field on the user's profile, Iterable displays the value from the event field. However, you can tell Iterable to display the value from the user profile field instead using the following syntax:
Example:
Let's say firstName
= "Christopher" in the campaign's triggering event and
firstName
= "Chris" on the user's profile. If you use the Handlebars
expression {{firstName}}
in your message template, it will evaluate
to “Christopher” (because the value from the triggering event field takes
precedence). If you use the Handlebars expression {{profile.firstName}}
instead, the output in the message will be "Chris".
Fields containing spaces or a period, or starting with a number
To use Handlebars to reference a field that contains spaces or a period, or starts with a number, surround the field in square brackets (as well as double curly braces).
For example:
WARNING
If possible, avoid using periods in field names, since they can cause difficulty when referencing data stored in nested objects on a user profile or event.
Fields containing HTML
To use Handlebars to display the HTML contained in a user profile or event field, wrap the field in triple curly braces (otherwise, the HTML will render as plain text). For example:
TIP
If the HTML-containing parameter comes from a data feed
Handlebars helpers and block helpers
Handlebars users helpers to manipulate, format, and loop through user profile and event data, to perform calculations, and to apply boolean and conditional logic. Helpers come in two varieties: helpers and block helpers.
Iterable message templates use Handlebars helpers and block helpers to display user and event profile data in a way that is most suitable to each recipient.
Helpers and block helpers can work with user profile fields, event fields, and literals.
For example, consider the capitalize
Handlebars helper, which capitalizes each
word in a string:
Assuming the existence of a favoriteBook
user profile or event field, these
examples will output:
War And Peace Animal Farm
Helpers
A Handlebars helper is a function that takes zero or more parameters and returns a value. For example:
This helper renders the firstName
parameter with its first letter
capitalized. The value stored in the firstName
parameter is not changed.
To nest sequential calls to Handlebars helper methods, use parentheses. For example :
This example lowercases every letter in firstName
, and then capitalizes its
first letter, rendering the output in the message template. Again, the value
stored in firstName
is not modified.
Block helpers
Like helpers, block helpers are functions. They are generally used to perform conditional logic or to iterate over collections of items.
A block helper has an opening statement, a block of content, and a matching
closing statement. The opening statement is always preceded by a #
character.
For example:
This example iterates over the items stored in the shoppingCartItems
,
displaying the name and price for each, like this:
Item name: shoes Item price: 59.99 Item name: jacket Item proice: 70.00
Working with strings
This section describes various helpers useful for working with strings in Handlebars.
#ifMatchesRegexStr
)
Regular expression matching (You can use regular expressions to compare string. For example:
-
To check whether a given string matches (exactly) another string:
-
To check whether a string contains a another string:
NOTES
- Regular expression queries are case-sensitive, which is why this example uses
[Bb]
to search for both cases. - To learn more about using regular expressions in Iterable, read Regular expressions for use in segmentation and Handlebars.
#ifContainsStr
)
Contains a substring (Search a string for a particular substring. If the substring is found, render the block's content. For example:
This example searches the haystack
field for "needle". If "needle" is found,
it renders the string "Haystack contains needle!"
#ifEq
, #eq
, #lt
, #lte
, #gt
, #gte
)
Checking equality and alphabetical order (To check whether two strings are in alphabetical order, use the various comparison helpers:
-
#ifEq
,ifEq
: if equals -
#eq
,eq
: equals -
#lt
,lt
: less than -
#lte
,lte
: less than or equal -
#gt
,gt
: greater than -
#gte
,gte
: greater than or equal
NOTES
If an
#lt
,lt
,#lte
,lte
,#gt
,gt
,#gte
, orgte
expression references a non-existent or null field, the template will fail and the message will not be sent to that user.Alphabetic order comparisons are case sensitive.
For detailed information about these comparisons, read the docs about the Java
compareTo
method.The below comparisons work for string literals as well as fields on user profiles and events.
For example:
-
To check whether "cat" comes before "dog" in alphabetical order:
This expression renders "cat comes before dog!"
-
To check whether "dog" comes after "cat" in alphabetical order:
This expression renders "dog comes after cat!"
-
To perform a string comparison in a boolean expression, use the non-block versions of these helpers:
For more information about the
#if
helper, see Conditional and boolean logic.
length
)
String length (Use the length
method to display the length of a string. For example:
For a myMergeParam
field with a value that's an 8-character string, his example
will output:
8
capitalizeFirst
)
Capitalize first letter of a string (Use the capitalizeFirst
helper to capitalize the first letter of a string.
For example:
Assuming myMergeParam
is set to iterable
, this will output:
Iterable
capitalize
)
Capitalize first letter of each word in a string (Use the capitalize
helper to capitalize the first letter of each word in a
string. For example:
Assuming myMergeParam
is set to iterable document
, this will output:
Iterable Document
upper
)
Capitalize entire string (Use the upper
helper to capitalize every letter in a string. For example:
Assuming myMergeParam
is set to ItErAbLe
, this will output:
ITERABLE
lower
)
Lowercase entire string (Use the lower
method to lowercase every letter in a string. For example:
Assuming myMergeParam
is set to ItErAbLe
, this will output:
iterable
defaultIfEmpty
)
Display default value if no value exists for a parameter (Use defaultIfEmpty
to display a default value for a parameter that's null,
undefined, or an empty string. For example:
Assuming myMergeParam
is null, undefined, or an empty string, this will
output:
My default value
Render HTML contained within a field
To render HTML contained in a field, wrap the field in triple curly braces. For example:
cut
)
Remove all instances of a specified string (To display a string with all instances of a certain string removed, use the
cut
helper. For example:
Assuming myMergeParam
is set to The cat climbed the tree
, this will output:
Thecatclimbedthetree
This does not affect the value stored in myMergeParam
, which (in this example)
would still contain spaces.
replace
)
Replace all instances of a string (To replace all instances of one string with another string, use the replace
helper. For example:
Assuming myMergeParam
is set to The dog ran around the block
, this will
output:
The-dog-ran-around-the-block
This does not affect the value stored in myMergeParam
, which (in this example)
would still contain spaces.
substring
)
Get substring by index (To display a substring of a string, use the substring
helper, which accepts
three parameters:
- (required) The string that contains the substring.
- (required) The starting index, in the containing string, of the substring.
- (optional) The index in the containing string of the first character past the end of the substring. The first character in the containing string has index 0.
For example:
Assuming myMergeParam
is set to iterable document
, this example:
- Finds the substring that starts at index 3 of
iterable document
(ther
) - Outputs the characters up to (but not including) index 6 (so, every character
up to but not including
l
)
Putting it together, this example outputs:
rab
This does not affect the value stored in myMergeParam
.
abbreviate
)
Abbreviate string to a specified length (To output a string, as abbreviated to a given length, use the abbreviate
helper.
This helper takes a single parameter: the final length of the string, including
three characters for ...
. For example:
Assuming myMergeParam
is set to Apples are red
, this will output:
Appl...
(Four characters for Appl
and three for ...
, making seven total characters)
This does not affect the value stored in myMergeParam
.
slugify
)
Convert to lowercase, remove numbers and special characters, and convert spaces to hyphens (Use the slugify
helper to output a string in lowercase, with numbers and special
characters removed, and spaces converted to hyphens. For example:
Assuming myMergeParam
is set to It's time for our 2nd annual fall sale
,
this will output:
its-time-for-our-nd-annual-fall-sale
The apostrophe has been removed, the 2 has been removed, and spaces have been converted to hyphens.
This does not affect the value stored in myMergeParam
.
#breaklines
)
Replace newlines (To replace \n
or \r\n
with <br>
, use the #breaklines
block helper.
Do this to help ensure that newlines display correctly in HTML.
For example, assume that myMergeParam
is set to:
Hi there! How are you?
And consider this #breaklines
expression:
This will output:
Hi there!<br><br>How are you?
This does not affect the value stored in myMergeParam
.
#urlEncode
)
URL encoding (To URL encode a string, use the #urlEncode
block helper. For
example:
Assuming that myMergeParam
is set to fall sale
, this example will output:
fall+sale
This helper:
- Does not encode alphanumeric characters, periods, hyphens, asterisks, or underscores. However, it changes spaces to plus signs, and URL-encodes all other characters.
- Does not affect the value stored in the provided field (in the example, this is
myMergeParam
).
toJson
)
Write the provided argument as a JSON string (Output the value it would be formatted when used as the value for a JSON field. For example:
For this example, the output depends on the data type of myMergeParam
:
myMergeParam | Data type | Output |
---|---|---|
My string | String | "My string" |
1234 | Long | 1234 |
3.14 | Float | 3.14 |
{"field1": "value"} | Object | {"field1": "value"} |
[1,2,3,4] | Array | [1,2,3,4] |
This does not affect the value stored in myMergeParam
.
toUrlEncodedJson
)
Write the provided argument as a URL encoded JSON string (Output the value it would be formatted when used as the value for a JSON field, URL-encoding special characters (such as quotes, curly braces, and square brackets).
For this example, the output depends on the data type of myMergeParam
:
myMergeParam | Data type | Output |
---|---|---|
My string | String | %22My+string%22 |
1234 | Long | 1234 |
3.14 | Float | 3.14 |
{"field1": "value"} | Object | %7B%22field1%22%3A%22value%22%7D |
[1,2,3,4] | Array | %5B1%2C2%2C3%2C4%5D |
This does not affect the value stored in myMergeParam
.
#base64
)
Base64-encode a merge parameter (To base64-encode a value, use the #base64
block helper. For
example:
Assuming myMergeParam
is set to user@example.com
, each of the above examples
will output the same value:
ZG9jc0BpdGVyYWJsZS5jb20= ZG9jc0BpdGVyYWJsZS5jb20=
This does not affect the value stored in myMergeParam
.
hmacSHA1
)
Generate a SHA1 HMAC (To generate a SHA1 HMAC, use the hmacSHA1
helper. This helper concatenates the
(arbitrary number of) passed-in parameters, then uses the HMAC Secret specified
in Project > Settings to generate an HMAC-SHA1. For example:
This does not affect the values of the passed-in parameters.
sha1
, #sha1
)
Generate a SHA1 hash (To generate a SHA1 hash, pass a string (or a field containing a string) to the
sha1
helper. For example:
If field1
is set to user@example.com
, this example will output:
e364ed2661a7b922e5bf670f2a0946977bf63ae7
It does not affect the value stored in field1
.
Alternatively, use the #sha1
block helper. For example:
This will output the same value as above. It does not affect the values stored in the passed-in parameters.
md5
, #md5
)
Generate an MD5 hash (To generate an MD5 hash, pass a string
(or a field containing a string) to the md5
helper. For example:
If userName
is set to docs
and host
is set to iterable.com
, this example
will output the MD5 hash for user@example.com
:
0e13848b1c7e27eb5d88c5d35b70783e
Alternatively, use the #md5
block helper. For example:
This will output the same value as above. It does not affect the value of the passed-in parameters.
sha256
, #sha256
)
Generate a SHA256 hash (To generate an SHA256 hash, pass a string
(or a field containing a string) to the sha256
helper. For example:
With field1
set to user@example.com
, this example outputs:
b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514
sha256
does not affect the values of passed-in parameters.
Alternatively, you can use the #sha256
block helper:
For this example, when userName
is user
and host
is example.com
, the
output is the same as above.
center
)
Pad a parameter (To output a field to a certain length, surrounded by a repeated character to
pad its length and center it, use the center
helper. For example:
If myMergeParam
is Hello
(five characters), this will output:
-------Hello--------
The total length is 20 characters, and the original string is roughly centered in the middle.
This does not affect the value of the passed-in parameters.
Working with numbers (longs and doubles)
This section describes various helpers useful for working with longs and doubles in Handlebars.
#ifEq
, eq
)
Equals (There are various ways to test for if one number equals another number:
-
Use
#ifEq
to test if one number is equal to another number and to display a block of content if so.#ifEq
can compare numbers represented as strings, longs, and doubles. Arguments need not be of the same type.This example displays
Equals
ifage
equals 21; otherwise, it displaysNot equals
:The
{{else}}
block is optional. -
Use
eq
to test two numbers for equality as part of a boolean expression.This example compares two sets of numbers. If either set is equal, it displays
Found a match
. Otherwise, it displaysNo matches
.For numeric comparisons, both arguments passed to
eq
must be of the same type: double or long.To output a string based on the result of an
eq
comparison, set values foryes
andno
. For example:For more information on boolean and conditional logic, read Conditional and boolean logic.
#ifGt
, gt
)
Greater than (There are various ways to test whether one number is greater than another number:
-
Use
#ifGt
to test if one number is greater than another number and to display a block of content if so.#ifGt
can compare numbers represented as strings, longs, and doubles. Arguments need not be of the same type.This example displays
<div>Greater than</div>
ifage
is greater than 21; otherwise, it displays<div>Not greater than</div>
:The
{{else}}
block is optional. -
Use
gt
to test whether one number is greater than another number as part of a boolean expression.This example compares two sets of numbers. If the first number is greater than the second in both sets, it displays
Both are greater than
. Otherwise, it displaysAt least one is not greater than
.For numeric comparisons, both arguments passed to
gt
must be of the same type: double or long.To output a string based on the result of an
gt
comparison, set values foryes
andno
. For example:If a
gt
expression references a non-existent or null field, the template will fail and the message will not be sent to that user.For more information on boolean and conditional logic, read Conditional and boolean logic.
#ifGte
, gte
)
Greater than or equal (There are various ways to test whether one number is greater than or equal to another number:
-
Use
#ifGte
to test if one number is greater than or equal to another number and to display a block of content if so.#ifGte
can compare numbers represented as strings, longs, and doubles. Arguments need not be of the same type.This example displays
<div>Greater than or equal</div>
ifage
is greater than or equal to 21; otherwise, it displays<div>Not greater than or equal</div>
:The
{{else}}
block is optional. -
Use
gte
to test whether one number is greater than or equal to another number as part of a boolean expression.This example compares two numbers. If the first number is greater than or equal to the second, it displays
Greater than or equal
. Otherwise, it displaysNot greater than or equal
.For numeric comparisons, both arguments passed to
gte
must be of the same type: double or long.To output a string based on the result of an
gte
comparison, set values foryes
andno
. For example:If a
gte
expression references a non-existent field, the template will fail and the message will not be sent to that user.For more information on boolean and conditional logic, read Conditional and boolean logic.
#ifLt
, lt
)
Less than (There are various ways to test whether one number is less than another number:
-
Use
#ifLt
to test if one number is less than another number and to display a block of content if so.#ifLt
can compare numbers represented as strings, longs, and doubles. Arguments need not be of the same type.This example displays
<div>Less than</div>
ifage
is less than 21; otherwise, it displays<div>Not less than</div>
.The
{{else}}
block is optional. -
Use
lt
to test whether one number is less than another number as part of a boolean expression.This example compares two sets of numbers. If the first number is less than the second in both sets, it displays
Both are less than
. Otherwise, it displaysAt least one is not less
.For numeric comparisons, both arguments passed to
lt
must be of the same type: double or long.To output a string based on the result of an
lt
comparison, set values foryes
andno
. For example:If an
lt
expression references a non-existent or null field, the template will fail and the message will not be sent to that user.For more information on boolean and conditional logic, read Conditional and boolean logic.
#ifLte
, lte
)
Less than or equal (There are various ways to test whether one number is less than or equal to another number:
-
Use
#ifLte
to test if one number is less than or equal to another number and to display a block of content if so.#ifLte
can compare numbers represented as strings, longs, and doubles. Arguments need not be of the same type.This example displays
<div>Less than or equal</div>
ifage
is less than or equal to 21; otherwise, it displays<div>Not less than or equal</div>
.The
{{else}}
block is optional. -
Use
lte
to test whether one number is less than or equal to another number as part of a boolean expression.This example compares two numbers. If the first number is less than or equal to the second, it displays
Less than or equal
. Otherwise, it displaysNot less than or equal
.For numeric comparisons, both arguments passed to
lte
must be of the same type: double or long.To output a string based on the result of an
lte
comparison, set values foryes
andno
. For example:If an
lte
expression references a non-existent or null field, the template will fail and the message will not be sent to that user.For more information on boolean and conditional logic, read Conditional and boolean logic.
#ifModEq
)
If remainder equals (If age
divided by 21 has a remainder or 0, output the contents of the block.
numberFormat
)
Formatting and rounding (Use the numberFormat
helper to format and round numbers in various ways.
For example (all examples below use literal numbers, but the numberFormat
works with user profile and event data as well):
-
Format as currency
Output:
$5.23
Output:
€5,23
NOTE
For a list of supported locale codes, see the Java Development Kit 11 support docs
.
-
Format as percent
Output:
23%
-
Specify a maximum number of fractional digits
Output:
123.457
-
Specify a minimum number of fractional digits
Output:
123.40000
-
Group digits for easy reading
Output:
1,000,000
-
Use a custom format (as specified by the
DecimalFormat
documentation)Output:
1,234.57
Output:
3.00
-
Round
-
Up (away from zero)
Output:
6
-
Down (towards zero)
Output:
5
-
Ceiling (towards positive infinity)
Output:
-5
-
Floor (towards negative infinity)
Output:
-6
-
Half even (towards the nearest neighbor; if equidistant, round towards the even neighbor)
Output:
6
-
Half up (towards the nearest neighbor; if equidistant, round up)
Output:
-6
-
Half down (towards the nearest neighbor; if equidistant, round down)
Output:
-5
NOTES
- When no
roundingMode
is specified,half_even
is used. - For more information and examples, see the Java
RoundingMode
documentation.
-
math
)
Addition, subtraction, multiplication, division, modulo (Use the math
helper to perform calculations. For example (all examples
below use literal numbers, but the math
works with user profile and event
data as well):
-
Addition
Output:
5
-
Subtraction
Output:
1
-
Multiplication
Output:
6
-
Division
Output:
1.5
-
Modulo
Output:
1
-
Using Math with Merge Parameters
Output: If the user had 3 cats, the result would be
5
cats.
Working with lists/arrays
This section describes various helpers useful for working with lists (such as
shoppingCartItems
) in Handlebars.
Show item at index (square brackets)
In this example works with the shoppingCartItems
array, accessing the name of the
second item. Note that the array index starts at 0, so the second item is located at
index 1.
#each
)
Iterating over all values (To loop over the values in an array, use the #each
block helper.
This example iterates through the shoppingCartItems
array, displaying the name
and price
for each item:
Output:
<div>Item name: Shoes</div> <div>Item price: 59.99</div> <div>Item name: Jacket</div> <div>Item price: 70.00</div>
To inspect the index of the current item in the loop, use @index
. Keep in mind
that the first item in an array has index 0.
Output example:
<div>Item 1 name: Shoes</div> <div>Item 2 name: Jacket</div>
For a more detailed example of how to use #each
and @index
, read
Conditional Logic with Handlebars.
join
)
Concatenate values in an array into a single string (To output the items of an array, joined by a particular character, use
join
. For example:
prefix
and suffix
are optional.
#ifContains
)
Check for an item (This example iterates over the shoppingCartItems
array, determining whether
it contains both chips
and dip
, either of them, or none of them.
Assuming the shoppingCartItems
array contains items where productName
is chips
and where productName
is dips, this will output:
You have chips and dip in your cart!
Here's another example that iterates over a user's emailListIds
array, in an
email-based project, to see if they're a member of a particular static list:
#minInList
)
Minimum value in list (To find the smallest item in a list, use #minInList
.
This example finds the least expensive item in the shoppingCartItems
array based
on the price
field of each item:
#maxInList
)
Maximum value in list (To find the largest item in a list, use #maxInList
:
This example finds the most expensive item in the shoppingCartItems
array,
based on the price
field of each item.
size
)
Size (To output the size of an array, use size
. For example, to find the size of the
shoppingCartItems
array:
Assuming the shoppingCartItems
array has two items, this will output:
2
#eq
, eq
, #neq
, neq
)
Comparing two arrays (To compare two arrays, use the #eq
, eq
, #neq
, and neq
helpers.
For two arrays to be considered equal, each array must have the same length and equal items, in the same order.
For example, consider these arrays, as might be stored on a user profile:
{ "array1": [1,2,3,4,5], "array2": [1,2,3,4,5], "array3": [4,5] }
Use the #eq
block helper to output a block of content when two arrays are equal.
-
This example outputs
The arrays are equal
: -
This example outputs
The arrays are not equal
: The
#neq
helper works similarly, but returns true when the two arrays are not equal.
Use the (non-block) eq
helper to compare arrays as part of a boolean expression.
-
This example outputs
The arrays are equal and contain more than two items
: The
neq
helper works similarly, but returns true when the two arrays are not equal.
@first
, @last
)
First and last items (This example finds the first and last items in the shoppingCartItems
array.
Working with objects
This section describes Handlebars helpers that can be used when working with objects.
#eq
, eq
, #neq
, neq
)
Comparing two objects (To compare two objects, use the #eq
, eq
, #neq
, and neq
helpers.
For two objects to be considered equal, each must have the exact same set of keys and values.
For example, consider these objects, as might be stored on a user profile:
{ "obj1": { "a": 1, "b": 2}, "obj2": { "a": 1, "b": 2}, "obj3": { "a": 1, "b": 3} }
Use the #eq
block helper to output a block of content when two objects are equal.
-
This example outputs
The objects are equal
: -
This example outputs
The objects are not equal
: The
#neq
helper works similarly, but returns true when the two objects are not equal.
Use the (non-block) eq
helper to compare objects as part of a boolean
expression.
-
This example outputs
The objects are equal and b is 2
: The
ne
helper works similarly, but returns true when the two objects are not equal.
Working with dates
This section describes various helpers useful for working with dates in Handlebars.
#ifGt
, #ifGte
, #ifLt
, #ifLte
)
Date comparison (The numeric conditionals (#ifGt
, #ifGte
, #ifLt
, #ifLte
) work with
appropriately formatted dates, since the date strings can be formatted as
numeric strings.
Example using #ifGte
:
Example using #ifLt
:
dateFormat
)
Date formatting (dateFormat
outputs a given date in the provided format.
dateFormat
)
Usage (For example:
Parameters:
-
inputDate
(required)A string that represents a valid date (either a string literal or a variable that contains a date string). Valid input date formats:
-
yyyy-MM-dd HH:mm:ss Z
For example:
2018-01-01 00:00:00 -0800
2018-06-22 14:00:00 +07:00
yyyy-MM-dd HH:mm:ss
Input formats accepted by
dateOptionalTimeParser
-
-
format
(optional)The format in which to output the date. Acceptable values defined by
java.text.SimpleDateFormat
.For example, this expression outputs a given date's day of the week (as a number):
Additional formats include
short
,medium
,long
, andfull
-
tz
(optional)The time zone in which to output the date. For a list of time zone values, read this blog post
For example, this expression takes a date (defined in UTC) and outputs it in New York's time zone:
Alternatively, use
tz=timeZone
to select thetimeZone
defined on the user's profile (if applicable).
NOTE
dateFormat
supports an alternate syntax that uses positional parameters instead
of named parameters:
For example:
When using this syntax:
formatString
should be specified in the same way as theformat
parameter, above.-
If
formatString
is provided, alocaleString
can also be given. This string should have formatlanguageCode_countryCode
, where:-
languageCode
should be lowercase -
countryCode
should be uppercase -
languageCode
andcountryCode
must be separated by an underscore
For example:
en_ES
,de_DE
,fr_FR
, etc. -
It is not possible to pass a
localeString
without aformatString
.
dateFormat
)
full (Example output: Tuesday, June 19, 2017
dateFormat
)
long (Example output: June 19, 2017
dateFormat
)
medium (Example output: Jun 19, 2017
dateFormat
)
short (Example output: 6/19/17
dateFormat
)
Format with locale (Example output: 21. Juni 2017
dateFormat
)
Format with time zone (
dateMath
)
Date math (dateMath
takes a given date and applies date math to it, as specified by a
provided mathematical expression.
dateMath
)
Usage (For example:
Parameters:
-
inputDate
(required)A string that represents a valid date (either a string literal or a variable that contains a date string). Valid formats for this paarameter include:
- yyyy-MM-dd HH:mm:ss Z
For example:
2018-01-01 00:00:00 -0800
2018-06-22 14:00:00 +07:00
yyyy-MM-dd HH:mm:ss
Input formats accepted by
dateOptionalTimeParser
now
- The current time (for the time zone defined by thetz
parameter, if available)midnight
- Midnight for the current day (for the time zone defined by thetz
parameter, if available)
-
dateMathExpression
(required)A string that represents the date math to apply to
inputDate
. In a date math expression, use these time units:-
y
: Years -
M
: Months -
w
: Weeks -
d
: Days -
h
orH
: Hours -
m
: Minutes -
s
: Seconds
For example:
This expression starts with
dateParameter
, adds one year, subtracts one month, adds one week, subtracts one day, adds one hour, subtracts one minute, and adds one second. -
-
format
(optional)The format in which to output the date. Acceptable values are defined by
org.joda.time.format.DateTimeFormat
For example, this expression subtracts five hours from a given date and outputs the day of the week (as a number) associated with the result:
Additional formats include
short
,medium
,long
, andfull
-
tz
(optional)The time zone in which to output the date. For a list of time zone values, read this blog post
For example, this expression takes an input date (defined in UTC), subtracts one hour, and outputs the result in New York's time zone:
Use
tz=timeZone
to select thetimeZone
defined on the user's profile (if applicable) -
locale
(optional)Localizes the output to the given language/locale combination. This string should have format
languageCode_countryCode
, where:-
languageCode
should be lowercase -
countryCode
should be uppercase -
languageCode
andcountryCode
must be separated by an underscore.
For example, this expression takes an input date, adds two hours, and outputs the result for locale
es_ES
:Output:
1 de enero de 2018
-
dateMath
)
Calculate a date from another date (The following example adds 30 days to the value of signUpDate
and outputs the
results as a long:
If the value of signUpDate
is 2022-10-10 17:47:38 +00:00
, the output will be
November 9, 2022
.
dateMath
)
Calculate a date from now (
dateMath
)
Calculate the number of days away from a date (You can use the dateMath
helper to determine how many days there are between
a date from a user or event field and now
(the current date at send time).
NOTE
The value of myDateField
must be a date that is both in the future and in the
same year as now
. If not, the output may be inaccurate.
Alternatively, you can use the #assign
method, which may give more accurate
results in certain situations. When using one or both of these methods, make
sure to throughly test and preview with user data before sending a campaign to
your users.
dateMath
)
Calculate a person's age (
now
)
Current date and time (now
outputs the current date and time in the provided format.
now
)
Usage (For example:
Parameters:
-
format
(optional)The format in which to output the date. Acceptable values are defined by
java.text.SimpleDateFormat
For example, this expression outputs the day of the week (as a number) associated with the current time:
Additional formats include
short
,medium
,long
, andfull
.
now
)
Current year (
now
)
Name of the current day of the week (
timestamp
)
Current time in epoch milliseconds (timestamp
outputs the current time in epoch milliseconds (number of
milliseconds since 1970-01-01 00:00:00 UTC).
Conditional and boolean logic
This section describes various conditional and boolean logic helpers supported by Handlebars.
True and false
Handlebars evaluates these values as false:
-
null
values - Empty strings (
""
) - Empty arrays (
[]
) - The boolean value
false
- Any number with a value of zero (
0
,0.0
)
Other values evaluate to true.
#if
)
If statements (The #if
helper evaluates a boolean expression. When true, the helper outputs the
contents of a block. This example outputs <div>Hi active user!</div>
when
activeUser
evaluates to true (see above); otherwise, it outputs
<div>Hi inactive user</div>
:
#if
can test nested conditions as demonstrated by this example, which outputs
<div>You like pets!</div>
to users whose likeCats
or likesDogs
user profile
field is set to true:
#and
, and
)
And (This section describes how to use #and
and and
in boolean expressions:
#and
is similar to #if
, except it evaluates any number of boolean expressions.
If they all evaluate to true, #and
outputs its associated block. For example:
#and
expressions can make use of other Handlebars helpers:
There also exists a non-block and
helper. Thisexample uses this helper to look for
any users who like cats, or adults who like dogs:
and
can output a value based on its evaluation. For example:
#or
, or
)
Or (This section describes how to use #or
and or
in boolean expressions:
#or
is similar to #if
, except it evaluates any number of boolean
expressions. If any of those expressions evaluates to true, #or
outputs its
associated block. For example:
#or
expressions can make use of other Handlebars helpers:
There also exists a non-block or
helper. This example uses this helper to look for
any users who like cats and either like dogs or are an adult:
or
can output a value based on its evaluation. For example:
#not
, not
)
Not (This section describes how to use #not
and not
in boolean expressions:
#not
negates the evaluation of a boolean expression. For example, if a user
profile has a likesCats
value of true
, this will return The user does like cats!
:
#not
expressions can make use of other Handlebars helpers:
There also exists a non-block not
helper. This example uses this helper to look
for any users who like cats and are not adults:
not
can output a value based on its evaluation. For example:
#unless
)
Unless (#unless
outputs its associated block unless the boolean expression is true.
This example outputs the text unless activeUser
has a value that evaluates to true
(see True and false):
Other Handlebars helpers
@key
and this
When you store an object on a user profile, sometimes you may want to look at
all of its keys and values (to output them, to find one that matches a particular
criteria, etc.). To do this, you can use @key
to reference the key, and this
to reference the value.
For example, here's an object that contains English and Spanish translations for the same word:
{ "translations": { "en_US": "Hello", "es_ES": "Hola" } }
To search for the Spanish translation, you might use code like this:
For the above translations
object, this Handlebars code will output:
The translation for es_ES is Hola.
This code:
- Iterates over each of the object's values (using
#each
). - Checks the current value's
@key
fores
(in this example, the key is eitheren_US
ores_ES
). - If
es
is found in the@key
, uses{{this}}
to output the translation (Hello
orHola
).
In other words: in each iteration of the loop, you're grabbing one of the
object's values (Hello
or Hola
). If that value's @key
contains es
,
you output the value.
@key
and this
with arrays
Using When using #each
to iterate over an array (instead of an object),
this
returns the item in the array, and @key
returns the item's 0-based
array index.
For example, consider this array and Handlebars code:
{ "favoriteColors": ["red", "blue", "green"] }
For this scenario, the code will output:
Key: 0, Value: red Key: 1, Value: blue Key: 2, Value: green
#lookup
)
Looking up a value (If you structure your data feed to resemble the example below, you can leverage
the #lookup
helper. The email body of this particular example (below)
consists of two paragraphs:
This takes the language
value from the user's profile, and performs a lookup
against the greetings
array (in this case, matching on "en"). It then returns
the values associated with greeting_1
and greeting_2
within that object.
NOTE
If using #lookup
with the email
field or any other field whose values
contain periods ("."), you must set resolveKey=false
in order for the lookup
to succeed. For example
#assign
)
Assigning a variable (You can use #assign
to set a variable that can be used at later points in a
template.
This example will output:
Greetings from Iterable!
NOTE
The assigned variable will be considered a string.
Inserting fields into snippets
You can pass fields from your template into your snippet. To do so, use this format:
Skipping/aborting a send
You can abort (and generate a skip) at any point in a template by using sendSkip
.
Any send skips originating from this will have a reason of SendAborted
.
You can pass any additional data you want persisted with the send skip via named parameters.
For example, consider users have a field creditAvailable
, and you want to abort the send if the user doesn't have enough credit to buy some product
they're considering. You might do something like:
JSON-LD
If you are using JSON-LD in your email template, you can use normal Handlebars format to include merge parameters inside the structured data block.
Want to learn more?
For more information about some of the topics in this article, check out these resources. Iterable Academy is open to everyone — you don't need to be an Iterable customer!
Iterable Academy
- Handlebars 101
- A Moment with Support: Looping over Arrays
- A Moment with Support: Utilizing Custom Event Data
- A Moment with Support: Formatting the Current Date with Handlebars
Other resources