Looping through objects and arrays

Loop through and repeat content from an array or object in your personalized message content.

You can use the #each operator to loop through and repeat content from an array or object. For example, you can show a user all the items in their shopping cart, including quantity, description, and price.

Specify the key of the array or object that you want to start your loop from using {{#each <property>}}. You can access properties within the loop with the HandlebarsHandlebars is Airship’s templating language for personalization. Handlebars expressions use double curly braces wrapped around a content template, ranging from a simple variable, e.g., {{first_name}}, to complex evaluations of personalization data. expressions on this page.


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.

Setting a loop limit

When you use #each, you can limit the number of loops to perform, making sure that your message is a reasonable length.

Set a limit using #each (limit <property> <integer>).

We think you might like:
{{#each (limit array_of_objects 2) as |obj|}}
{{obj.name}}: {{obj.desc}}

Setting context using #with

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 your audience’s shipping information is nested in an object called shippingAddress, your code might look like this:

{{shippingAddress.state}}, {{shippingAddress.zipCode}}

You then might use the with helper to limit context and simplify your template like this

We'll ship your package to:
{{#with shippingAddress}}
   {{state}}, {{zipCode}}

Referencing properties in objects and arrays

Because your loop reference begins from the object or array specified by #each, you don’t need to provide the full path of the property that you want to reference, just the path to the key within the current iteration of the loop.

For example, if looping through an array of objects called suggestedProducts, you could specify the keys within each object — qty and productName.

{{#each suggestedProducts}}
{{qty}}x {{productName}}

You can also reference properties of the array itself within the context of the loop.

  • {{.}} — Accesses the current item in the array, generally for simple arrays of strings or integers.

  • {{@index}} — References the current array index in the loop.

  • {{@key}} — Provides the key name or index location of the current loop iteration.

  • {{@root}} — Accesses the root element properties while you iterate in the context of any nested or child elements.

  • {{@first}} — Returns true for the first element in the loop and can be used with If/Else statements. For example, {{#each array}} {{#if @first}} Hello! {{/if}} {{/each}} will include “Hello!” in front of the first object in your array.

  • {{@last}} — Returns true for the last element in the loop and can be used with If/Else statements. For example, {{#each array}} {{#if @last}} Goodbye! {{/if}} {{/each}} will include “Goodbye!” in front of the last object in your array.

  • {{this}} — Limits 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 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 duplicate key outside the current iteration of the loop if the key in the loop is missing.

Reference names in a simple array:
Everybody coming to the pizza party:
{{#each pizza_partiers}}
{{@index}}: {{.}}

Reference 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}}

Using a feed

An External Data Feed is a connection to an external API. When you send a message, Airship uses a response from that API to personalize messages. See: External data feeds.

You reference an external feed as a block, and you can use properties from your feed within the block — {{#feed "feed_name" var_in_url="value" as |alias|}}.

For example, imagine you have a feed at https://www.example.com/[[region]]/featured-products that returns an array of products that you want to display to your audience. You may want to set the region at send time (rather than using the default value from your feed), and you may want to provide an alias so that your feed properties don’t collide with attributes or custom event properties.

Your message text and Handlebars might look something like this:

{{#feed "featured_products" region="us" as |result|}}
  {{#each (limit result.products 2) as |product|}}
    {{product.name}}: {{product.price}}
    https://cool-store.tld/us/products/{{urlEncode product.slug}}/
    Check back later for deals!
Couldn't fetch featured products!

While the feed block grants access to variables from the feed response, you can still reference variables (or merge fieldsA variable in your message or template that you want to populate with a personalized value for each member of the audience. Merge fields use Handlebars syntax — {{merge_field}}. ) that aren’t a part of the feed — attributes, custom event properties, etc. If this is something you may do, set the feed namespace using as |alias| to differentiate between properties from the feed and other personalization variables.