How to Use Dynamic Content In Email Campaigns
Personalization in email campaigns can take many forms, from simply inserting the recipient’s name to offering a personalized discount. But it is far more impactful when the template adapts dynamically: shows items in the cart, suggests accessories for a recent purchase, or reminds the user about previously viewed products. Such emails feel like a continuation of a conversation rather than generic mass messages.
In this article, we will cover dynamic content: what it is, why it matters, and how it works.
What Is Dynamic Content
Dynamic content refers to elements in an email that change automatically at the moment of sending. They can be unique for each recipient or segment, turning a template into a personalized message.
Examples of dynamic elements include:
Element | Description |
---|---|
Product Cards | Generated from a YML or JSON feed or through CDP tools, and adapted to a specific user or segment. These can also be universal cards that don’t require manual re-coding: the system automatically adds products and prices from the website or CDP. |
Current Promotions | Inserted into the email based on the user’s region, their interaction history, participation in A/B testing, and other data. |
User Bonus Balance | Displays personal bonuses, accumulated points, or available privileges. |
News and Articles | Depend on the type of email campaign. For example, you can automate a monthly digest by loading the most popular blog posts into the template. |
Why Use Dynamic Content
In short — to make emails more effective, faster to develop, and easier to scale. Below, we’ll go into the main advantages in more detail.
Increased Campaign Effectiveness
When the email is tailored to the user’s interests, it feels relevant and attracts more attention. Deep personalization helps to:
- Better meet audience needs
- Keep attention through relevant offers
- Convert clicks into targeted actions
Easy Scalability
Without dynamic content, you have to create a separate template for each segment — a process that may take dozens of hours. With dynamic content, you only need to create a single template, and the system will automatically insert the necessary blocks. This allows new campaigns to launch faster, even in large-scale projects, while keeping the email structure clean and manageable.
Timely Response
Dynamic content is useful for reacting when the user is most engaged and interested. For this, you can set up automated scenarios, such as:
- When a customer has viewed a product several times on the website → Send an email with similar products or accessories
- When a customer has placed an order → Send an email with “You might also like…” recommendations
- When new arrivals appear in a product category the customer has purchased from before → Send an email “You may be interested in these new products”
Less Routine Work
A well-thought-out template with dynamic elements reduces the number of repetitive tasks required for preparing emails. This frees up time for more complex processes, such as developing creative materials and strategy planning.
How Dynamic Content Works in Emails
For an email to become dynamic, it must contain specific logic that allows the content to change automatically. For this, email marketing platforms use special tools: template engines, conditions, loops, and external data sources.
Variables: Data Insertion
This is the simplest form of personalization. Variables insert the necessary values from a database into the email, such as name, city, order amount, registration date, and other information.
Examples of variables:
Variable | Description |
---|---|
{{user.name}} | Recipient’s name |
{{user.city}} | City from the address database |
{{item.title}} | Product name from the data array |
Such variables can be used in the body text, links, images, or subject lines. The key point is that the data must be available in the system at the time the email is generated; otherwise, the variable will remain empty.
Loops: Iterating Through Lists
Loops are used to display a list of items in an email, for example, a set of recommended products.
Loop example:
1 2 3 4 5 6 7
{% for product in recommendations %} <div class="product-card"> <img src="{{product.image}}" alt="{{product.title}}"> <p>{{product.title}}</p> <p>{{product.price}} USD</p> </div> {% endfor %}
In this case, if five products are featured in recommendations
, the email will display five product cards.
Conditions: Displaying Relevant Content
Conditions control which content is shown depending on the user’s gender, status, activity, or other parameters. For example, these can be used to show one content block only to men and another only to women.
Conditions example:
1 2 3 4 5 6 7
{% if user.gender == "male" %} <img src="banner-men.jpg" alt="Men’s collection"> {% elseif user.gender == "female" %} <img src="banner-women.jpg" alt="Women’s collection"> {% else %} <img src="banner-default.jpg" alt="New arrivals"> {% endif %}
Conditions can also be combined with loops, for example, to display products only within a certain price range or from selected categories.
Feeds: Connecting External Data
To add up-to-date information on categories, prices, and product availability, you can use external data sources, such as YML or JSON files.
The platform loads the feed and makes its content available for display in emails. Since the data is loaded from an external source (such as the store’s website), it remains relevant in campaigns.
General example of connecting a YML feed:
1
[% external_extra("https://site.ru/catalog.yml", "format", "yml") %]
How Dynamic Content Works In Different Platforms
As an example, let’s take a look at how dynamic content is implemented in three popular mass mailing platforms: Altcraft, Sendsay, and DashaMail.
Altcraft
Altcraft Platform features Market — a module for working with product and customer order data. It allows you to use this data in email campaigns to generate dynamic content.
The following can be used in templates:
- Products. Prefix —
product
. A basic product card that contains the name (name
), identifier (external_id
), categories (categories
), custom fields (custom_fields
), and other parameters. - SKU (Stock Keeping Unit). Prefix —
sku
. Variations and product attributes, such as product manufacturer (manufacturer_name
), availability (is_available
), courier delivery option (delivery
), and others. - Order. Prefix —
order
. Includes general information about a single order, such as identifier (external_id
), status (status
), and total price (total_price
). - Orders. Prefix —
orders
. Allows for selecting multiple orders in a profile list.
Altcraft Platform supports two main methods of importing product data:
- YML. Format developed by Yandex and used for describing products. Suitable for bulk export from CMS, marketplaces, or warehouse systems. Includes store name, categories, product list, prices, and other parameters.
- JSON. Supports uploading product entities, SKUs, categories, orders, and items with required parameters (
external_id
,name
,entity_type
, and others). With JSON, you can add data generated on your server directly at the time of sending.
Below is an example of inserting product cards into a template. This is a simplified version of the code, showing only the key fragments:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
<table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr><td align="center" valign="top"> {for $index $el = products("product.manufacturer_name == 'Apple'" 4 "price" "desc")} <div style="display: inline-block;width:300px;"> <div><a href="{$el.url}" ><img src="{$el.pictures}" /></a></div> <div><a href="{$el.url}" >{$el.name}</a></div> {if "el.old_price"} <div><s>{$el.old_price}</s></div> {end} <div>{$el.price}</div> <a href="{$el.url}" >Buy now</a> </div> {if iseven($index)} <!--[if (gte mso 9)|(IE)]> </td> <td valign="top" width="300" style="width: 300px"> <![endif]--> {else} {if $index lt 3} <!--[if (gte mso 9)|(IE)]> </td></tr> <tr><td valign="top" width="300" style="width: 300px"> <![endif]--> {end} {end} {end} </td></tr> </table>
Let’s break down some of its elements:
for $index $el
— a loop that outputs an array of elements. In this case, the array is a list of products.products("product.manufacturer_name == 'Apple'" 4 "price" "desc")
— a product query. It contains four parameters: filter (which products to display), number of products, field to sort by, and the sort order.- Another important detail is the condition under the product card. To ensure proper display in Outlook, the correct table structure must be maintained. Depending on whether the current card number is even (
if iseven($index)
), the template should either move to the next cell in the same row or end the current row and start a new one. This is handled using conditional comments that Outlook can interpret and process.
A major advantage of Altcraft Platform is the unified template syntax for different channels — email, push notifications, SMS, and messengers. The same insertion and filtering logic works across all communication formats, simplifying the setup and scaling of campaigns.
Sendsay
Sendsay is equipped with the PROScript language, a content templating mechanism for email campaigns. It is designed to allow the following directly within an email template:
- Generate dynamic content
- Control structure based on conditions
- Insert data from external sources
PROScript supports:
- Variables. Provide access to profile field values or data from an external source. A variable can be a hash, a link to an array, or an object.
- Loops (
foreach
). Allow for iterating through data arrays (for example, a list of promotions or gifts). - Conditions (
if
,elsif
,else
). Display content blocks depending on variable values. - Operators (
==
,!=
,and
,or
). Enable building complex, compound checks and nested conditions.
For e-commerce scenarios such as “Abandoned Cart” or “Abandoned View”, Sendsay uses external YML files. In addition to product descriptions, these can contain a list of categories, promotions, and gifts. Elements in these sections are accessible via special keywords in the path:
[% yml.CATEGORY.<id>.* %]
— product categories, where<id>
is the value of the id attribute of the<category>
tag in the YML file, identifying a specific category in the catalog.[% yml.GIFT.<id>.* %]
— list of gifts, where<id>
matches the value of the id attribute of the<gift>
tag describing a specific gift.[% yml.PROMO.<id>.* %]
| — list of promotions, where<id>
is the value of the id attribute of the<promo>
tag describing the terms and details of the promotion.
Here is a simplified example of inserting product cards from a JSON file into a template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
[% external_extra("URL/products.json","ignore_error","1","timeout","1") %] <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr><td align="center" valign="top"> [% FOREACH item IN products %] <div style="display: inline-block;width:300px;"> <div><a href="[% item.url %]"><img src="[% item.pictures %]" /></a></div> <div><a href="[% item.url %]">[% item.name %]</a></div> [% IF item.old_price %] <div><s>[% item.old_price %]</s></div> [% END %] <div>[% item.price %]</div> <a href="[% item.url %]">Buy now</a> </div> [% IF loop.index % 2 == 0 %] <!--[if (gte mso 9)|(IE)]> </td> <td valign="top" width="300" style="width: 300px"> <![endif]--> [% ELSE %] [% IF !loop.last %] <!--[if (gte mso 9)|(IE)]> </td></tr> <tr><td valign="top" width="300" style="width: 300px"> <![endif]--> [% END %] [% END %] [% END %] </td></tr> </table>
Key points to note:
external_extra
requests a JSON file with the product catalog.[% FOREACH item IN products %]
loop iterates through all loaded products.- Proper display in Outlook is ensured through a table-based layout. For this, the code checks whether the current iteration is even:
[% IF loop.index % 2 == 0 %]
.
How it works upon sending:
- The platform loads data from JSON.
- Filtering and selection of required elements are performed directly in the template.
- The recipient sees content generated according to the set rules — for example, products from a chosen category or promotions for a specific segment.
DashaMail
Unlike Altcraft and Sendsay, DashaMail does not have a full-fledged template language with loops and conditions in the usual sense, but it does include a mechanism for automatically inserting product data from a YML file. The file must first be added in the “Products” section. It’s important to note that product insertion in DashaMail is only available for trigger emails.
Here’s how a basic example of adding product cards looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr><td align="center" valign="top"> <!--json_products_limit--><!--4--><!--/json_products_limit--> <!--json_products--> <div style="display: inline-block;width:300px;"> <div><a href="%YML_URL%"><img src="%YML_IMAGE%" /></a></div> <div><a href="%YML_URL%">%YML_NAME%</a></div> <div><s>%YML_OLDPRICE%</s></div> <div>%YML_PRICE%</div> <a href="%YML_URL%">Buy now</a> </div> <!--/json_products--> </td></tr> </table>
Let’s take a closer look at some of the details:
<!--json_products--><!--/json_products-->
— a loop that outputs product cards.<!--json_cart-->...<!--/json_cart-->
— for displaying cart data.<!--json_recent-->...<!--/json_recent-->
— for displaying recently viewed products.<!--json_products_limit--><!--4--><!--/json_products_limit-->
— sets a limit on the number of displayed products.
It’s not possible to add conditional comments for proper rendering in Outlook here. For layout purposes, other solutions need to be used — for example, displaying one card per row or applying CSS media queries for adaptation.
Tips for Working with Dynamic Content
Before launching a campaign, it’s important to check how the email looks and behaves in real-life conditions. Here are the key points to keep in mind:
- Test templates in different email clients. For example, Gmail may cut off content, and Outlook may display tables incorrectly. Check data insertion: for instance, what happens if the loop outputs only one product instead of four. Also check rendering on both desktop and mobile devices.
- Use a fallback if data is not loaded. For example, if the cart is empty or a field has no value. If a product is unavailable, show a placeholder (e.g., “Product will be available soon”) or hide empty blocks entirely.
- Avoid overloading with too many items. If there are too many products in the email, it’s harder for the reader to focus. Limit the template to 4–6 product cards. Below them, add a “View All” button that opens the full product list on the website.
- Limit image sizes. Heavy images slow down email loading. Compress them to an optimal size — ideally, up to 100 KB each.
Conclusion
When implemented correctly, tested thoroughly, and aligned with user behavior, dynamic content becomes a powerful email marketing tool. The key to success is a combination of technology with attention to detail:
- Choose the right tool for the task and complexity level
- Test scenarios and template responsiveness
- Ensure data accuracy and high-quality rendering
And if you wish to avoid the complexities of coding, use our convenient Pixcraft visual email builder. Bring your ideas to life quickly and without the need to dive into complicated technical details.