Data feeds let your templates render content using live external data at send time, so messages can reflect each recipient's latest context.
In Iterable, you reference data feed fields in templates with Handlebars.
This guide explains how to add a data feed to a template, choose the right template settings, and reference data feed fields correctly in template content.
# In this article
# Before you begin
Before you add a data feed to a template, make sure you've already:
- Created a data feed web service that meets Iterable requirements. See Creating a Data Feed Web Service.
- Added the data feed to your Iterable project. See Managing Data Feeds.
# Overview of using data feeds in templates
Once you have a data feed set up in Iterable, there are two parts to using it in a template:
Add the data feed to your template. You'll select the data feed to use in the template, and set template-specific settings for the data feed.
-
Reference the data feed fields in your template content. You'll use Handlebars syntax to reference the data feed fields in the template content.
NOTE
If you're using a snippet to process the data feed fields, read this guide first, then see Using Data Feeds in Snippets to learn how to set up this advanced use case.
# How data feeds are processed
When Iterable processes a template that references a data feed, it resolves the data feed fields and user profile fields, and then renders the final message for each recipient.
How Iterable resolves those fields depends on whether you've enabled the Merge the Data Feed and User Contexts setting on the template.
When Merge the Data Feed and User Contexts is enabled:
- User profile fields are populated first with data from the user profile.
- Data feed fields are populated next with data from the data feed.
When the merge contexts setting is enabled and a field name exists in both the user profile and the data feed, the user profile data takes precedence unless you use a data feed alias to reference the data feed data explicitly (thus separating the data feed data from the user profile data).
When Merge the Data Feed and User Contexts is disabled:
- Data feed fields are populated first with data from the data feed.
- User profile fields are populated next with data from the user profile.
Notably, field name collisions between data feed and user profile fields aren't
possible when the merge contexts setting is disabled, because data feed fields
are always resolved with square bracket notation ([[...]]), while user profile
fields are always resolved with double curly braces ({{...}}).
# Adding a data feed to a template
To add a data feed to a template, you'll need the Create and Manage Templates and Creative Library project permission.
First, add the data feed in the template details, following these steps:
- Open the template and click Edit in the Details area.
- Check the box in the Data Feeds section.
- In the dropdown menu, select the data feed(s) to use.
- Adjust the data feed template settings as needed:
- Click Save to keep your changes.
Now, you can use the data feed fields in your template content. See Referencing data feeds fields in a template to learn how.
# Using multiple data feeds in a template
You can use more than one data feed in a single template. Here are some key things to keep in mind when using multiple data feeds:
- The maximum data size is 4MB total for all data feeds in a template, not per data feed.
- Template settings apply to all data feeds in the template, and can't be selectively enabled or disabled per data feed.
- Using an alias for each data feed is highly recommended to avoid field name collisions and ambiguity in template content.
# Copying a template that references a data feed
When you make a copy of a template that references a data feed, the new template also references the same data feed.
Confirm that this is the correct data feed to reference in the new template before using it in a campaign.
To learn more about copying templates, see Organizing Templates.
# Template settings for data feeds
When you use data feeds in templates, you can set certain settings to control how Iterable processes the data feed. These settings apply to all data feeds in the template and cannot be customized on a per-data feed basis.
# Cache Data Feed Response (up to 1 hr)
Enabling caching causes Iterable to cache (store) a data feed response for 1 hour, reducing load on the servers that host the data feed by eliminating duplicate requests.
The cache expiration time is 1 hour and is not configurable. Caching applies to all data feeds in the template and cannot be selected on a per-data feed basis.
When this setting is enabled, Iterable checks if it has a cached response for the data feed URL from within the past hour. If a cached response exists, Iterable uses that data for the campaign send. If Iterable doesn't have a cached response stored, it queries the URL, uses the fresh data for the campaign send, and caches the response for the next hour.
When caching is disabled, Iterable fetches a fresh response from the data feed for every unique message ID (every recipient user).
# When to enable caching
-
Caching is helpful when:
- The data feed response is the same for all users (static data feeds).
- The data feed request URL and response are the same for a large number of users who share common values (such as users in the same locale or membership tier).
-
Caching is not helpful when:
- The data feed response is unique for each user (dynamic data feeds).
- The data feed content changes frequently and must be fresh at send time (such as real-time inventory or flash sale pricing).
Ask your development team to help you determine whether caching is appropriate for your data feed and template in question. For technical details on how caching works with static vs. dynamic data feeds, see Data feed caching.
# Merge the Data Feed and User Contexts
The Merge the Data Feed and User Contexts setting allows the template to reference data feed data with double curly braces
({{productName}}) instead of double square brackets ([[productName]]).
Double curly braces also reference user profile data. If the same field name exists for both the user profile and the data feed, Iterable prioritizes the value from the user profile. When the user profile data isn't available, Iterable falls back to the value from the data feed.
CAUTION
Merging user profile data with data feed data can cause a campaign to accidentally reference the wrong data source if you're not careful. This is because the setting prefers user profile data over data feed data.
To avoid this problem, you can use a data feed alias to reference the data feed data explicitly.
# Use Data Feed Alias
This option allows the template to reference data feed fields using an alias.
A data feed alias helps Iterable and template designers to disambiguate between data feed fields and user profile fields when they have the same name, making it less likely to accidentally reference the wrong data source.
A data feed alias can be helpful in the following situations:
- Merge the Data Feed and User Contexts is enabled.
- Your template has more than one data feed.
To use this setting, the data feed must have an alias set up. The alias is set when you create the data feed. It can also be added or changed later. To learn about adding or editing an alias for a data feed, see Managing Data Feeds.
When Use Data Feed Alias is enabled, you can use the alias as a prefix when referencing data feed fields in your template.
For instructions and an example of the syntax when using an alias, see Referencing data feeds by alias.
# Referencing data feeds fields in a template
You can reference the fields of a data feed in an Iterable template using Handlebars syntax.
(If you're using aliases for the data feed, read the next section on referencing data feeds by alias.)
How a data feed field is referenced in a template depends on the template settings and your desired outcome.
For example, if your data feed field name conflicts with a user profile field name, you can control how Iterable prioritizes the data source.
Use this table to choose the right syntax based on how you've configured your template:
| Goal | Template setting | Syntax to use |
|---|---|---|
| Reference only data feed fields | Merge the Data Feed and User Contexts disabled (default) | [[fieldName]] |
| Reference data feed and user profile fields together | Merge the Data Feed and User Contexts enabled | {{fieldName}} |
| Reference a data feed field by alias | Use Data Feed Alias enabled | Depending on the merge contexts setting:
|
You can choose to:
-
Use only data feed data. Use double square brackets (
[[]]) to reference the data feed field. This only references data feed data, not user profile data.
-
Prefer user profile data, but fall back to data feed data when the user profile data is not available.
Enable the Merge the Data Feed and User Contexts setting and
use double curly braces (
{{}}) to reference the data feed field.
TIP
If you're not sure what fields are present in your data feed, you can go to the Preview area of the template and load the data feed to see the fields and values.
If the data feed is dynamic, make sure to preview with user profiles that work with the data feed. For example, if the data feed is personalized by email address, preview with a user profile that has a valid email address.
To learn more about how to preview a template when it has data feeds, see Previewing Templates.
# Example data feed
Most of the examples in this guide use the JSON product feed example from
Creating a Data Feed Web Service.
That sample response has a top-level items array with toy product fields such
as sku, name, description, price, inStock, imageUrl, and
productUrl.
# Referencing data feeds by alias
To use an alias for data feeds in a template:
- Assign an alias to the data feed in question (on the Content > Data Feeds screen).
- Enable Use Data Feed Alias for the template.
To reference a data feed field by alias, use the alias as a prefix when referencing the data feed field in your template.
The basic syntax is [[alias.fieldName]].
For example, if you have a feed with the alias toyFeed, you can reference fields
in the items array with expressions like [[toyFeed.items.[0].name]], or
{{toyFeed.items.[0].name}} if you're also using Merge the Data Feed and User Contexts.
# Skipping a send when a data feed field is empty or missing
You can skip sending a message to a user when a data feed field is empty by
intentionally triggering an error. Use the {{#if}} helper to check if the
field has a value. If it doesn't, reference an invalid field to cause Iterable
to skip the send.
This example shows how to skip a send when the items array from the
sample data feed is empty or missing:
In this example, if the items field from the data feed is empty or
missing, Iterable attempts to resolve {{invalid.reference}}, which doesn't
exist. This causes the send to be skipped for that user. A send skip event is
logged in the Event History tab on the user's profile with the reason
HandlebarsExecutionError.
# Displaying multiple items from an array
Data feeds often return arrays of items, such as product recommendations, blog posts, or event listings. To display multiple items from an array, use one of the following approaches:
- Indexed expressions provide granular control over the position of each specific item and field in the template.
-
The
#eachhelper loops through all items in a single expression. You can add logic to limit the number of items displayed if needed.
For more information about Handlebars and arrays, see Handlebars Reference: Looping Over Objects and Arrays.
If you're rendering data feed array items through snippets, see Using Data Feeds in Snippets.
IMPORTANT
Arrays require indexed expressions or the #each helper to display content.
If your data feed field contains an array of items, a basic non-indexed expression doesn't iterate the list and may return empty output. To display items from an array, and the fields they contain, use one of the approaches described in this guide.
# Approach 1: Indexed expressions
Use indexed expressions when you want precise control over where each specific item appears in the template, such as in a specific column or row.
Benefits of this approach:
- Predictable output with a fixed number of items.
- Precise placement for each item in the layout.
- Easy to limit displayed items without Handlebars helper logic.
When using indexed expressions, remember that the index is zero-based, so the first item is at index 0, the second item is at index 1, and so on.
To learn more about indexed expressions in our Handlebars guide, see Display a specific item within an array.
The most basic expression for displaying an item from an array is:
This example displays the name and price fields for the first two items in
the items array:
# Approach 2: The #each helper
Use #each when you want to loop through an array dynamically.
Benefits of this approach:
- Displays some or all returned items without hard-coding indexes.
- Less repetitive template code.
- Can be combined with helper logic (such as index checks) to limit output.
A basic #each loop without any helper logic displays all items in the array.
To learn more about the #each helper in our Handlebars guide, see Display all items in an array.
With square bracket notation (default settings):
For a template with Merge the Data Feed and User Contexts and Use Data Feed Alias
enabled (for example, alias toyFeed):
To limit the number of items displayed, you can use the #lt helper in block
format with the @index variable and #each. This creates a maximum number
of items that can be displayed, regardless of the number of items in the array.
To learn more about the lt helper in our Handlebars guide, see Check whether one number is less than another.
With square bracket notation (default settings):
With Merge the Data Feed and User Contexts and Use Data Feed Alias enabled
(for example, alias toyFeed):
This stops the items from displaying after the fifth item:
- If there are more than 5 items, only the first 5 items display.
- If there are fewer than 5 items, only the items that are available display (for example, if there are 3 items, only the first 3 items display).
- If there are exactly 5 items, 5 items display.
# Referencing fields with special characters and namespaced fields
Some data feeds may include field names that contain special characters.
For example, your data feed may use field names that contain colons. These are often called namespaced fields, and are common in RSS/XML formats.
For example:
| Namespace | Common fields | Purpose |
|---|---|---|
content: | content:encoded | Full HTML content of an article |
dc: |
dc:creator, dc:date
| Dublin Core metadata |
itunes: |
itunes:duration, itunes:summary
| Apple iTunes podcast metadata |
media: |
media:content, media:thumbnail
| Images, videos, media attachments |
To reference a field name that contains special characters, wrap the field name in square brackets and quotes:
With square bracket notation (default settings):
With Merge the Data Feed and User Contexts and Use Data Feed Alias enabled
(for example, alias rssFeed):
NOTE
If the field contains HTML that you want rendered (not escaped), use unescaped output syntax for your merge contexts setting:
- With square bracket notation (default settings):
[[{item.[0].["content:encoded"]}]] - With Merge the Data Feed and User Contexts and Use Data Feed Alias enabled:
{{{rssFeed.item.[0].["content:encoded"]}}}
# Referencing sub-properties of namespaced fields
The bracket-and-quote syntax shown above works for namespaced fields that contain
a single value (like content:encoded or dc:creator). However, some
namespaced fields are objects with sub-properties, rather than simple values.
For example, the media:content element in an RSS feed often contains attributes
like url, medium, height, and width all within the same element (surrounded
by angle brackets <...>):
<item> <title>How To Scale Personalization With Modular Content</title> <link>https://iterable.com/blog/modular-content-personalization/</link> <description>Learn how to scale personalization by assembling messages from reusable content blocks.</description> <media:content url="https://iterable.com/blog/images/modular-content-hero.jpg" medium="image" height="1200" width="2400"/> <author>Katie Gray</author> </item>
When Iterable parses this feed, the media:content element becomes an object
with properties like url, medium, height, and width. You might expect to
access the image URL with a path like item.[0].["media:content"].url, but this
resolves to an empty string. This limitation applies to dot notation, lookup,
and #with.
To access sub-properties of a namespaced field, use #each to loop over the
item's fields, check @key to find the namespaced field, then access its
sub-properties from within that context. Then, use #assign to capture the
sub-property into a variable you can reference later in the template.
The example below uses an indexed expression to capture the sub-property for
each item, an alias for the data feed (blogFeed), and has Merge the Data Feed and User Contexts
enabled (using curly braces notation):
Inside the #each loop, this refers to the media:content object directly.
From this context, sub-properties like this.url, this.width, and this.height
resolve correctly.
After the loop, you can use the captured variable anywhere in the template:
To put it together, you can use an indexed expression to capture the sub-property for each item:
Or, use a nested #each loop:
If you aren't using the merge contexts setting or an alias, here is the final example in square bracket notation:
NOTE
If you need to pass a captured sub-property value like this to a snippet, see Passing sub-properties of namespaced fields to snippets for more information.
# Referencing data feeds in snippets
For a more advanced use case, you can pass data feed fields to snippets, and then use snippets in your templates to display data feed content via reusable content blocks.
The snippet article covers techniques specific to passing data feed values into snippets.
To learn how, see Using Data Feeds in Snippets.
# Troubleshooting
# Data feed fields not displaying
If data feed fields are missing from the rendered message, check the following:
- Confirm the data feed is added to the template. In the template details, verify that the data feed appears under Data Feeds and is checked.
-
Check your bracket syntax. If the template does not have Merge the Data Feed and User Contexts
enabled, use square bracket notation (
[[fieldName]]). Using curly braces ({{fieldName}}) without the merge contexts setting enabled resolves to the user profile field of the same name, or renders as empty if no such profile field exists.
Check for field name collisions. If a field name exists in both the data feed and the user profile, and the merge contexts setting is enabled, the user profile value takes precedence. Use a data feed alias to reference data feed fields explicitly and avoid collisions.
Check the data feed response. In the template Preview area, load the data feed to confirm it's returning data. If the feed is dynamic, preview with a user profile that satisfies the feed's conditions (for example, a valid email address for a feed personalized by email).
# Arrays not displaying multiple items
If a data feed field is an array and only one item displays (or none), the
template is using a basic expression instead of an indexed expression or
#each loop.
- To display a specific item by position, use an indexed expression such as
[[items.[0].name]]. - To loop over all items, use the
#eachhelper.
For examples, see Displaying multiple items from an array.
# Send is being skipped
If messages are not being sent to users, and you see a HandlebarsExecutionError
or RetriesExhaustedError in the send skip events on a user's profile:
-
HandlebarsExecutionError: The template referenced an invalid Handlebars expression, which may be intentional (for example, using{{invalid.reference}}to skip sends when a data feed field is empty). Verify the template logic is correct.
-
RetriesExhaustedError: The data feed web service did not respond within 10 seconds after 5 attempts. Check that the service is reachable, responding quickly, and not returning 4xx or 5xx errors. See Response times, retries, and timeouts.
# Data feed content is stale
If the data feed is returning outdated data, caching may be enabled on the template. The cache persists for up to one hour and is not configurable. Disable the Cache data feed response (up to 1 hr) setting on the template if freshness is critical. See When to enable caching for guidance.
# 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
Support docs