Personalizing Your Messages With Liquid
  • 8 Minutes To Read

Personalizing Your Messages With Liquid

With, you can use the Liquid templating language to personalize your messages. Any part of your message (or in the cases of rich-text emails, your Layout) can contain Liquid.

Personalization variables supported by liquid

There are three types of variables you can use to personalize messages for your audience: attributes and event properties.

  • attributes use the customer scope—{{customer.<attribute_name>}}
  • event properties from the data object in an event that triggers your campaign use the event scope—{{event.<>}}
  • trigger properties from the data object in a transactional message or API-triggered broadcast use the trigger scope—{{trigger.<>}}

You can reference attributes (using the customer scope) in any message. You can only use event properties in a campaign that uses a trigger event and trigger properties in an API-triggered broadcast or transactional message.

When you create a message, we show a Sample data section with representative attribute and event or trigger property examples that you might use to personalize your message.

Basic user attributes

If you want to include a dynamic customer attribute, you'll want to include the tag that references that attribute. For example, if someone has an attribute on their profile called first_name, the tag would be:

{{ customer.first_name }}

As you can see, anything you've included as a customer attribute should start with customer. before your attribute name. If you've got country, for example, it'd be {{ }}

Event data

Let's use a simple example: imagine one of your customers bought a pair of socks, and you want to send them a receipt for those socks. To do that, you send a purchase event, with data for the socks they bought, and how much those socks cost. Say the data that received looks like this (Javascript):

_cio.track("purchase", { price: "23.45", product: "socks" });

You could then use that data in your message content (be it email, push, or anything else) like this:

You just bought {{ event.product }} for {{ event.price }}!

That would output "You just bought socks for 23.45!" You'll see that though the event is named "purchase", you still use the notation event to reference it in

Note that event data is only accessible in event triggered campaigns

If you need more detailed technical information about sending events, it's in our API docs.

Trigger Properties

When you send an API-triggered broadcast or a transactional message, you can reference properties from the trigger as {{trigger.<property>}}.

For example, if your transactional message is designed to send shipping updates, you might include information about the item(s) that you're shipping to your audience and when they'll arrive, like this:

Your {{trigger.product}} has shipped! It will arrive in {{trigger.minShipTime}} to {{trigger.maxShipTime}} {{trigger.unitOfTime}}.

And you could expect that to output, "Your trampoline as shipped! It will arrive in 4 to 6 weeks."

See API-triggered broadcasts and transactional messages for more information.

Filters and tags

Filters and tags make up the foundations of Liquid, and there are a number of them that you can use. In the first-name example, if you wanted to make sure it was capitalized, add a capitalize filter to the tag:

{{ customer.first_name | capitalize }}

If the field was full_name and you wanted to include only the first word/name, you could use:

{{ customer.full_name | split: " " | first }}

Check out the other filters and tags (and how to write them) in our complete Liquid documentation.

More examples: what else can you do?

Note: If you are using our drag-and-drop email editor to add user data, if you have code which involves logical or comparison operators (&, >, or <), use our "Add Liquid" option in the text dropdown, rather than typing manually:


Messages will fail if you attempt to use data that does not exists from the source you are pulling it from. To prevent such errors, you will need to decide how to handle cases when such data is not available.

For example, if only a subset of your People have a value for an attribute named plan_name then you can create a fall back like:

{% if customer.plan_name != blank %}
  You are currently on our {{ customer.plan_name | capitalize }} plan.
{% else %}
  Please choose a plan.
{% endif %}

That will show, "You are currently on our XYZ plan." for People who have a value for their plan_name attribute and "Please choose a plan." for People who do not have a value for their plan_name attribute.

Alternatively, if you would rather not show anything for People who do not have a value for their plan_name attribute you can just leave off the else statement like this:

{% if customer.plan_name != blank %}
  You are currently on our {{ customer.plan_name | capitalize }} plan.
{% endif %}

That will show, "You are currently on our XYZ plan." for People who have a value for their plan_name attribute and nothing at all for People who do not have a value for their plan_name attribute.


You can include attributes within links as well, in order to send your users to a custom page.


<a href="{{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.


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 %m/%d/%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 }}


  1. You can get the current epoch time with 'now' | date: "%s". %s is a formatting option.
  2. The customer.trial_end date is in epoch time.
  3. 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:

{{}} <{{}}>

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 lanuage:

{{'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 %}
{% endif %}

Using data containing whitespace

We recommend adding data to 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"] }}

Filtering out default data or specific data

{% if customer.first_name contains 'Visitor' %}
	{% else %}{{ customer.first_name | capitalize }}
{% endif %}


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 might look like in Javascript:

  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.price }} <br/>
{% endfor %}

This will loop through your data and output the items that were passed in with the purchase event.

Was This Article Helpful?