Attentive’s dynamic content, like variables and dynamic links, allows you to personalize the emails you send for each subscriber. See Personalize your email with dynamic content for more about personalization.
Because Attentive uses the Liquid templating language for personalization, you can use Liquid variables (objects), conditional logic, and iterative logic to fine-tune your personalizations.
Overview
You can use Liquid to include variables and execute logic, like conditional if
/else
logic and iterative for
logic, in your message:
- Single liquid objects (variables)
- Conditional statements (if/else tags)
- Iterative statements (for tags)
If there are errors with Liquid code (e.g., a value is missing for a subscriber, the syntax is incorrect), Attentive doesn’t send the email if it’s a marketing message. However, transactional messages are always sent, even if subscriber values are missing or there are Liquid syntax errors.
Notes:
- Whenever possible, we recommend using display conditions instead of Liquid templating. This reduces the possibility of syntax errors that may cause marketing emails to be dropped and transactional emails to have missing or unresolved values.
- Always preview your emails before sending a campaign or turning on a journey.
Use Liquid objects and object properties
Liquid objects (or variables) are placeholders that store a value, which can be displayed in a message. For example, you can use the {{subscriber.firstName}}
object/variable to display a subscriber’s actual first name in messages sent to them. See Personalize your email with dynamic content - Variables for a list of standard, non-custom Liquid objects in Attentive and instructions for adding them to your messages.
Follow these guidelines when adding and formatting non-standard Liquid objects in your emails:
- Enclose Liquid objects in curly braces
{{
}}
. - Enclose object properties in single quotes
'
'
.- For example, if the property is
VIP status
:{{ % if subscriber.custom['VIP status'] == "VIP" }}
- This formatting prevents issues if an object property contains spaces or if Liquid is embedded inside HTML tags with double quotes.
- For example, if the property is
- Don’t use single quotes for boolean values (more about booleans here).
- For example, if the boolean value is
true
:{{ % if subscriber.custom['isVIP'] == true }}
- For example, if the boolean value is
You can use variables in any content block containing text (such as a paragraph block, title block, or list block) in the drag-and-drop email editor. You can also use them in HTML content blocks and in the HTML editor.
Use Liquid date objects
Liquid allows you to personalize messages with dates, which can be helpful for offer expiration, birthday messages, or subscription messages. You can reference these dates from custom attributes, custom event data, or Liquid's built-in now
date object, which gets pulled in at time of send.
Attentive ingests dates in ISO 8601 format, but you may want to change the format to be more human-readable. When formatting dates, use the Liquid date filter, then bring in different parts of the date individually (day, month, year, time) or use preset date formats.
See the examples below for some common formats used on the now
object.
Description | Liquid code | Output |
DD/MM/YY | {{ "now" | date: "%D" }} |
09/06/24 |
Full date and time | {{ "now" | date: "%c" }} |
Fri, Sept 06 10:15:00 2024 |
Day, Month DD | {{ "now" | date: "%A, %B %e" }} |
Friday, September 6 |
12-Hour Time | {{ "now" | date: "%I:%M %P" }} |
10:15 am |
Use conditional logic with Liquid
You can use Liquid to write conditional logic in your messages. Conditional logic (also called statements or tags) allows you to display content based on certain conditions being met. For example, if a subscriber’s favorite color is red, you can display one message, and if a subscriber’s favorite color is anything other than red, you can display a different message.
See Control flow (Shopify) for a more detailed guide about creating conditional logic with Liquid.
Syntax for conditional logic with subscriber attributes
Here are a few important guidelines for writing conditional logic with Liquid:
- Wrap conditional logic in “Liquid tags,” denoted by curly brace percentage delimiters
{% %}
. - You can use as many
if
/elsif
/else
conditional statements as you need. - Always end conditional statements with an
endif
statement.
You can use the if
, elsif
, else
, and endif
tags to execute your use case.
if / elsif
The example below shows Liquid conditional logic that evaluates a custom attribute (favorite makeup product). If the if
condition isn’t met, the logic proceeds to evaluate the else
condition.
{% if subscriber.custom[‘favorite makeup product’] == “lipstick” %}
Check out Rihanna’s favorite lip picks for you!
{% else %}
Check out Rihanna’s top picks for you!
{% endif %}
In the example, if
a subscriber’s favorite makeup product
is lipstick
, then the message will say: Check out Rihanna's favorite lip picks for you!
. However, if
a subscriber’s favorite makeup product
is anything other than lipstick
, then the message will say: Check out Rihanna's top picks for you!
.
If you only want to evaluate whether something is true, you can omit == true
. The example below shows conditional logic that evaluates whether a subscriber is a vip
.
{% if subscriber.custom[‘vip’] %}
Hi, VIP customer!
{% endif %}
See the example below for conditional logic that uses if
, elsif
, and else
conditions:
Liquid code | Output |
{% if subscriber.custom[‘which pets are you shopping for’] == “dog” %} |
If the subscriber responds that they like dogs:
If the subscriber responds that they like cats:
If the subscriber responds that they like parakeets:
If the subscriber responds with something other than dog, cat, or parakeet:
|
Booleans
You can also use conditional logic with boolean properties (true
and false
). Like other variables, these come from either a custom attribute in the subscriber’s profile or the Custom Events API. Unlike other Liquid properties, however, you don’t need to enclose booleans in single quotes.
See the example below for logic that uses booleans to evaluate whether a subscriber custom attribute is true:
Liquid code | Output |
{% if subscriber.custom[‘responded to product survey’] == true %} |
If customer filled out a product survey:
If customer didn’t fill out the product survey:
|
Null values
Some APIs and integrations send object properties with null values, which generally means that a value isn’t present for an object. When possible, send booleans instead of null values or exclude them from the event object altogether.
If you must send null values, note the following:
- Null values should be sent to our APIs without quotes:
- ✅
{ last_name: null }
- ❌
{ last_name: "NULL" }
- ✅
-
if
conditionals for null values will fail, and the Liquid code will be skipped. - If an undefined macro is referenced within a conditional clause (e.g.,
{% if myUndefinedMacro = 'LoyaltyId' %}
), the message won’t be dropped. However, if it’s referenced to print (e.g.,{{ myUndefinedMacro }}
), the message will be dropped. - Attempting to display a null value in a message will cause errors:
- Marketing emails will be dropped.
- Transactional emails will be sent with errors, which usually appear as blank sections in the HTML.
Operators
You can use operators to evaluate object properties. Common operators include ==
, which you can use in conditional statements to show or hide content based on certain criteria.
Other operators include the following:
Operator syntax | Operator description |
== |
equals |
!= |
does not equal |
> |
greater than |
< |
less than |
= |
greater than or equal to |
<= |
less than or equal to |
or |
condition A or condition B |
and |
condition A and condition B |
contains |
evaluates whether a string or array of strings contains a specific string |
In the example below, the >
operator is used to evaluate whether subscribers have spent more than $500. Subscribers who spend more than $500 receive a free gift, while subscribers who spend less than $500 get free shipping:
Liquid code | Output |
{% if subscriber.custom[‘total spend’] > 500} |
If the subscriber has spent more than $500:
If the subscriber has spent less than $500:
|
Notes:
- Operators are evaluated from right to left.
- Parentheses are not supported in Liquid. They’re evaluated as invalid characters.
Syntax for conditional logic using event objects and properties
Some objects and properties come from an event and are shared with Attentive via the event payload (see Custom Events for more information). You can use these event variables similarly to subscriber attribute variables, and they use similar syntax.
Sample event payload with event object and properties
Below is a sample payload from a custom event that sends data to Attentive when an order is shipped.
{
"type": "Custom Shipped Event",
"properties": {
"orderStatusURL": "example.com/orderstatus/54321",
"delivery_date": "May 10",
"CustNo": 63459333,
"OrderNo": "W0041160",
"PayMethod": "Visa",
"Total": 100.00,
"Loyalty_member": true,
"Loyalty_points": 250,
"products": [
{
"name": "Shirt",
"price": 4.50,
"imageURL": "https://google.com",
"productLink": "https://google.com"
},
{
"name": "Pants",
"price": 10.50,
"imageURL": "https://google.com",
"productLink": "https://google.com"
},
{
"name": "Hat",
"price": 2.50,
"imageURL": "https://google.com",
"productLink": "https://google.com"
}
],
"shipment": {
"carrier": "fedex",
"trackingNumber": 12345
}
},
"externalEventId": "37fb97a9-6cfd-4983-bd65-68d104d53b70",
"user": {
"phone": "+15555555555",
"email": "test@attentivemobile.com"
}
}
To use the attribute PayMethod
as a variable in a message to a subscriber from the event above, use the following Liquid code: {{triggerEvent.custom['PayMethod']}}
. You can add default values , too, as in this example: {{triggerEvent.custom['PayMethod'] | default: 'none'}}
.
Sample Liquid code using conditional logic for event objects and properties
Below are a few examples that demonstrate how you can use operators in conjunction with the sample event payload and Liquid variable above.
Liquid code | Output |
Boolean {% if triggerEvent.custom[‘Loyalty_member’] == true %} |
If the subscriber is a loyalty member:
If the subscriber isn’t a loyalty member:
|
String {% if triggerEvent.custom[‘PayMethod’] == "Visa" %} |
If the subscriber used a Visa to purchase:
If the subscriber didn’t use a Visa to purchase:
|
Number {% if triggerEvent.custom[‘Loyalty_points’] > 200 %} |
If the subscriber has over 200 loyalty points:
If the subscriber has 200 or fewer loyalty points:
|
Assign and capture variables
Liquid provides two useful tags for creating and manipulating variables: assign
and capture
. These tags are useful when creating reusable content or complex personalized messages in your email messages.
Assign
Use assign to create a new named variable.
Example: {% assign header = "WELCOME TO OUR SALE" %}
Note: Variable assignment isn’t supported in the drag-and-drop editor. However, you can use variable assignment in the HTML editor.
Capture
Use capture to create complex strings using other variables or Liquid expressions.
Example:{% assign sale_date = "2023-09-01" %}
{% capture sale_message %}
Don't miss our big sale starting on {{sale_date}}!
{% endcapture %}
Use iterative logic with Liquid
Another way to use Liquid syntax to fine-tune personalization in your messages is to use the for
tag to iterate. Iterative statements (or tags) using for
allow you to loop through a list or array. For example, you can use iterative statements to display a list of products a subscriber added to their cart in a message.
- The Dynamic list content block only appears in the drag-and-drop editor if your event contains the corresponding list or product object.
- You can use
for
tags in the HTML editor or with the dynamic list content block in the drag-and-drop email editor. This ensures that the resulting HTML in the email message is properly formatted. You can’t use them in the HTML block in the email drag-and-drop editor.
Below are a few examples using the same sample custom event payload from the previous section.
Sample event payload with a list of products from an event
{
"type": "Custom Shipped Event",
"properties": {
"orderStatusURL": "example.com/orderstatus/54321",
"delivery_date": "May 10",
"CustNo": 63459333,
"OrderNo": "W0041160",
"PayMethod": "Visa",
"Total": 100.00,
"Loyalty_member": true,
"Loyalty_points": 250,
"products": [
{
"name": "Shirt",
"price": 4.50,
"imageURL": "https://google.com",
"productLink": "https://google.com"
},
{
"name": "Pants",
"price": 10.50,
"imageURL": "https://google.com",
"productLink": "https://google.com"
},
{
"name": "Hat",
"price": 2.50,
"imageURL": "https://google.com",
"productLink": "https://google.com"
}
],
"shipment": {
"carrier": "fedex",
"trackingNumber": 12345
}
},
"externalEventId": "37fb97a9-6cfd-4983-bd65-68d104d53b70",
"user": {
"phone": "+15555555555",
"email": "test@attentivemobile.com"
}
}
Sample Liquid code using for
tag to display list of products
Given the sample payload above, here’s how you can use the for
tag to display a list of all products from this event, along with the price of each product:
{% for item in triggerEvent[‘custom’][‘products’] %}
Product Name: {{item['name']}}
Product Price: {{item['price']}}
{% endfor %}
This code retrieves all prices and model numbers for every product in an event payload for a given subscriber. However, if you’re writing this in Attentive’s HTML email editor, it also needs HTML tags so that it can be rendered properly in the actual email that’s sent to subscribers.
Here’s an example written with HTML:
<table align="center" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;color:#000;background-color:#fff;width:600px;margin:0 auto" width="600">
<tr>
<td style="mso-table-lspace:0;mso-table-rspace:0;text-align:left;font-weight:400;padding-bottom:5px;padding-top:5px;vertical-align:top;border-top:0;border-right:0;border-bottom:0;border-left:0">
{% for item in triggerEvent[‘custom’][‘products’] %}
<table class="image_block block-1" width="100%" border="0" cellpadding="10" cellspacing="" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;word-break:break-word">
<tr>
<td class="pad" style="width:100%">
<div class="alignment" align="center" style="line-height:10px">
<a href="{{product.link}}" target="_blank" style="outline:none" tabindex="-1">
<img src="{{product.image}}" style="height:auto;display:block;border:0;max-width:695px;width:100%" width="695">
</a>
</div>
</td>
</tr>
<tr>
<td>
<div style="color:#000;direction:ltr;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;letter-spacing:0;line-height:120%;text-align:left;mso-line-height-alt:16.8px">
<p style="margin:0">Product Name: {{item['name']}}</p>
</div>
</td>
</tr>
<tr>
<td>
<div style="color:#000;direction:ltr;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;letter-spacing:0;line-height:120%;text-align:left;mso-line-height-alt:16.8px">
<p style="margin:0">Product Price: {{item['price']}}</p>
</div>
</td>
</tr>
<tr>
<td>
<div class="alignment" align="left">
<a href="{{product.link}}" target="_blank" style="text-decoration:none;display:block;color:#fff;background-color:#000;border-radius:4px;width:50%;border-top:0px solid transparent;font-weight:400;border-right:0px solid transparent;border-bottom:0px solid transparent;border-left:0px solid transparent;padding-top:4px;padding-bottom:4px;font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:16px;text-align:center;mso-border-alt:none;word-break:keep-all;">
<span style="padding-left:4px;padding-right:4px;font-size:16px;display:inline-block;letter-spacing:normal;">
<span style="word-break: break-word; line-height: 32px;">Buy now</span>
</span>
</a>
</div>
</td>
</tr>
</table>
{% endfor %}
</td>
</tr>
</table>
And below is the output of the HTML above without any additional HTML tags or formatting:
Troubleshooting
There are two common types of errors when using conditional and iterative logic with Liquid: data type errors and syntax errors.
Data type errors
Data values must be comparable in order for Liquid to properly evaluate and execute operators (e.g., ,
<
,==
). For example, your Liquid code won’t work as intended if you compare a string
data value to a number
data value.
If you use the custom events or the custom attributes API, you should also verify that values are properly formatted as follows:
- Don’t wrap numbers in quotes. In the JSON payload, a properly formatted number looks similar to the following:
"Total": 100.00
- Don’t wrap booleans (
true
andfalse
) in quotes. Properly formatted booleans look similar to the following in the JSON payload:"loyalty_member": true
- Always wrap string values in quotes.
If you use Attentive custom attributes, check the Custom attributes page to see what attributes and data types exist. Contact your Attentive CSM or White Glove (whiteglove@attentive.com) to change data types if needed.
If you change a custom attribute’s data type (e.g., from a string to a number), make sure that all values match the new type. If any values don’t match, Liquid code that references the attribute may fail, causing your marketing emails to be dropped. Your transactional emails will still be sent, but they may contain missing or unresolved values.
Syntax errors
Like any code, Liquid must be written correctly to be executed properly. This is especially important if you’re using the HTML editor rather than the drag-and-drop editor. Always make sure you have closing tags {%
%}
and curly braces. We recommend using a code editor like Visual Studio Code with the Liquid code extension to help you make sure you aren’t missing key characters.