Liquid recipes
UpdatedLearn how to add liquid syntax for your use case.
You can find our available tags, keys, and filters in our Liquid syntax list, and you can learn more about how to use liquid in Personalize messages with liquid.
Countdown to an event
If your customers subscribe to an event—a webinar, they buy tickets to a movie or concert, etc—you can include a countdown to an event or specific date and time that your audience is interested in! The timer produces an animated GIF that counts down to the event.
The countdown timer GIF cannot contain more than 60 frames. This limits the size of the image in your messages and ensures that your message loads properly. So, if you set the resolution for your timer to seconds, the counter will stop 60 seconds after the image loads. The countdown image reloads when a person opens the message again, so it’ll always be relevant to the user’s current time, but it cannot count down indefinitely.
{% countdown point:64 font:roboto weight:light fg:000000 bg:f2f6f9 time:"2022-07-04 12:00:00 (GMT)" locale:en looping:true resolution:S frames:2 %}


Countdown timers take several parameters. Your timer must include the font size, the foreground (font) color, the background color, and the time you want to count down to.
| Parameter | required | format | default | description |
|---|---|---|---|---|
| point | ✓ | integer | The font size for the timer | |
| time | ✓ | ISO 8601 timestamp | The date and time you want to countdown to in the format YYYY-MM-DD hh:mm:ss (TZ). Remember to close the time in quotes, as the value includes a space. | |
| fg | ✓ | hex color | The foreground (font) hexidecimal color | |
| bg | ✓ | hex color | The background hexidecimal color | |
| font | string | inter, roboto | The font family for your timer | |
| weight | string | normal | The font weight, takes normal CSS font-weight values. | |
| locale | language code | en | The language you want to display: en (English), ru (Russian), jp (Japanese), zh (Chinese), pt (Portuguese), es (Spanish) | |
| looping | boolean | false | Determines whether the countdown timer should restart after it finishes | |
| resolution | one of S, M, H, D | S | Determines how often the timer counts down—by the second, minute, hour, or day. | |
| frames | integer | 1 | Number of seconds you want to show, based on the resolution, where seconds: 60, minutes: 2, hours: 1, days: 1 |
Math operations with attributes
AttributesA key-value pair that you associate with a person or an object—like a person’s name, the date they were created in your workspace, or a company’s billing date etc. Use attributes to target people and personalize messages. are stored as strings—even if the attribute value is a number or an integer. When you want to use a number/integer attribute in a math operation, or evaluate it against another number, you need to convert the attribute to a number/integer to ensure that your liquid statements evaluate properly. You can do this using plus to add zero to the attribute.
{% assign my_attribute = customer.my_attribute | plus: 0 %}
{% if my_attribute > 0 %}
Your attribute is greater than 0!
{% else %}
Oh no, your attribute is 0 or negative.
{% endif %}
Links
You can include attributes within links as well, in order to send your users to a custom page.
Example:
<a href="http://www.yoursite.com/{{customer.ATTRIBUTE}}">
Displaying a timestamp as a regular date
Let’s say you have a customer attribute called expiration (for a trial, maybe) that you store as a timestamp. If you wanted to display that expiration date in messages as a human-readable date, you can do so with liquid. There are a few different date filters you can use with this, but here we’re just going to show you month name, day, and year.
Example
If you had a customer attribute called expiration with a timestamp value of 1596153600, you can do the following:
{{customer.expiration| date: "%B %-d, %Y"}}
The result in your message would be July 31, 2020.
The spaces, commas, etc between the date filters are included in the output. So if you want 31/07/2020 you’d do %d/%m/%Y.
For the current date, you can use:
{{ 'now' | date: "%B %-d, %Y" }}
Displaying how many days left in a trial
{% assign current_date = 'now' | date: '%s' %}
{% assign future_date = customer.trial_end %}
{{ future_date | minus: current_date | divided_by: 86400 }}
Explanation
- You can get the current epoch time with
'now' | date: "%s". %s is a formatting option. - The
customer.trial_enddate is in epoch time. - Since epoch time is in seconds, we’re dividing by 86400 (number of seconds in a day) to get the number of days. Keep in mind that this is integer division so it’ll be rounded down.
Compare two user or event attributes
While it’s not possible to compare attributes when you create segments or when you set up an event filter for your campaign, you can use liquid code inside your campaign’s content to achieve this purpose. The following example checks for equality:
{% if customer.attribute_1 == customer.attribute_2 %}
Hello awesome person!
{% endif %}
But you can also use operators, such as >, <, and so on:
{% if customer.lifetime_value > 100 %}
Thanks for being a loyal customer!
{% endif %}
Emails: Using a customer name in the ‘To’ field
This is done by using the following Liquid in your email’s ‘To’ field:
{{customer.name}} <{{customer.email}}>
Localizing date
If you want to display the current date formatted like:
06:54 AM Février 21, 2017
you can use this code replacing the months with the proper names for your desired language:
{{'now' | date: "%H:%M %p %B %d, %Y" | replace: "January","Janvier" | replace: "February","Février" | replace: "March","Mars" | replace: "April","Avril" | replace: "May","Mai" | replace: "June","Juin" | replace: "July","Juillet" | replace: "August","Aout" | replace: "September","Septembre" | replace: "October","Octobre" | replace: "November","Novembre" | replace: "December","Décembre"}}
If you want to display the month in your customers’ language you can do this:
{{ event.invoice_date | date: "%-d" }}
{% case m %}
{% when '1' %}Janvier
{% when '2' %}Février
{% when '3' %}Mаrs
{% when '4' %}Avril
{% when '5' %}Mаi
{% when '6' %}Juin
{% when '7' %}Juillet
{% when '8' %}Août
{% when '9' %}Septembre
{% when '10' %}Octobre
{% when '11' %}Novembre
{% when '12' %}Décembre
{% endcase %}
{{ event.invoice_date | date: "%Y" }}
Show a different message based on day of week
{% assign day = 'now' | date: '%A' %}
{% if day == 'Friday' %}
Have a great weekend!
{% else %}
Cheers,
{% endif %}
Using data containing whitespace
We recommend adding data to Customer.io without spaces. But if you do (for example, if you send us an attribute called current city), here’s how you’d refer to it:
{{ customer["current city"] }}
Escaping special characters in attribute names
In general, you shouldn’t use periods, commas, numbers, or special characters in attribute names or event properties, because it can make it hard to find and use your attributes. But if your attribute names do include these kinds of characters, you can use brackets and quotes to reference your attribute in liquid.
{{customer["attribute.name"]}}
Filtering out default data or specific data
{% if customer.first_name contains 'Visitor' %}
{% else %}{{ customer.first_name | capitalize }}
{% endif %}
Advanced
Drag-and-drop editor users: If you’re writing more advanced Liquid including logical or comparison operators (&, >, or <, for example), use our Add Liquid dropdown option!
Looping through attributes
For this example, imagine each person has in their profile a list of friends, and you want to include this list in a message. Here’s an example of what the data you send to Customer.io might look like in JavaScript:
_cio.identify({
id: "1",
friends: ["Elaine", "George", "Kramer"]
});
Say the user with an id of 1 is “Jerry”. When you’re composing messages for Jerry, you can display his friend list using a Liquid for loop:
{% for person in customer.friends %}
{{ person }}<br/>
{% endfor %}
And that’s it! That’ll display:
Elaine George Kramer
Looping through event data
Let’s go back to our event data example above, where a user bought some socks. Instead of making just one purchase (socks), let’s say they bought multiple items (socks, toothpaste, and dental floss), and you want to list them all in a particular message. If you sent us data like this (this example’s in Ruby):
customerio.track ( user_id, "purchase",
:items => [
{:name => "socks", :price => "23.45"},
{:name => "toothpaste", :price => "3"},
{:name => "dental floss", :price => "2.97"}
]
)
You can access that data to output a list by looping through it. This is how you’d do that:
{% for item in event.items %}
{{ item.name }} - {{ item.price }} <br/>
{% endfor %}
This will loop through your data and output the items that were passed in with the purchase event.
Sorting looped data
This utilizes our latest liquid. Check your message to see which liquid version you’re using.
If you want to sort the data you’re looping through, you can use the sort filter. Here’s an example of how you might sort someone’s purchases per type.
Array of purchases
"purchases": [
{
"title": "utensils",
"type": "kitchen",
"date": "today"
},
{
"title": "garlic press",
"type": "kitchen",
"date": "yesterday"
},
{
"title": "vacuum",
"type": "household",
"date": "yesterday"
}
]
Liquid to sort the groups and items in ascending order
{% assign sorted_groups = customer.purchases | group_by: "type" | sort: 'name' %}
{% for group in sorted_groups %}
{{ group.name | capitalize }}
{% assign sorted_items = group.items | sort: 'title' %}
{% for item in sorted_items %}
- {{ item.title }}
{% endfor %}
{% endfor %}Liquid to sort the groups and items in descending order
{% assign sorted_groups = customer.purchases | group_by: "type" | sort: 'name' | reverse %}
{% for group in sorted_groups %}
{{ group.name | capitalize }}
{% assign sorted_items = group.items | sort: 'title' | reverse %}
{% for item in sorted_items %}
- {{ item.title }}
{% endfor %}
{% endfor %}
