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 handlebarAirship’s message personalization syntax using double curly braces ({{handlebars}}). You can use handlebars to insert variables and conditional logic in messages and templates. syntax to personalize templates and messages based on information that you associate with your audience. When you send a message, Airship evaluates the conditions in your template or 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.

When you send a message, set up an automation, or set up a journey, you will provide the variables that you referenced in your message template by CSV, in the API payload, or from an incoming custom eventA trigger that initiates an automation or journey when a custom event associated with members of your audience occurs. .

  • For SMS, email, and open channel messages, you will associate information directly with each user using a CSV or a /create-and-send API payload.
    • 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.
  • For automations and journeys directed at any channel, you will trigger your message using a custom event that contains properties relevant to each member of your audience. You can reference your custom event’s properties in the {{$data.events.[0].properties}} namespace.

Dynamic content uses handlebar syntax:

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

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.
{{else}}
   Maybe you'd enjoy a book instead.
{{/if}}
{{#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!
{{else}}
   Get up to $75 off!
{{/eq}}
{{#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!
{{/and}}
{{#or}} — Or

Renders message text if any of the conditions are true.

{{#or (eq movies "action") (eq era "80s") }}
   You might like Indiana Jones!
{{/or}}
{{#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 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 items in an array or keys in an object. You can reference the current item in the loop a few ways:

  • {{.}} — Access the current item in the array, generally for simple arrays of strings or integers.
  • {{key}} — Reference a key in the current object in the loop, generally for arrays of objects.
  • {{@index}} — Reference the current array index in the loop.
  • {{this}} — Limit the context to the current object iteration of the loop. Use dot notation to reference a key in the object, i.e. {{this.key}}. In general, you only need to specify this if you have a duplicate key outside the loop and the key within objects in the loop is optional. (this prevents Airship from using the value you the key outside the loop if the key does not exist in the current iteration of the loop).
 Note

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

Example: referencing names in a simple array
Everybody coming to the pizza party:
{{#each pizza_partiers}}
{{@index}}: {{.}}
{{/each}}
Example: referencing items in a user’s shopping cart as an array of objects.
Are you still interested in the following items? 
{{#each cart}}
* {{qty}}x {{product}} for {{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}} — Limit the context to the current iteration of the loop. Use dot notation to reference a key in the object, like {{this.price}} to specify a key in the current object called “price”.
 Note

In general, you don’t need to use this unless you have a duplicate key outside the loop and the key in your loop is optional. In such a case, this prevents the template from finding and using a dulpicate key outside the current iteration of the loop if the key in the loop is missing.

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).

 Note

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 within your template. 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:

We'll ship your package to:
{{#with shippingAddress}}
   {{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).

 Note

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:

ua_address,ua_commercial_opted_in,name,address.city,address.state,items.[0].name,items.[1].name
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.