Handlebars and Dynamic Content

Use handlebars to insert dynamic content and send personalized messages to each member of your audience. Pass variables to templates, determine the message text you want to show to each recipient based on those variables, and even iterate over objects and arrays of message variables.

You can use Airship's handlebar syntax to personalize templates and messages based on information that you associate with your audience. Airship evaluates conditions in your message, and issues personalized, Dynamic ContentVariable message content using handlebar syntax that you populate at send time. Use dynamic content to personalize messages for each member of your audience. to each member of your audience.

You can use handlebars to personalize templates. When you send a message based on a template, you will provide the variables that you want to populate for each member of the audience — either by uploading a CSV, or in the payload of a /create-and-send operation.

You can also use handlebars to personalize messages without a template when:

  • Creating an Automation using the Custom Event trigger.You can personalize automated messages using properties from your automation's custom event trigger. Access properties in the event in the {{$data.events.[0].properties}} namespace.
  • Sending a message using the Upload List Audience option.You will upload a CSV containing your message audience, and variables associated with each audience member. You can access variables in the list as merge fields
  • Sending a message using the /create-and-send API.Each object in the audience.create_and_send array represents an audience member, and variables you want to associate with each audience member. You can access variables here as merge fields in your message.

Dynamic content uses handlebar syntax:

{{#eq merge_field "string value"}}
    If merge_field contains "string value", this string will appear!

Logical Operators and Basic Syntax

Use the following logical conditions to determine the message content you want to send to each member of your audience.

{{$def}} — The default value handler

Use $def to set a default value for one or more variables. This handler is a simplified way of testing whether or not variables exist or are empty. In the handler you provide the variable(s) you want to use in your message and the default value. Airship uses the default value if the variable(s) do not exist, are null, or have an empty values, i.e., {{$def key1 key2 key<x> "value if keys are empty"}}.

The example below uses the value you if the name event property is empty or does not exist.

{{$def $data.events.[0].properties.name "you"}}
{{#if}} — If condition

Renders message text if the condition is not false, empty, or 0.

{{#if movies}}
   You might like Indiana Jones.
   Maybe you'd enjoy a book instead.
{{#eq}} — Equal to

Renders message text if a merge field contains a particular string value. In this example, the message is different if the merge field category contains the value Accessories.

{{#eq category "Accessories"}}
   Enjoy up to $25 off!
   Get up to $75 off!
{{#neq}} — Not equal to

Renders message text if a merge field does not contain a string value.

{{#neq things "thing 1"}}You must be thing 2!{{/neq}}
{{#and}} — And

Renders message text if all conditions are true.

{{#and (eq genre "action") (eq era "80s") }}
   You will definitely like Indiana Jones!
{{#or}} — Or

Renders message text if any of the conditions are true.

{{#or (eq movies "action") (eq era "80s") }}
   You might like Indiana Jones!
{{#not}} — Not

Renders message text if the merge field is empty or 0.

{{#not movies}}You might be interested in our new TV shows!{{/not}}`
{{else}} — Else

An alternative to a condition. Renders message text if the previous conditions fail and any conditions included with the else statement pass. When used without parameters, else renders a message if all previous conditions fail. Your message can have multiple else statements for any operation. For example, the following statement has else statement with a parameter and an else statement without:

{{#eq var_name "value"}}Money has value
{{else eq var_name “pizzaz”}}You have pizzaz
{{else}}I don't know what to tell you{{/eq}}
{{unless}} — Unless

Renders message text if the condition is false. This is a negative condition; you might want to use unless when you only really need the else statement for a condition. In the example below, the message text renders if the condition not_a_movie_watcher is empty or false.

 {{unless not_a_movie_watcher}}You'll probably like Indiana Jones.{{/unless}}

Greater Than and Less Than Operators

Comparison operators evaluate two values — numbers or array/string length (when comparing string values or arrays) and display text based on the result.

  • {{#lt}} — less than
  • {{#gt}} — greater than
  • {{#lte}} — less than or equal to
  • {{#gte}} — greater than or equal to

The following example displays text if "quantity" is less than 2.

{{#lt quantity 2}}You have <2 items in your cart{{/lt}}

Object and Array Loops

Looping operators help you traverse and display text from an array or object in your message. For example, you can show a user all the items in their shopping cart, including quantity, description, and price.

{{#each}} — Loop through an items in an array or keys in an object. Specify the array or object that you want to perform an operation against. Within the loop, you can specify the information you want to display, including a reference for the current array index or object key.


You cannot limit the loop using an operator. If you want to limit iterations in a loop, you must limit the array or object data that you pass to Airship.

This example displays a user's shopping cart items:

Are you still interested in {{#each cart}}{{this.qty}}x {{this.product}} for {{this.price}}{{/each}}?

You can use additional operators to reference properties in the current iteration of the loop:

  • {{@index}} — Reference the current array index in the loop.
  • {{@key}} — Reference a property in the object in the loop.
  • {{this}} — Reference the content in the loop. Use dot notation to reference a key in the object, like {{this.price}} to access a key in the current object called "price".

Object and Array Notation

You can use standard dot notation to access properties in objects or an item/index in an array.

Use the array index to access an item at a particular location in an array. For example, if your message includes an array of objects called suggestedProducts for each member of your audience, you can access the first suggested product with suggestedProducts.0 (array index 0).


Array indexes start at 0.

If you want to reference a key called image belonging to the first suggested product in the array, you would use suggestedProducts.1.image.

Use {{#with}} to set the context to a particular object. This can help you access nested keys without having to repeat the parent object's path. For example, if you wanted to print a user's shipping information from an object called shippingAddress, you might use the with helper like this:

{{#with shippingAddress}} shipped to {{yourStreet}}, {{yourState}}, {{yourPostCode}}{{/with}}

Object and Array Notation for CSV Uploads

When you Upload Users to send a message, you can include complex arrays and objects in your CSV using object notation to represent object properties in the header. When referencing an array index, you must wrap the array index in brackets. Your CSV should include headers for each item in the array and each property in the object that you want to reference in your message.

For example, if you want to use an array of objects called items for each member of your uploaded audience, your CSV will include items.[#] for each item in the array. If each object in the array had name, image, and url properties, you would add items.[0].name, items.[0].image, items.[0].url to your CSV, and reference additional objects in the array by incrementing the index (e.g. items.[1] and so on).


Array indexes start at 0.

If you wanted to personalize an email to members of your audience based on their addresses and the names of items they're interested in, you might format your CSV as follows:

someone@sample.com,2018-04-01T18:45:30,Joe Someone,Portland,OR,Rubber Gloves,Bleach Alternative  
else@sample.com,2018-04-21T16:13:01,Sir Else,Seattle,WA,Flashlight,Shovel 

Accessing Custom Event Properties

For Custom Event-triggered Automation, you can access event properties in the $data.events.[0].properties namespace. For example, if you have a property called cart, you could access it in your template at $data.events.[0].properties.cart.