Liquid is an open-source language created by Shopify to enable dynamic content. It is supported in smart transactional emails when you import your own email, allowing you to create invoice item lists, reformat text, show content based on certain conditions and more.
Below are some examples of how Liquid can be used with smart transactional emails. For a quick-start guide on Liquid's syntax and capabilities, we recommend Liquid for designers.
Handy to know
- The Liquid template language is not supported in classic transactional email.
- You can test your Liquid content before sending, by entering JSON directly into the "Email Variables" field during the testing stage.
- Liquid content is supported both in the body of your email, and the subject field, but not the "From" name or email address.
Filters
Liquid can manipulate strings and numbers in various ways using filters. A filter is applied to a variable by adding a pipe ( | ) symbol to the end, followed by a filter name and/or parameters.
For example, if you want to say "hi" to your recipient in your email, but want their name in uppercase regardless of how it is entered into your system, you could use the following:
Email content
HI {{ customer_name | upcase }}!
Above we have used the Liquid variable of customer_name, and piped it through the filter upcase, which converts everything preceding it into uppercase.
When we make an API call or perform a test using the above email content, and pass in the JSON content:
JSON payload
{
"customer_name": "Sally Sparrow"
}
Sally Sparrow's name replaces the customer_name variable in the email, and is then converted to uppercase, so the final result becomes:
Final email
HI SALLY SPARROW!
You can just as easily make text lowercase by using downcase instead, and perform other string manipulation tasks like slicing, splitting, replacement, reformatting a date and more.
Conditionals
Liquid supports if statements, using the syntax:
{% if variable == 'value' %}
//code if true
{% else %}
//code if false
{% endif %}
You can also specify extra conditions using the elsif tag.
{% if variable1 == 'value1' %}
//code if variable1 equals value1
{% elsif variable2 == 'value2' %}
//code if variable2 equals value2, but variable1 does not equal value1
{% else %}
//code if no conditions are true
{% endif %}
Like dynamic content in email campaigns, this can be used to show or hide content based on certain conditions.
For example, if you had recipients' countries recorded in your application, you could customize a greeting:
{% if customer.country == 'AU' %}
G'day {{ customer.name }}!
{% elsif customer.country == 'USA' %}
Yo {{ customer.name }}!
{% elsif customer.country == 'UK' %}
Hello there, {{ customer.name }}!
{% else %}
Greetings, {{ customer.name }}!
{% endif %}
If we then passed in customer data using the following JSON during a test send or API call:
{
"customer":
{
"name": "Sally Sparrow",
"country": "AU"
}
}
The final recipient would see:
G'day Sally Sparrow!
Loops
To create a loop — for example, for listing multiple items in an invoice — for is used.
For example, a simple FOR loop that reads from an array called invoice_list might look like this:
{% for item in invoice_list %}
{{ item.description }} | QTY: {{ item.qty }} | COST: ${{ item.cost }} | SUBTOTAL: ${{ item.subtotal }}
{% endfor %}
This block of code will repeat for every item that is passed in, building a list line-by-line, including each item's description, the order quantity, the cost, and the subtotal.
The JSON we'd pass in for a test email or API call, containing the items in said item list, would look something like this:
{
"invoice_list": [
{
"description": "Brand A Coffee (500g)",
"qty": 1,
"cost": 15.95,
"subtotal": 15.95
},
{
"description": "Brand B Tea (20 bags)",
"qty": 3,
"cost": 1.99,
"subtotal": 5.97
},
{
"description": "Brand C Coffee Mug (Large)",
"qty": 1,
"cost": 14.99,
"subtotal": 14.99
}
]
}
In the example above, there are three items within the invoice_list array: Brand A Coffee (500g), Brand B Tea (20 bags) and Brand C Coffee Mug (Large), each with its individual attributes. If this data was passed in, the final email would look like this:
To make things more readable, Liquid can be used inline with HTML and CSS. For example:
<table>
<tr>
<td class="description header bold">Item</td>
<td class="cost header bold">Cost</td>
<td class="qty header bold">Quantity</td>
<td class="subtotal header bold">Subtotal</td>
</tr>
{% assign invoice_total = 0.00 %}
{% for item in invoice_list %}
<tr>
<td class="description bold">{{ item.description }}</td>
<td class="cost">${{ item.cost }}</td>
<td class="qty">x{{ item.qty }}</td>
<td class="subtotal bold">${{ item.subtotal }}</td>
</tr>
{% assign invoice_total = invoice_total | plus: item.subtotal %}
{% endfor %}
<tr>
<td colspan="4"> </td>
</tr>
<tr>
<td colspan="4" class="total bold">TOTAL: ${{ invoice_total }}</td>
</tr>
</table>
Above is a basic HTML table, with predefined CSS (not shown—download the HTML file for the full example). The Liquid code has has been highlighted so it's easier to see.
We've added more Liquid in this example: an additional variable called invoice_total has been initialized outside the loop by assigning it a value of zero, then as each loop finishes for an input item, the item's subtotal is added to the invoice_total value using the plus filter. This provides a final total when the loop exits.
If you were to preview the example above in a browser, it would look like the image below:
Inputting the exact same JSON above, the email content gets filled out and arrives in the recipient's inbox like the following example:
Link tracking is not supported inside Liquid FOR loops. When adding links inside a FOR loop, make sure to turn off link tracking by including the cm_dontconvertlink parameter.