Handlebars rundown

Symplify uses handlebars for placeholders, custom tracking and dynamic content. This article is a reference of the handlebars you can use, with examples.

All handlebars that work in message content also work in links and in tracking. In links, the result is URL-encoded. To reuse handlebars you use often, save them as snippets.

 

Contact data

A handlebar starts with {{ and ends with }}. To show the value of a contact attribute, write contact. followed by the attribute name:

{{contact.firstName}}

When the message is sent, this is replaced with the value in the contact's firstName attribute. Attribute names aren't case sensitive, so {{contact.firstname}} works too.

 

Letter casing and fallbacks

 

Letter casing

Handlebar Result
{{#capitalize}}{{contact.firstName}}{{/capitalize}} Anna
{{lower contact.firstName}} anna
{{upper contact.firstName}} ANNA

 

Fallback for empty values

Use print to show a fallback when the attribute is empty:

Hi {{print contact.firstName "dear customer"}}

This renders Hi Anna, or Hi dear customer if the contact has no first name. You can combine print with other helpers:

HI {{#upper}}{{print contact.firstName "dear customer"}}{{/upper}}

This renders HI ANNA, or HI DEAR CUSTOMER.

 

Date formats

Dates are stored in the format yyyy-MM-dd, so {{contact.dateOfBirth}} renders for example 1979-08-03. See Date and time in the database. To show the date in another way, add a format:

Handlebar Result
{{date "d MMM. yyyy" contact.dateOfBirth}} 3 Aug. 1979
{{date "MMMM d" contact.dateOfBirth}} August 3
{{date "dd/MM/yy" contact.dateOfBirth}} 03/08/79

 

You can use these parts in the format:

Format Example result
M 8
MM 08
MMM Aug
MMMM August
d 3
dd 03
yy 79
yyyy 1979

 

Note: The parts are case sensitive. Use lowercase d and y. Uppercase D is the day of the year and Y is a week-based year, which give wrong dates.

 

Dates in other languages

Month and day names are in English by default. To use another language, use localizedDate with a language code, such as sv-SE (Swedish) or de-DE (German):

{{localizedDate "dd MMMM yyyy" "fr-FR" contact.dateOfBirth}}

This renders 03 août 1979. See Supported handlebar languages.

To show the day of the week, use EEEE:

{{localizedDate "EEEE" "fr-FR" contact.dateOfBirth}}

For a date that falls on a Tuesday, this renders mardi.

 

URL encoding

In links and tracking, values are URL-encoded so that they work in a URL. In content, you can encode a value yourself with urlEncode:

{{urlEncode contact.firstName}}

If an attribute holds a complete link, use noEncode in the link so the address isn't encoded:

<a href="{{noEncode contact.linkTarget}}">

 

Switch and compare

Use switch to show different content depending on a value. This is useful if you, for example, store short product codes but want to show the full name in your message.

This example checks the contact's product_size attribute:

{{#switch contact.product_size}}{{#compare "==" 'S'}}size: small{{/compare}}{{#compare "==" 'M'}}size: medium{{/compare}}{{#compare "==" 'L'}}size: large{{/compare}}{{#default}}Default value{{/default}}{{/switch}}

It renders size: small if the value is S, size: medium if it is M, size: large if it is L, and Default value for anything else.

The value doesn't have to match completely. To match values that start with something, use stringcompare:

{{#switch contact.status}}{{#stringcompare "startsWithIgnoreCase" "pro"}}professional{{/stringcompare}}{{#default}}creative mind{{/default}}{{/switch}}

This renders professional for values such as pro_sewer or pro_painter, and creative mind for everything else.

You can also compare numbers:

Level: {{#switch contact.bonusPoints}}{{#compare ">" 100}}Gold member{{/compare}}{{#compare "<" 100}}Silver member{{/compare}}{{#default}}New{{/default}}{{/switch}}

This renders Level: Gold member for more than 100 points, Level: Silver member for less than 100, and Level: New otherwise.

 

Compare operators

Operator Example Matches when the value
> {{#compare ">" 100}} is greater than 100
< {{#compare "<" 100}} is less than 100
>= {{#compare ">=" 100}} is 100 or greater
<= {{#compare "<=" 100}} is 100 or less
== {{#compare "==" 100}} is equal to 100. Works for text too, and ignores letter case.
!= {{#compare "!=" 100}} is not equal to 100
% {{#compare "%" 4 0}} divided by 4 leaves 0, that is, it can be divided by 4
!% {{#compare "!%" 4 0}} divided by 4 doesn't leave 0

 

Only the first matching compare in a switch is used.

 

Switch on a part of a value

Use switchOnExpression to switch on the result of another handlebar. For example, {{message.sendtime}} renders the full send time, such as 2026-02-07T08:55:30.587. To show the month as a name, pick out the month with date 'M':

{{#switchOnExpression "{{date 'M' message.sendtime}}"}}
{{#compare "==" '1'}}January{{/compare}}
{{#compare "==" '2'}}February{{/compare}}
{{#compare "==" '3'}}March{{/compare}}
...
{{/switchOnExpression}}

For a message sent in February, this renders February. Use y for the year, M for the month and d for the day.

 

When

when is a simpler alternative to switch and compare, for when you want to check one value:

{{#when contact.level "equals" "gold"}}
For gold members, our sale starts on Monday.
{{else}}
Our sale starts on Thursday.
{{/when}}

 

Text operators

Operator Matches when the value
equals is exactly the text
contains contains the text
startsWith starts with the text
endsWith ends with the text

 

The text operators are case sensitive. Add IgnoreCase at the end to ignore letter case, and not at the start to reverse the operator, for example equalsIgnoreCase, notEquals or notContainsIgnoreCase:

{{#when contact.level "notEquals" "VIP"}}
Become a VIP member today.
{{/when}}

If you leave out the operator, when uses equalsIgnoreCase: {{#when contact.level "vip"}}.

 

Number operators

Operator Matches when the value is
> greater than the number
>= greater than or equal to the number
< less than the number
<= less than or equal to the number
== exactly the same as the number, compared as text (so 5 and 5.0 don't match)

 

{{#when contact.points ">=" 500}}
You are a gold member.
{{/when}}

To check a range, put one when inside another:

{{#when contact.points ">=" 1}}{{#when contact.points "<=" 250}}Membership: Silver{{/when}}{{/when}}
{{#when contact.points ">=" 251}}{{#when contact.points "<=" 500}}Membership: Gold{{/when}}{{/when}}

when also works with purchase history and DataDocs:

{{#when ph.last.paymentOption "equals" "card"}}{{#when ph.last.totalPrice ">" 400}}You have earned a bonus with your latest purchase.{{/when}}{{/when}}
{{#when payment "equals" "accepted"}}Paid and ready to go.{{/when}}

 

Empty values

Without an operator or a value, when checks that the value isn't empty. Add {{else}} for a fallback:

{{#when contact.points}}Current points: {{contact.points}}{{else}}You have no points yet.{{/when}}

If you don't want to show anything when the value is empty, leave out the {{else}}.

 

Anniversary

ifAnniversary shows content when a date attribute has the same month and day as today. If there is no match, nothing is shown, or the {{else}} content if you add one. anniversary renders the number of years:

{{#ifAnniversary contact.date}}Time flies! You've been a member for {{anniversary contact.date}} {{#ifAnniversary contact.date 1}}year{{else}}years{{/ifAnniversary}}!{{/ifAnniversary}}

This renders, for example, Time flies! You've been a member for 2 years! Without a number, ifAnniversary matches dates one year ago or more, not dates from this year.

Add one number to match an exact anniversary. This only matches if the date is exactly 1 year ago today:

{{#ifAnniversary contact.date 1}}
Time flies! You've been a member for a whole year!
{{/ifAnniversary}}

Add two numbers to match a range. This matches if the date is 2, 3, 4 or 5 years ago today:

{{#ifAnniversary contact.date 2 5}}...{{/ifAnniversary}}

As in the first example, you can also use a number to choose the wording: {{#ifAnniversary contact.date 1}}year{{else}}years{{/ifAnniversary}} renders year on the first anniversary and years otherwise.

 

Purchase history

You can show purchase history data in your messages. Use the name of any purchase history column, standard or custom. The standard columns are transactionDate, ItemPrice, ItemCount and TotalPrice. To target the right rows, you sometimes need a segment.

There are three ways to pick rows:

  • The first or last row, for example "Are you happy with your new tent?"
  • The first or last row in a segment, for example "Are you running out of gas canisters?"
  • All rows, for example "This is your order history".

 

First or last row

{{ph.first.YourColumn}} gets the value from the oldest row, by transaction date. {{ph.last.YourColumn}} gets the value from the newest row.

For example, with this purchase history:

OriginalID TransactionDate ProductCategory
100245 2025-09-13 tents
100245 2025-11-20 boots
100245 2025-10-14 jackets

 

Handlebar Result
{{ph.first.ProductCategory}} tents
{{ph.last.ProductCategory}} boots
{{ph.last.transactionDate}} 2025-11-20

 

First or last row in a segment

Create a purchase history segment to target specific purchases, and use it as the master segment or as a content segment. {{ph.firstInSegment.YourColumn}} gets the value from the oldest matching row, and {{ph.lastInSegment.YourColumn}} from the newest.

For example, with a segment for everyone who bought gas canisters three weeks ago:

Hi {{contact.firstName}}, are you running out of {{ph.lastInSegment.ProductName}}?

This renders, depending on the contact's purchases, Hi Anna, are you running out of Camping Gas 230 g? or Hi Erik, are you running out of Camping Gas 450 g?

 

All rows

To show all purchase rows, from oldest to newest, use ph.all and choose the columns:

{{#each ph.all}}{{this.YourColumn}} {{/each}}

This is useful, for example, to list all purchased items on a Dynamic web profile page. To show only the rows that match a segment, for example purchases in a period or a product category, use ph.allInSegment:

{{#each ph.allInSegment}}{{this.YourColumn}} {{/each}}

If the message has no purchase history segment, ph.allInSegment returns all rows.

 

Format purchase history values

You can combine purchase history with the other helpers:

Handlebar Stored value Result
{{date 'd MMM. yyyy' ph.last.transactionDate}} 2025-11-03 3 Nov. 2025
{{capitalize ph.last.ProductName}} trail runner Trail runner

 

JSON arrays

For example for order confirmations, you can store a JSON array in an attribute or a DataDoc and show it in the message.

 

From a contact attribute

Use jsonRender. With this JSON in an attribute called LastOrder:

{
  "Products": [
    { "Product": "Trail runner", "Price": "1 499 SEK" },
    { "Product": "Wool socks", "Price": "199 SEK" }
  ]
}

this handlebar:

Your order:
{{#jsonRender contact.LastOrder}}
{{#each Products}}
{{Product}} ({{Price}})<br>
{{/each}}
{{/jsonRender}}

renders:

Your order:
Trail runner (1 499 SEK)
Wool socks (199 SEK)

If the attribute holds a JSON array rather than an object, loop over dataAsArray: {{#jsonRender contact.attributeName}}{{#each dataAsArray}}{{.}} {{/each}}{{/jsonRender}}.

 

From DataDocs

With this array in a document:

"orderItems": [
  { "ticketType": "Adult", "quantity": 2, "price": 40 },
  { "ticketType": "Child", "quantity": 1, "price": 10 },
  { "ticketType": "Student", "quantity": 1, "price": 15 }
]

this handlebar:

{{#documents}}
Your order:
{{#each orderItems}}{{ticketType}} x {{quantity}} = {{price}} €<br>
{{/each}}{{/documents}}

renders:

Your order:
Adult x 2 = 40 €
Child x 1 = 10 €
Student x 1 = 15 €

 

Calculations with numbers and dates

 

Numbers

In these examples, the contact has value1 = 10 and value2 = 5.

Handlebar What it does Result
{{add contact.value1 contact.value2}} Adds the values 15
{{subtract contact.value1 contact.value2}} Subtracts value2 from value1 5
{{multiply contact.value1 contact.value2}} Multiplies the values 50
{{divide contact.value1 contact.value2}} Divides value1 by value2 2
{{random 1 1000}} A random number from 1 to 1000 For example 417

 

Results are rounded to at most two decimals, with a comma as the decimal separator, for example 2,5. Dividing by 0 gives 0. To choose the format, add a number pattern and a language code:

{{multiply contact.price "0.8" "0.00" "en"}}

For a price of 199, this renders 159.20.

 

Dates

In these examples, the contact has StartDate = 2026-05-22.

Handlebar What it does Result
{{dateAdd contact.StartDate 2 "DAYS"}} Adds 2 days 2026-05-24
{{dateAdd contact.StartDate 2 "WEEKS"}} Adds 2 weeks 2026-06-05
{{dateAdd contact.StartDate 2 "MONTHS"}} Adds 2 months 2026-07-22
{{dateAdd contact.StartDate 2 "YEARS"}} Adds 2 years 2028-05-22
{{dateSubtract contact.StartDate 2 "DAYS"}} Subtracts 2 days 2026-05-20
{{dateAdd contact.StartDate 2 "DAYS" "MM/dd/yyyy"}} Adds 2 days and shows the result as MM/dd/yyyy 05/24/2026

 

Symplify entities

These handlebars show data about the message, campaign, project and link:

Handlebar Shows
{{contactdb.id}} The ID of the contact database
{{contactdb.name}} The name of the contact database
{{contact.originalId}} The contact's originalId
{{message.id}} The system ID of the message
{{message.guid}} The unique identifier of the message
{{message.sendtime}} The send time in the format yyyy-MM-dd'T'HH:mm:ss.SSS, for example 2026-06-25T15:30:24.123. To change the format, use the date formats or switchOnExpression.
{{message.abslice}} A, B, C or D, if the message is part of an A/B test. If the message is sent as the winning version, the winning version's letter is returned.
{{campaign.id}} The ID of the email
{{campaign.name}} The name of the email
{{campaign.segmentid}} The ID of the master segment. Returns -1 if there is no master segment, for example for transactional sendouts.
{{campaign.segmentname}} The name of the master segment
{{project.id}} The ID of the project
{{project.name}} The name of the project
{{link.id}} The ID of the link
{{link.name}} The name of the link
{{link.categories}} All categories on the link, separated by commas
{{link.segmentid}} The ID of the content segment on the block that contains the link
{{link.segmentname}} The name of the content segment on the block that contains the link
{{link.clicktime}} The click time in the format yyyy-MM-dd'T'HH:mm:ss.SSS. To change the format, use the date formats.

 

Regular expressions and substrings

 

Regular expressions

Use regex to pick out parts of a value:

{{#regex valueToMatchIn regexPattern}}
Your text, with the matched parts as {{match.1}}, {{match.2}} and so on.
{{/regex}}

valueToMatchIn can be an attribute, such as contact.firstName, or a fixed text in quotes. The pattern must match the whole value, and each part in parentheses becomes match.1, match.2 and so on. The pattern uses Java regular expression syntax.

Example:

{{#regex 'Hello World!' '([A-Za-z]+) World(!)'}}{{match.1}} Universe{{match.2}}{{/regex}}

This renders Hello Universe!

 

Substrings

Use substring to show part of a value:

{{substring beginIndex endIndex value}}

or as a block:

{{#substring beginIndex endIndex}}value{{/substring}}

The first character has index 0, and the character at endIndex isn't included. For example, if myValue is This is my Hello World! string:

{{substring 11 23 myValue}}

This renders Hello World!

 

Related articles

Was this article helpful?
0 out of 0 found this helpful