Liquid tag list
UpdatedThis page contains a list of the liquid tags, variables, and filters available to you in Customer.io. Use the search bar below to look for a specific tag. If you’re new to liquid, you can learn more about it in our guide about personalizing messages.
You're looking at the latest Liquid documentation
If your account was created on or after Nov 28, 2023, you are using our latest liquid version for all messages. If your account was created before this date, go to How to upgrade your liquid version for more info.
The two versions are largely similar, but you'll find a list of differences on our Liquid Upgrade page.
Looking for something specific?
Variables and Assignment
There are common variables you can reference within messages and elsewhere. These may be variables associated with a person, the event triggering a message workflow, or variables that you assign within your message from other values.
Logical Operators
Logical operators determine the basic rules for evaluating true or false statements. You can also use
and
andor
operators to combine logic statements to evaluate multiple conditions.Loops and Conditionals
Loop through an array of items or set conditions determining the content that you want to show.
Timestamps and Dates
Use these tags to get and manipulate dates and times.
Array Filters
Liquid used to filter and manipulate arrays (lists of values). If your event or another incoming value is an array, you may iterate over the array with a
for
loop or grab items at a particular index of the array, to display information for your audience.Number and Currency Filters
These are tags and filters that manipulate incoming number, integer, and timestamp values.
Some tags, like the
currency
andformat_number
, take an optional localization parameter, formatting the output for a specific locale. These tags use the format{{ 10 | currency: "en-us" }}
, which would output$10.00
.Math Filters
Filters that perform math operations on incoming number or integer values. With the legacy liquid version, if you encounter an error with negatives while using math filters, wrap the negative numbers in quotes.
String Filters
The following filters manipulate strings in templates. You might use these to truncate or set the case of strings you reference from other places, to humanize your messages for recipients.
Miscellaneous
These are tags that you can use to escape liquid rendering or escape rendering all together.
campaign.id
“Your campaign’s numerical ID. This can be found in your campaign URL. For example, the campaign ID here is 2000:
https://fly.customer.io/env/12345/v2/campaigns/2000/overview.
For newsletters, your
campaign.id
is the value afternewsletters
in your URL. For example, the newsletter’scampaign.id
here is1
https://fly.customer.io/env/109950/composer/newsletters/1/templates/21
.”Syntax
{{campaign.id}}
campaign.name
The name that you assigned your campaign or newsletter. For example: “Q2 Anvil Onboarding Campaign [Coyotes]”.
Syntax
{{campaign.name}}
campaign.subscription_topic_ids
This returns the topic assigned in subscription preferences settings for Campaigns, API Triggered Broadcasts and Newsletters.
Syntax
{{campaign.subscription_topic_ids}}
campaign.type
This returns the type of trigger for your campaign:
behavioral
(segment-triggered),transactional
(event-triggered),form
,date
,object
, orrelationship
. For messages sent through our Transactional API, this returnstransactional_message
. It also returnstriggered_broadcast
for an API-triggered broadcast ornewsletter
accordingly.Syntax
{{campaign.type}}
cio_link
Use this tag to track links in non-email messages (SMS, push, or slacks) as well as
mailto
links. If you use our SDKs, you do not need to use this tag to track links in in-app messages or push notifications. To track links in emails, go tocio_link_id
below.The filters
track
andurl_params
are optional. If you exclude these filters, url parameters will be present and tracking will be on. To turn either off, set them to false. For more info on this tag, go to Link tracking.Do not use this tag to track deep links.
Example
{% cio_link url:http://example.com %} {% cio_link url:http://example.com track:true url_params:true %} {% cio_link url:http://example.com track:true url_params:false %} {% cio_link url:http://example.com track:false url_params:true %} {% cio_link url:http://example.com track:false url_params:false %}
Output
https://e.customeriomail.com/e/c/{string} https://e.customeriomail.com/e/c/{string} https://e.customeriomail.com/e/c/{string} http://example.com?utm_campaign={string}&utm_content={string}&utm_medium={string}&utm_source=customer.io http://example.com
cio_link_id
Use this to track deep links in emails. Visit Track universal and app links in email for instructions.
For links in non-email messages, go to
cio_link
above.Example
<a href="https://yourwebsite.com/confirm?link_id={% cio_link_id %}" class="untracked">Text</a>
content
Use in layouts to indicate where code added via the email editor will be included. You might use this in a template for a transactional message or API-triggered broadcast where you will provide content from the API directly.
Example
{{content}}
delivery_id
A URL-compatible base64 string that identifies an instance of a message created for a person. This is set to unsent in test send and composer previews, and generated when the message is drafted or sent.
Syntax
{{delivery_id}}
event_id
The id of the event being previewed for the selected sample profile. It throws an error if the event has not been sent recently (within the last ~30 days).
Syntax
{{event_id}}
event_name
The name of the event that triggers a campaign. If you send an event with different casings - for instance, MyEvent and myevent - Customer.io will output the event name that corresponds with the profile. This throws an error if the event has not been sent recently (within the last ~30 days).
Syntax
{{event_name}}
layout.id
The numerical ID associated with the email layout you’ve used.
Syntax
{{layout.id}}
layout.name
The name assigned to the email layout you’re using.
Syntax
{{layout.name}}
manage_subscription_preferences_url
Renders a unique unsubscribe link for a customer and their email-address. This link takes a user to your subscription center where they can manage all of their preferences.
Syntax
{% manage_subscription_preferences_url %}
message.id
The numerical ID for a message action in the workflow. For example, an SMS action might have a
{{message.id}}
of 200. Note that this identifies the action in your workflow, not the individual delivery instances. Every SMS delivery generated from the action would have a different{{delivery_id}}
.For newsletters, the
message.id
is the value after templates in your URL. For example, themessage.id
here is21
https://fly.customer.io/env/109950/composer/newsletters/1/templates/21
.Syntax
{{message.id}}
message.journey_id
The ID for the path a person went through in a Campaign or API Triggered Broadcast workflow. You can use this value to trace message metrics back to a person’s path through a journey using the
journey.id
value sent in our Reporting Webhooks.Syntax
{{message.journey_id}}
message.name
The name you give your message in the workflow, like “Welcome to ACME!”
Syntax
{{message.name}}
message.preheader
For email messages only, if your message has a preheader value set, this tag echos it.
Syntax
{{message.preheader}}
message.subject
If your message has a subject, or the message subject is different from the message name, this tag echos it.
Syntax
{{message.subject}}
message.subscription_topic_ids
This returns the topic assigned in subscription preferences settings for Campaigns, API-triggered Broadcasts and Newsletters. If there is a message-level override of the topic (Campaigns and API-triggered Broadcasts only), it will return that topic over the setting at the Campaign or APITB level.
Syntax
{{message.subscription_topic_ids}}
message.type
This refers to the type of a particular workflow action. Possible values are:
email_action
,delay_seconds_action
,delay_time_window_action
,split_randomized_action
,webhook_action
,twilio_action
,slack_action
,attribute_update_action
,filter_match_delay_action
,grace_period_action
,push_action
,conditional_wait_action
,conditional_branch_action
,multi_split_branch_action
,random_cohort_branch_action,
exit_action
,static_seg_update_action
,collection_query_action
,create_event_action
,multi_lang_branch_action
,batch_update_action
,in_app_action
.Syntax
{{message.type}}
subscription_topic_name
Renders the name of the subscription topic assigned to a broadcast or campaign. If the topic is overriden for a message, this will render the message-level topic. Add a language parameter to translate the name, like
lang='pt'
. If the language doesn’t match a translation in your subscription center, customers will see the default language.Syntax
{% subscription_topic_name %}
unsubscribe
Renders the word unsubscribe and links to the customer’s unique unsubscribe URL.
Syntax
{% unsubscribe %}
unsubscribe_url
Renders a unique unsubscribe link for a customer and their email-address.
Syntax
{% unsubscribe_url %}
view_in_browser_url
Our default link that generates a web version of your email, personalized for each recipient. In general, these URLs look something like:
http://e.customeriomail.com/deliveries/....
Syntax
{% view_in_browser_url %}
Variables and Assignment
There are common variables you can reference within messages and elsewhere. These may be variables associated with a person, the event triggering a message workflow, or variables that you assign within your message from other values.
assign
Assign a value to a variable.
Syntax
{% assign var_name = 'value' %}
Input
{% assign favorite_food = 'apples' %}
Output
{{ favorite_food }}
capture
Captures contents and assigns them to a variable.
Input
{% capture about_me %}I am 28 and my favorite food is pasta.{% endcapture %}
Output
{{ about_me }}
customer attributes
You reference customer attributes—data associated directly with a person in Customer.io—in the
customer
scope. You may want to use customer attributes with anif
conditional so you have text to fallback to if a customer doesn’t have the attribute in question. You must usedefault
rather than checking for empty strings using== blank
or!= blank
.Syntax
{{customer.<attribute_name>}}
Example
{% if customer.first_name %} Hello {{ customer.first_name }}! {% else %} Hello to our nameless but valued customer! {% endif %}
event properties
If you trigger a campaign using an event, you can reference properties from the event that triggers your campaign in the
event
scope. You may want to use event properties with anif
conditional, so that you have text to fallback to if an event doesn’t have the property in question or your property doesn’t contain the value you expect. You must usedefault
rather than checking for empty strings using== blank
or!= blank
.Syntax
{{event.<property>}}
Example
{% if event.type == "purchase" %} Thanks for your purchase! {% else %} Thanks for using our service! {%endif%}
trigger properties
You can reference properties from the
data
object when you trigger a transactional message or API-trigger a broadcast using thetrigger
scope. This provides a convenient way to pass event data into transactional and broadcast templates. You may want to use trigger properties with anif
conditional, so that you have text to fallback to if your trigger data is incomplete or contains values you don’t expect. You must usedefault
rather than checking for empty strings using== blank
or!= blank
.Syntax
{{trigger.<data.property>}}
Example
{% if trigger.first_name %} Hi {{trigger.first_name | capitalize}} {% else %} Hi Buddy {%endif%}
Logical Operators
Logical operators determine the basic rules for evaluating true or false statements. You can also use
and
andor
operators to combine logic statements to evaluate multiple conditions.and
Evaluate a statement as true when both conditions are true.
Syntax
{% if condition1 and condition2 %} // do something if both condition1 and condition 2 are true {% endif %}
Example
{% if customer.name == "bugs bunny" and event.episode_start == true %} What's up doc? {% else %} That's all folks! {% endif %}
Does not equal (!=)
Use
!=
to check that two values are not equal to each other.Example
{% if customer.name != "daffy duck" %} Duck season! {% else %} Wabbit season! {%endif%}
equals (==)
Use
==
to check if two values are equal to each other.Example
{% if customer.name == "daffy duck" %} Wabbit season! {% else %} Duck season! {%endif%}
Greater than and Greater than or equal to (>, >=)
Use
>
to match when one value is greater than another. Use>=
to match when one value is greater than or equal to another.Syntax
{% if val1 > val2 %} {% comment %}do something if val1 is greater than val2{% endcomment %} {% endif %}
Example
{% if customer.acct_age_years > 1 %} Thanks for being with us these past years {% else %} Thanks for spending the last year with us! {% endif %}
Less than and less than or equal to (<, <=)
Use
<
to match when one value is less than another. Use<=
to match when one value is less than or equal to another.Syntax
{% if val1 < val2 %} {% comment %}do something if val1 is less than val2{% endcomment %} {% endif %}
Example
{% if customer.purchases < 5 %} Thanks for your support {% else %} Thanks for spending the last year with us! {% endif %}
or
Evaluate a statement as true when either of two conditions are true.
Syntax
{% if condition1 or condition2 %} {% comment %}do something if either condition1 and condition 2 are true{% endcomment %} {% endif %}
Example
{% if customer.name == "bugs bunny" or customer.group == "looney toons" %} That's all folks! {% else %} See you later! {% endif %}
Loops and Conditionals
Loop through an array of items or set conditions determining the content that you want to show.
case
Creates a set of conditions depending on a variable’s specific value—like a set of if, if-else, else conditions.
For example, you might use this to display different text depending on if a customer lives in a specific country.
Syntax
{% case condition %} {% when "value1" %} text when condition is value1. {% when "value2" or "value3" %} text when condition is value2 or value3 {% else %} text when condition does not match other conditions {% endcase %}
for loop
Repeatedly executes a block of code, most commonly to perform an operation for each item in an array. You might use a for loop in a message to provide a receipt of purchases (assuming an array of items in a purchase). Find more information about for loops and iteration here. For instance, you can use a break tag - {% break %} - to exit a loop.
Syntax
{% for item in array %} {{ item }} {% endfor %} {% comment %} You can use a break tag so the loop stops iterating. {% endcomment %} {% for i in (1..5) %} {% if i == 4 %} {% break %} {% else %} {{ i }} {% endif %} {% endfor %}
Example
{% comment %} You can output each item of the array. {% endcomment %} {% for member in members_of_band %} {{member}} {% endfor %} {% comment %} If the items are objects, you can output properties from each object. {% endcomment %} {% for product in event.products %} - {{ product.title }} x {{ product.price }} {% endfor %}
if
Executes a block of code if a condition is met. We execute the first true condition. Use
elsif
to add multiple ‘if’ conditions andelse
for the block of code you want to execute if all conditions are false. Use thedefault
filter to specify a fallback for when a variable does not exist instead of an if statement. Find more information about conditional liquid here.Example
{% if customer.lastEventType == "sports" %} You last attended a sports event, so we thought you might like to try out our leagues! Fill out our interest form below. {% elsif customer.lastEventType == "theater" %} You attended a theater event, so we thought you might like to try out our after show parties! Fill out our interest form below. {% elsif customer.lastEventType %} {% comment %} If the attribute exists and does not equal sports or theater, then this will render.{% endcomment %} You last attended {{customer.lastEventType}}; we'd love to hear what other offerings you'd like from us in the form below. {% else %} {% comment %} If the attribute does not exist, this will render. {% endcomment %} Let us know your interests in the form below so we can better serve you! {% endif %}
unless
Like an if conditional, but reversed: this tag executes a block of code if your condition is not met.
Example
{% unless product.name == "cool beans" %} The beans are not cool. {% endunless %}
Timestamps and Dates
Use these tags to get and manipulate dates and times.
add_day
Adds a day, or multiple days, to a given timestamp.
Syntax
{{ <unix_timestamp> | add_day: <int_days> }}
Example
{{ 1477430251 | add_day: 7 }}
add_month
Adds a month, or multiple months, to a given timestamp.
Syntax
{{ <unix_timestamp> | add_month: <int_months> }}
Example
{{ 1477430251 | add_month: 7 }}
add_year
Adds a year, or multiple years, to a given timestamp.
Syntax
{{ <unix_timestamp> | add_year: <int_years> }}
Example
{{ 1477430251 | add_year: 4 }}
countdown
Creates a countdown timer in your message, helping you alert your audience to how soon an event they’re interested in is set to happen. Countdown timers take several parameters. At the minimum, a countdown must include the font size, the foreground (font) color, the background color, and the time you want to count down to. You can only set this to count down from a static timestamp; you cannot set the time to count down based on a customer’s attribute, for instance.
The countdown timer cannot contain more than 60 frames. This limits the size of the animated GIF in your messages. So, if the resolution is set to seconds, the counter will stop after 60 seconds from when the person opens their message. The countdown image reloads when a person opens the message again, so the counter will always be relevant to the user’s current time, but it cannot count indefinitely.
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 (GMT)
. Remember to close the time in quotes, as the value includes a space. This field does not accept liquid variables.fg ✓ hex color The foreground (font) hexidecimal color bg ✓ hex color The background hexidecimal color apng boolean false Determines whether to show your countdown as a gif (default) or animated PNG. Note that some browsers/email clients don’t support apng images. 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
(Portugese),es
(Spanish), andfr
(French)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 Example
{% 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 %}
date
Format a date. Use the LiquidJS reference for more information about date filters including overriding the timezone. For a full list of regions, see our Supported timezone formats. You can also offset the timezone in minutes (360 = -6:00 hrs and -360 = +6:00 hrs).
Input
{{ 1483272000 | date: '%H:%M, %a, %b %d, %Y' }} {{ 1483272000 | date: '%a., %-m/%d at %I:%M %P %Z' }} {{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", "Asia/Colombo" }} {{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", 360 }}
Output
12:00, Sun, Jan 01, 2017 Sun., 1/01 at 12:00 pm UTC 1991-01-01T04:30:00 1990-12-31T17:00:00
date_to_long_string
Converts a date-time to include the full name of the month. You can convert this to ordinal time by adding ‘ordinal’, and you can follow that with ‘US’ if you’d like to lead with the month. By default, this displays the date in DD, M full name, YYYY.
Input
{{ site.time | date_to_long_string }} {{ site.time | date_to_long_string: "ordinal" }} {{ site.time | date_to_long_string: "ordinal", "US" }}
Output
07 November 2008 7th November 2008 November 7th, 2008
date_to_rfc822
Converts a date-time into the RFC-822 format used for RSS feeds.
Input
{{ site.time | date_to_rfc822 }}
Output
Mon, 07 Nov 2008 13:07:54 -0800
date_to_string
Converts a date-time to ordinal time. Add ‘US’ to lead with the month. By default, this displays the date in DD, M abbreviated, YYYY.
Input
{{ site.time | date_to_string }} {{ site.time | date_to_string: "ordinal" }} {{ site.time | date_to_string: "ordinal", "US" }}
Output
07 Nov 2008 07th Nov 2008 Nov 7th, 2008
date_to_xmlschema
Converts a date-time into ISO 8601, a format expected by XML schema.
Input
{{ site.time | date_to_xmlschema }}
Output
2008-11-07T13:07:54-08:00
event_timestamp
The UNIX timestamp when a particular event was performed. This time is different from the
now
tag! This throws an error if the event has not been sent recently (within the last ~30 days).Syntax
{{event_timestamp}}
now
The current time in UTC. You must format time with
date
.To modify date or time with
add
orsubtract
filters you must convertnow
into a unix timestamp first usingdate: '%s'
. If you use our built inadd_day
,add_month
, oradd_year
filters, you must convert the timestamp to an integer first. You can do this by using theplus
filter to add0
as shown in the second example below.Example
{{ 'now' | date: '%I:%M %p %B %d, %Y' }} {{ 'now' | date: '%s' | plus: 0 | add_day: 1 | date: '%I:%M %p %B %d, %Y'}}
Output
08:28 AM May 11, 2021 08:28 AM May 12, 2021
subtract_day
Subtracts a day, or multiple days, to a given timestamp.
Syntax
{{ <unix_timestamp> | subtract_day: <int_days> }}
Example
{{ 1477430251 | subtract_day: 7 }}
subtract_month
Subtracts a month, or multiple months, to a given timestamp.
Syntax
{{ <unix_timestamp> | subtract_month: <int_months> }}
Example
{{ 1477430251 | subtract_month: 2 }}
subtract_year
Subtracts a year, or multiple years, to a given timestamp.
Syntax
{{ <unix_timestamp> | subtract_year: <int_years> }}
Example
{{ 1477430251 | subtract_year: 4 }}
Array Filters
Liquid used to filter and manipulate arrays (lists of values). If your event or another incoming value is an array, you may iterate over the array with a
for
loop or grab items at a particular index of the array, to display information for your audience.compact
Removes
nil
(empty) values from an array.Input
{{ "mick, keith, nil, Charlie" | compact }}
Output
mick, keith, Charlie
concat
Concatenates arrays, joining them end to end. Accepts a single object or an array of objects. The resulting array contains all of the elements of both original arrays.
concat
does not remove duplicate entries unless you also use theuniq
filter.Input
{% assign stones = "mick, keith, ronnie, charlie" | split: ", " %} {% assign beatles = "john, paul, george, ringo" | split: ", " %} {% assign rolling_beatles = stones | concat: beatles %} {{ rolling_beatles | join: ", " }}
Output
mick, keith, ronnie, charlie, john, paul, george, ringo
cycle
In a ‘for’ loop, this tag loops through and outputs strings in the order they were passed.
Input
<ul>{% assign characters = "coyote,bugs,tweety" | split: "," %} {% for character in characters %} <li class="{% cycle 'odd', 'even' %}">{{ character }}</li> {% endfor %} </ul>
Output
<ul> <li class='odd'>coyote</li> <li class='even'>bugs</li> <li class='odd'>tweety</li> </ul>
find
Returns the first object in an array for which the queried attribute has the given value or returns nil if no item in the array satisfies the given criteria.
Input
{{ customer.purchases | find: "type", "kitchen" | json }}
Output
{"date":"1726589206","title":"utensils","type":"kitchen"}
find_exp
Returns the first object in an array for which the given expression evaluates to true or returns nil if no item in the array satisfies the evaluated expression.
Input
{{ members | find_exp: "item", "item.graduation_year == 2014" | json }}
Output
{"graduation_year":2014,"name":"John"}
first
Returns the first element of the array.
Input
acme.characters = ["Wile E Coyote", "Road Runner"] {{ acme.characters | first }}
Output
Wile E Coyote
group_by
Groups an array’s items by a given property.
Input
{% assign groups = customer.purchases | group_by: "type" %} {% for group in groups %} {{group.name | capitalize}} {% for item in group.items %} - {{ item.title }} {% endfor %} {% endfor %}
Output
Bathroom - shower curtain - body soap Kitchen - forks - spoons - knives
group_by_exp
Groups an array’s items using a Liquid expression.
Input
{% assign groups = customer.purchases | group_by_exp: "item", "item.type contains 'kitchen'" %} {% for group in groups %} {% if group.name == true %} You bought some kitchen supplies from us in the past year: {% for item in group.items %} - {{item.title}} {% endfor %} {% endif %} {% endfor %}
Output
You bought some kitchen supplies from us in the past year: - forks - spoons - knives
join
Joins the elements of an array with the character passed as the parameter.
Input
acme.characters = ["Wile E Coyote", "Road Runner"] {{ acme.characters | join: ', ' }}
Output
Wile E Coyote, Road Runner
json_array_uniq
Evaluates an array of JSON objects and outputs an array containing all the unique objects based only on the value of the passed-in key name. Use the filter
to_json
if a string is the desired output.Input
{{ customer.arrayOfColorObjects | concat: customer.arrayOfColorObjectsWithDuplicationsAndNew | json_array_uniq: 'name' | to_json }}
Output
[{"color":"brown","name":"coyote"},{"color":"black","name":"bugs"},{"color":"yellow","name":"tweety"},{"color":"black","name":"daffy"}]
last
Returns the last element of the array.
Input
acme.characters = ["Wile E Coyote", "Road Runner"] {{ acme.characters | last }}
Output
Road Runner
limit
Return a set number of values from an array or string.
Input
{% assign beatles = "john, paul, george, ringo" | split: ", " %} {{ beatles | limit: 2 | join: ", " }}
Output
john, paul
map
Creates an array of values by extracting the values of a property in an object. You can output your new characters in a ‘for’ loop.
Input
Array of objects: [{"name":"coyote"},{"name":"bugs"},{"name":"tweety"}]" {% assign names = customer.characters | map: 'name' %}
Output
coyote, bugs, tweety
pop
Removes the last element from the array.
Input
{% assign fruits = "apples, oranges, peaches" | split: ", " %} {% assign everything = fruits | pop %} {% for item in everything %} - {{ item }} {% endfor %}
Output
- apples - oranges
push
Adds an element to an array.
Input
{% assign fruits = "apples, oranges" | split: ", " %} {% assign everything = fruits | push: "peaches" %} {% for item in everything %} - {{ item }} {% endfor %}
Output
- apples - oranges - peaches
remove
Remove an element from an array. The array can contain objects of any type.
Input
{% assign pl = collection.products | remove: collection.products[0] %} - {{ collection.products.size }} - {{ pl.size }}
Output
- 2 - 1
reverse
Reverses the order of the items in an array.
Input
{% assign my_array = "apples, oranges, peaches, plums" | split: ", " %} {{ my_array | reverse | join: ", " }}
Output
plums, peaches, oranges, apples
shift
Removes the first element from the array.
Input
{% assign fruits = "apples, oranges, peaches" | split: ", " %} {% assign everything = fruits | shift %} {% for item in everything %} - {{ item }} {% endfor %}
Output
- oranges - peaches
size
Returns the number of characters (the size) of a string (in characters) or the number of elements in an array.
Input
{{ "That's all, folks!" | size }}
Output
18
sort
Sorts the elements of an array by an attribute of an element in that array. Usually used with a ‘for’ loop. The order of the sorted array is case-sensitive! This filter will not reorder any list/array that contains null values. See Sorting looped data for an advanced example.
Input
{% assign beatles = "paul, john, ringo, george" | split: ", " %} {{ beatles | sort | join: ", " }}
Output
george, john, paul, ringo
sort_natural
Sort the items in an array in case-insensitive order.
Input
{{ "mick, keith, Charlie, Ronnie" | sort_natural }}
Output
Charlie, keith, mick, Ronnie
sum
The
sum
filter aggregates numbers. Every value is cast to a number. Unlike with legacy liquid,sum
does not concatenate numbers, strings, or booleans. You can specify an object property to sum, as shown in the third example below.Input
{% assign nums = '1,2,3' | split: ',' %} {{ nums | sum }} {% assign letters = 'a,b,c' | split: ',' %} {{ letters | sum }} {{ cart.products | sum: 'total_number' }} {% comment %} where `total_number` includes milk,cheese,eggs {% endcomment %} {{ purchase.products | sum }} {% comment %} where `products` includes true,false {% endcomment %}
Output
6 0 3 1 {% comment %} counts the number of trues, would also aggregate numbers alongside booleans {% endcomment %}
uniq
Removes duplicate elements in an array.
Input
{% assign my_array = '"lions", "tigers", "bears", "bears", "lions"' %} {{ my_array | uniq | join: ", " }}
Output
lions, tigers, bears
unshift
Adds an element to the beginning of the array.
Input
{% assign fruits = "oranges, peaches" | split: ", " %} {% assign everything = fruits | unshift: "apples" %} {% for item in everything %} - {{ item }} {% endfor %}
Output
- apples - oranges - peaches
where
Creates an array including only the objects with a given property value, or any “truthy” value by default.
Input
All Players: {% for player in collection.players %} - {{ player.last_name }} {% endfor %} Baseball Players: {% assign baseball_players = collection.players | where: "sport", "baseball" %} {% for player in baseball_players %} - {{ player.last_name }} {% endfor %} ---------------------------- All products: {% for product in collection.products %} - {{ product.title }} {% endfor %} {% assign available_products = collection.products | where: "available" %} Available products: {% for product in available_products %} - {{ product.title }} {% endfor %}
where_exp
Selects all the objects in an array where the expression is true. You provide two items separated by a comma: the key you want to match on and the value you want to match.
Input
All products: {% for product in customer.products %} - {{ product.title }} {% endfor %} {% assign kitchen_products = customer.products | where_exp: "item", "item.size > 30 and item.type == 'kitchen'" %} Kitchen products: {% for product in kitchen_products %} - {{ product.title }} {% endfor %}
where_not
Creates an array of items that do not match a given property value, or any “falsey” value by default. When using
where_not
, you provide two items separated by a comma: the key you want to match on and the value you want to match.Input
All players: {% for player in collection.players %} - {{ player.last_name }} {% endfor %} Not baseball players: {% assign not_baseball_players = collection.players | where_not: "sport", "baseball" %} {% for player in not_baseball_players %} - {{ player.last_name }} {% endfor %}
Output
All players: - Posey - Maradona - Montana - Gretzky - Jordan Not baseball players: - Maradona - Montana - Gretzky - Jordan
Number and Currency Filters
These are tags and filters that manipulate incoming number, integer, and timestamp values.
Some tags, like the
currency
andformat_number
, take an optional localization parameter, formatting the output for a specific locale. These tags use the format{{ 10 | currency: "en-us" }}
, which would output$10.00
.A list of locales and currency codes
We support the following localization values:
af, ar, az, be, bg, bn, bs, ca, cs, cy, da, de-AT, de-CH, de-DE, de, dz, el-CY, el, en-AU, en-CA, en-CY, en-GB, en-IE, en-IN, en-NZ, en-TT, en-US, en-ZA, en, eo, es-419, es-AR, es-CL, es-CO, es-CR, es-EC, es-ES, es-MX, es-NI, es-PA, es-PE, es-US, es-VE, es, et, eu, fa, fi, fr-CA, fr-CH, fr-FR, fr, gl, gsw-CH, he, hi-IN, hi, hr, hu, id, is, it-CH, it, ja-JP, ja, ka, kk, km, kn, ko, lb, lo, lt, lv, mg, mk, ml, mn, mr-IN, ms, na, nb, ne, ng, nl, nn, oc, or, pa, pl, pt-BR, pt, rm, ro, ru, sc, sd, sk, sl, sn, sq, sr, st, sv-FI, sv-SE, sv, sw, ta, te, th, tl, tn, tr, tt, ug, uk, ur, uz, vi, wo, za, zh-CN, zh-HK, zh-Hant-MO, zh-MO, zh-TW, ao, cd, ci, cm, eg, gh, ke, ls, ly, ma, mu, mw, mz, sz, tz, zm
We support the following currency codes:
'AED','AFN','ALL','AMD','ANG','AOA','ARS','AUD','AWG','AZN','BAM','BBD','BDT','BGN','BHD','BIF','BMD', 'BND','BOB','BRL','BSD','BTN','BWP','BYN','BZD','CAD','CDF','CHF','CLP','CNY','COP','CRC','CUC','CUP', 'CVE','CZK','DJF','DKK','DOP','DZD','EGP','ERN','ETB','EUR','FJD','FKP','GBP','GEL','GHS','GIP','GMD', 'GNF','GTQ','GYD','HKD','HNL','HRK','HTG','HUF','IDR','ILS','INR','IQD','IRR','ISK','JMD','JOD','JPY', 'KES','KGS','KHR','KMF','KPW','KRW','KWD','KYD','KZT','LAK','LBP','LKR','LRD','LSL','LYD','MAD','MDL', 'MGA','MKD','MMK','MNT','MOP','MRU','MUR','MVR','MWK','MXN','MYR','MZN','NAD','NGN','NIO','NOK','NPR', 'NZD','OMR','PAB','PEN','PGK','PHP','PKR','PLN','PYG','QAR','RON','RSD','RUB','RWF','SAR','SBD','SCR', 'SDG','SEK','SGD','SHP','SLE','SLL','SOS','SRD','SSP','STN','SVC','SYP','SZL','THB','TJS','TMT','TND', 'TOP','TRY','TTD','TWD','TZS','UAH','UGX','USD','UYU','UZS','VES','VND','VUV','WST','XAF','XCD','XDR', 'XOF','XPF','XSU','YER','ZAR','ZMW','ZWL'
abs
Returns the absolute value of a number.
Input
{{ 3.14 | abs }}
Output
3.14
ceil
Rounds a number up to the nearest integer.
Input
{{ 3.14 | ceil }}
Output
4
currency
Converts an integer to currency. This filter accepts two arguments for currency and locale. When no arguments are passed to the filter, the currency code defaults to USD. When only a locale is passed, we base the currency on the closest match to the locale. See above for a list of specific locales and currencies. We only accept a currency code after a locale is specified.
Input
{% comment %} no arguments: {% endcomment %} {{ 1234567.896 | currency }} {% comment %} only locale: {% endcomment %} {{ 1234567.896 | currency: 'en-GB' }} {% comment %} locale and currency code: {% endcomment %} {{ 1234567.896 | currency: 'en', 'EUR' }}
Output
$1,234,567.90 £1,234,567.90 €1,234,567.90
floor
Rounds a number down to the nearest integer.
Input
{{ 3.14 | floor }}
Output
3
format_number
Format a number with a delimiter. This filter also takes an optional localization parameter to format a number for a specific locale.
NOTE: This replaces the former
number_with_delimeter
filter.Input
{{ 10000 | format_number }} {{ 123456.78 | format_number: "fr" }}
Output
10,000 123 456,78
random
Generates a random number between 0 and an integer you specify.
Example
{% random 100 %}
round
Rounds a number up or down to the nearest integer, or to a decimal place you specify.
Input
{{ 4.32 | round }} {{ 4.32 | round: 1 }}
Output
4 4.3
rounded_currency
Rounds a number to the nearest whole integer and formats it to a currency. Accepts both a locale and currency code. We only accept a currency code after a locale is specified. See above for a list of specific locales and currencies.
Input
{% comment %} no arguments: {% endcomment %} {{ 1234567.896 | rounded_currency }} {% comment %} only locale: {% endcomment %} {{ 1234567.896 | rounded_currency: 'en-GB' }} {% comment %} locale and currency code: {% endcomment %} {{ 1234567.896 | rounded_currency: 'en', 'EUR' }}
Output
$1,234,568 £1,234,568 €1,234,568
Math Filters
Filters that perform math operations on incoming number or integer values. With the legacy liquid version, if you encounter an error with negatives while using math filters, wrap the negative numbers in quotes.
at_least
Limits a number to a minimum value.
Input
{{ 41 | at_least: 42 }}
Output
42
at_most
Limits a number to a maximum value.
Input
{{ 100 | at_most: 99 }}
Output
99
divided_by
Divides a number by another number.
Input
{{ 10 | divided_by: 2.5 }} {{ 10 | divided_by: 4 }} {{ 10 | divided_by: 4.0 }}
Output
4 2.5 2.5
minus
Subtracts a number from another number.
Input
{{ 10 | minus: 1 }}
Output
9
modulo
Returns the remainder of division. The output will always be a positive number, even when there’s a negative number as input.
Input
{{ 3 | modulo: 2 }}
Output
1
plus
Adds a number to another.
Input
{{ 10 | plus: 1 }}
Output
11
times
Multiplies a number by another number.
Input
{{ 5 | times: 2 }} {{ 10 | times: 2.5 }}
Output
10 25
String Filters
The following filters manipulate strings in templates. You might use these to truncate or set the case of strings you reference from other places, to humanize your messages for recipients.
append
Adds a string to the end of another string.
Input
{{ "What's all the hubbub, " | append: "bub?" }}
Output
What's all the hubbub, bub?
array_to_sentence_string
Converts a list of data into a commma-delineated list. Use in tandem with the
split
filter.Input
{{ customer.groceries | split:"," | array_to_sentence_string }} {{ customer.groceries | split:"," | array_to_sentence_string: "or" }}
Output
cherry, kiwi, and passion fruit cherry, kiwi, or passion fruit
base64
Base64-encodes a string.
Input
{{ 'Hello, world!' | base64 }}
Output
SGVsbG8sIHdvcmxkIQ==
base64_decode
Decode a base64-encoded string.
Input
{{ "Zm9vLmJhcg==" | base64_decode }}
Output
foo.bar
base64_encode
Base64-encode a value.
Input
{{ "foo.bar" | base64_encode }}
Output
Zm9vLmJhcg==
base64_url_safe_decode
Decode a string from URL-safe Base64.
Input
{{ "Zm9vLmJhcg" | base64_url_safe_decode }}
Output
foo
base64_url_safe_encode
Encode a string into URL-safe Base64. To produce URL-safe Base64, this filter uses
-
and_
in place of+
and/
.Input
{{ "foo" | base64_url_safe_encode }}
Output
Zm9vLmJhcg
capitalize
Capitalize the first character in a string.
Input
{{ "hello world" | capitalize }}
Output
Hello world
cgi_escape
CGI escapes a string for use in a URL.
Input
{{ "overview: account" | cgi_escape }}
Output
overview%3A+account
contains
Finds a substring inside a string, or the presence of a string in an array of strings. This filter only works with strings; you cannot use it to search for an object in an array of object.
Syntax
{% if product.description contains 'lorem ipsum' %} You might also be interested in Fillerama or Office Ipsum. {% endif %}
downcase
Converts a string to lower case.
Syntax
{{ 'STRING' | downcase }}
Input
{{ "ACME" | downcase }}
Output
acme
escape
Escaping a string removes special characters. To encode a URL, use
url_encode
instead.Input
{{ "win+help@customer.io" | escape }}
escape_once
Escapes or encodes a string, but doesn’t include already-escaped characters.
Input
{{ "1 < 2 & 3" | escape_once }}
Output
1 < 2 & 3
hex_base64
Returns a base64 encoding of a hex digest, like ones returned by the
hmac_sha256
filter.Input
{{ "Customer.io" | hmac_sha256: "some_key" | hex_base64 }}
Output
bd23cyOCFrzicxM7w/ahKoJPQd0YTQlFLwXHZZ2ufVc=
hmac_sha1
Converts a string into an hmac_sha1 hash.
Input
{{ "Customer.io" | hmac_sha1: "some_key" }}
Output
2bdf556c9a75766f258d1e2824f6d0e31d1beedc
hmac_sha256
Converts a string into an hmac_sha256 hash.
Input
{{ "Customer.io" | hmac_sha256: "some_key" }}
Output
6dddb773238216bce273133bc3f6a12a824f41dd184d09452f05c7659dae7d57
lstrip
Strips all whitespace, including tabs, spaces, and newlines, from the left side of a string.
Input
text{{ " Customer.io " | lstrip }}text
Output
textCustomer.io text
md5
Converts a string into an md5 hash.
Input
{{ "Customer.io" | md5 }}
Output
d52b6a207bf5255c05b1d0056230617e
newline_to_br
Replaces newline with an HTML line break. input: See this example for output.
Input
<br /> Customer.io<br /> liquid<br />
normalize_whitespace
Replaces any occurrence of whitespace with a single space.
Input
{{ "a \n b" | normalize_whitespace }}
Output
a b
number_of_words
Counts the number of words in text. Learn about counting Chinese-Japanese-Korean characters.
Input
{{ "Welcome to Customer.io!" | number_of_words }}
Output
3
pluralize
Outputs the singular or plural version of a string based on the value of a number. The first parameter is the singular string and the second parameter is the plural string.
Syntax
{{ int-val | pluralize 'singular', 'plural'}}
Input
{{ event.item_count | pluralize: 'item', 'items' }}
Output
3 items
prepend
Adds a string to the beginning of another string.
Input
{{ "Sufferin' succotash!" | prepend: "Sylvester: " }}
Output
Sylvester: Sufferin' succotash!
remove_first
Removes the first occurrence of a value from a string.
Input
{{ "folks that's all, folks!" | remove_first: "folks" }}
Output
that's all folks!
remove_last
Remove the last occurence of a string within a substring.
Input
{{ "foobarbar" | remove_last: "bar" }}
Output
foobar
remove
Removes a value from a string.
Input
{{ "And that's all, folks!" | remove: ", folks" }}
Output
And that's all!
replace
Find and replace values within a string. The first argument represents the value you want to replace, and the second argument is the replacement.
Syntax
{{ "String you want to replace values in" | replace: "find-str", "replace-str" }}
Input
{{ "Coyotes never catch roadrunners!" | replace: "never", "always" }}
Output
Coyotes always catch roadrunners!
replace_first
Find and replace the first match in a string. The first argument represents the value you want to replace, and the second argument is the replacement.
Syntax
{{ "String you want to replace values in" | replace_first: "find-str", "replace-str" }}
Input
{{ "roller rocket roller skates" | replace_first: "roller", "awesome" }}
Output
awesome rocket roller skates
replace_last
Replace the last occurence of a string within a substring.
Input
{{ "foobarbar" | replace_last: "bar", "foo" }}
Output
foobarfoo
rstrip
Strips all whitespace, including tabs, spaces, and newlines, from the right side of a string.
Input
text{{ " Customer.io " | rstrip }}text
Output
text Customer.iotext
sha1
Converts a string into a sha1 hash.
Input
{{ "Customer.io" | sha1 }}
Output
c197ff0ae0a41983362f35ca972c544061c54d4c
sha256
Converts a string into a sha256 hash.
Input
{{ "Customer.io" | sha256 }}
Output
6dddb773238216bce273133bc3f6a12a824f41dd184d09452f05c7659dae7d57
slice
Returns the character located at the index specified in the first argument. You can also provide a second argument indicating the length of the string you want to return (if you want to return multiple characters).
If the first argument is a negative number, the index is begins from the end of the string.
Syntax
{{ "string" | slice: <req, index of char>, <optional, length of result> }}
Input
{{ "Customer.io" | slice: 3 }} {{ "Customer.io" | slice: 3, 3 }} {{ "Customer.io" | slice: '-4', 3 }}
Output
t tom r.i
slugify
Converts a string into a lowercase URL slug. Set the mode to specify how characters and spaces should be converted. Then set a boolean value of
true
if you want to retain the original casing of the string. By default, theslugify
filter replaces spaces and non-alphanumeric characters with dashes and lowercases all letters.mode replaces “none” no characters “raw” spaces “default” spaces and non-alphanumeric characters “pretty” spaces and non-alphanumeric characters except for ._~!$&’()+,;=@ “ascii” spaces, non-alphanumeric, and non-ASCII characters “latin” like default, except Latin characters are first transliterated (e.g. àèïòü to aeiou) Input
{{ "The _config.yml file" | slugify }} {{ "The _config.yml file" | slugify: "pretty" }} {{ "The _cönfig.yml file" | slugify: "ascii" }} {{ "The cönfig.yml file" | slugify: "latin" }} {{ "The cönfig.yml file" | slugify: "latin", true }}
Output
the-config-yml-file the-_config.yml-file the-c-nfig-yml-file the-config-yml-file The-config-yml-file
split
Divides an input string into an array using a separator you define. This filter is often used with a for loop.
Input
{% assign rolling_stones = "Mick, Keith, Ronnie, Charlie" | split: ", " %} {% for member in rolling_stones %} {{ member }} {% endfor %}
strip
Strips all whitespace, including tabs, spaces, and newlines, from the left and right side of a string.
Input
text{{ " Customer.io " | strip }}text
Output
Customer.io
strip_html
Removes HTML characters from a string.
Input
{{ "Eh, what's <i>up</i>, <b>Doc</b>?" | strip_html }}
Output
Eh, what's up, Doc?
strip_newlines
Removes line breaks (\n) from a string.
Example
{{ product.description | strip_newlines }}
titlecase
Converts a string to title case.
Syntax
{{ 'string' | titlecase }}
Input
{{ "rocket roller skates" | titlecase }}
Output
Rocket Roller Skates
truncate
Shortens a string to the specified number of characters, adding an ellipsis if the string is longer than the value provided.
Input
{{ "I knew I shoulda taken that left turn at Albuquerque." | truncate: 20 }}
Output
I knew I shoulda ...
truncatewords
Shortens a string to a specified number of words, rather than characters, and adds an ellipsis if the string contains more words than the value provided.
Input
{{ "I knew I shoulda taken that left turn at Albuquerque." | truncatewords: 8 }}
Output
I knew I shoulda taken that left turn...
upcase
Converts a string to upper case.
Syntax
{{ 'string' | upcase }}
Input
{{ 'acme' | upcase }}
Output
ACME
uri_escape
This filter percent encodes special characters in a URI that are not reserved.
Input
{{ "https://example.com/?q=foo, \bar?" | uri_escape }}
Output
https://example.com/?q=foo,%20%08ar?
url_decode
Decodes a string that has been encoded as a URL or has been modified by
url_encode
.Input
{{ "%27Customer.io+is+great%27" | url_decode }}
Output
Customer.io is great
url_encode
Escapes/encodes URL-unsafe characters in a string.
Input
{{ "cool.person@example.com" | url_encode }}
Output
cool.person%40example.com
xml_escape
Escapes text for use in XML. If you use this filter in HTML messages (i.e. not webhooks), the final output may differ due to HTML processing.
Input
{{ "Have you seen \'Learn the basics: video guide\'?" | xml_escape }}
Output
Have you read 'James & the Giant Peach'?
Miscellaneous
These are tags that you can use to escape liquid rendering or escape rendering all together.
comment
This tag doesn’t show its contents, providing a way for you to leave notes inside templates for other members of your organization.
Syntax
{% comment %} Don't display me! {% endcomment %}
default
Set a default value when one does not exist. You cannot use ==/!= operators for nil/empty check. You must use
default
rather than checking for empty strings using== blank
or!= blank
.Input
{{ product_color | default: "red" }} {{ product_price | default: 2.99 }}
Output
red 2.99
from_json
This filter lets you create values from JSON.
from_json
parses string-encoded (or ‘stringified’) JSON so you can reference its values with liquid. Note that you don’t need this filter for the JSON-encoded values of people, events, or objects; they are already automatically parsed.Example
{% assign var = '{"key": "value", "number": 123, "boolean": true}' | from_json %} {{ var.key }} {{ var.number }} {{ var.boolean }}
Input
{% assign fruit = '{"type": "kiwi", "quantity": 2, "sweet": true}' | from_json %} {{ fruit.type }} {{ fruit.quantity }} {{ fruit.sweet }} {% assign greeting = '[{"greeting": "hello" }, {"greeting": "hey" }, {"greeting": "hi" }, {"greeting": "howdy" }]' | from_json %} {{ intro[0].greeting }} {{ intro[1].greeting }} {{ intro[2].greeting }} {{ intro[3].greeting }}
Output
kiwi 2 true hello hey hi howdy
generate_uuid
Generate a UUID.
Example
{% generate_uuid %}
json
Converts values to a JSON-encoded string (same as using
jsonify
). An additionalspace
parameter can be specified to format/prettify the JSON.Input
{% assign arr = "foo bar coo" | split: " " %} {{ arr | json: 4 }}
Output
[ "foo", "bar", "coo" ]
raw
Temporarily disables Liquid processing. You might use this to escape tag processing if you use a conflicting syntax or you want to show raw liquid syntax in your message."
Example
{% raw %} {{This}} is displayed exactly as typed. {% endraw %}
to_json
Outputs the json representation of the input. For example,
{{ customer | to_json }}
sends all your customer data into a JSON variable.Example
{{ customer | to_json }}
whitespace control
You can remove whitespace before and/or after a tag using hyphens.
Input
{% assign username = "Charlie" %} Hello, {{ username -}} !
Output
Hello, Charlie!