All Collections
Email Templates
Advanced Email Personalization with Liquid
Advanced Email Personalization with Liquid

How to use Liquid to create even more personalized emails with conditional content, filters, and more.

Updated over a week ago

This is part 2 of a 2-part series about personalizing emails with Liquid:

  1. Advanced Email Personalization with Liquid — 📍You are here!

☝️PLEASE NOTE: This is an advanced article that focuses on providing Liquid use cases & code samples for your reference. Please refer to our this tutorial for the basics of Liquid implementation, how to test out your personalized content, and frequently asked questions!

Take your email personalization to another level with conditional content and more.

In this article, we'll cover some more advanced applications of Liquid that are available for you to use in your ConvertKit emails.

Conditional content

You can use Liquid to show different content based on whether or not a subscriber has a particular tag, like this:

{% if subscriber.tags contains "Purchased course" %}

This will show if the subscriber has the "Purchased course" tag.

{% else %}

This will show if the subscriber does not have the "Purchased course" tag.

{% endif %}

Just replace the name of your tag enclosed between the quotes (if your tag’s name has a quotation mark in it, make sure you enclose it in single-quotes instead), and then adjust both versions of the content accordingly.

‘Else if’ statements

You can get a little more sophisticated by using ‘else if’ statements. This allows you to include an ‘else’ version of the content at the end, which will show only if none of the above conditions apply:

{% if subscriber.tags contains "Purchased course" %}

This will show if the subscriber has the "Purchased course" tag.

{% elsif subscriber.tags contains "Purchased ebook" %}

This will show if the subscriber has the "Purchased ebook" tag.

{% else %}

This will show if the subscriber has neither the "Purchased course" nor "Purchased ebook" tags.

{% endif %}

☝️NOTE: With elsif statements, the first positive match will apply and that content will be shown, even if there’s another positive match lower down. If you want certain conditions to take priority over others, ensure they’re in order of precedence from top to bottom.


You can also nest if statements inside one another. Here’s an example:

{% if subscriber.tags contains "Past purchaser" %}

{% if subscriber.tags contains "Purchased course" %}

Subscriber has the "Past purchaser" and "Purchased course" tags.

{% elsif subscriber.tags contains "Purchased ebook" %}

Subscriber has the "Past purchaser" and "Purchased ebook" tags.

{% else %}

Subscriber has the "Past purchaser" tag, but neither the "Purchased
course" nor "Purchased ebook" tags.

{% endif %}

{% else %}

Subscriber does not have the "Past purchaser" tag.

{% endif %}

In the above example, the code will first check whether the subscriber has the “Past purchaser” tag.

If they do have the “Past purchaser tag”, then it’ll proceed to check whether they also have the “Purchased course” tag. If they don’t, it’ll then check whether they also have the “Purchased ebook” tag. The first positive match’s content will be shown, but if they have neither of those, then the content in the first else statement will be shown.

If they don’t have the “Past purchaser tag”, then the content in the second else statement will be shown (regardless of whether they have the “Purchased course” and/or “Purchased ebook” tags).

‘Unless’ statements

If you only want to show certain content if your subscriber doesn’t have a particular tag, you can simplify the code by using an unless statement instead, as follows:

{% unless subscriber.tags contains "Purchased course" %}

The subscriber doesn’t have the "Purchased course" tag.

{% endunless %}

URL encoding

If you want to use Liquid shortcodes in your URLs, you’ll want to include the url_encode filter, which will convert any URL-unsafe characters to their percent-encoded counterparts:

{{ subscriber.email_address | url_encode }}

The above would convert the email address [email protected] to the URL-safe

Name filters

In addition to the default fallback filter (more on that here), there are some additional Liquid filters that can come in handy, especially when applied to first name values.


You can ensure that only the first letter of the first name field is capitalized by using the capitalize filter:

{{ subscriber.first_name | capitalize }}

This would convert ‘jughead’ to ‘Jughead’.


Some subscribers might enter both their first and last name in the first name field. To override that and only use the first word they entered as their first name, you can use the truncatewords filter:

{{ subscriber.first_name | truncatewords: 1, "" }}

This would truncate ‘Jughead Jones’ to just its first word, ‘Jughead’.

Stripping whitespace

Liquid’s strip filter will remove any leading and trailing spaces from a variable (it won’t affect spaces in between words):

{{ subscriber.first_name | strip }}

This would output the first name value of ‘ Jughead ’ to just ‘Jughead’.

Combining filters

Liquid filters can also be used in tandem! For example, you can simultaneously truncate and capitalize the first name value by combining the truncatewords and capitalize filters as follows:

{{ subscriber.first_name | truncatewords: 1, "" | capitalize }}

The above code would convert the first name value of ‘jughead jones’ to ‘Jughead’.

You can even combine them with the default filter to also include a fallback option, as follows:

{{ subscriber.first_name | default: "friend" | truncatewords: 1, "" | capitalize }}

☝️NOTE: Be aware that any subsequent filters will also be applied to the default fallback value. For example, in the case of no first name value, the above code would actually result in “Hello Friend!”, since the capitalize filter will also act upon the fallback value.

⚠️ Potential shortcomings of name filters

The addition of filters to the {{ subscriber.first_name }} shortcode may prevent the [FIRST NAME GOES HERE] text from rendering correctly in preview emails, but you can still test out your code using the ‘Preview as a subscriber’ feature.

It’s also worth noting that some first names intentionally contain more than one word and/or capital letter. As a result, these filters could potentially result in unwanted edits to valid first names.

For example, use of the truncatewords and capitalize filters in tandem would change the first name values of “Mary Anne” and “McKayla” to “Mary” and “Mckayla”, respectively.

We provide the filters above for your knowledge, but ultimately it’s up to you as to whether it makes sense to utilize them with your own list.

Date & time filters

The following Liquid filters can come in handy when working with dates & times. Credit goes to Derrick Reimer for the inspiration!

Generating timestamps

You can use the timestamp filter to generate a timestamp (in seconds-since-epoch) from the input time. For example, the following will output the current timestamp:

{{ "now" | timestamp }}

Converting time zones

The in_time_zone filter will output the input date to the time zone provided. For example, the following would output the current date in the America/Denver time zone (in the format December 15, 2020):

{{ "now" | in_time_zone: "America/Denver" }}

Click here for the full database of worldwide time zone names.

☝️NOTE: If the zone name is not recognized or not provided, it will return the original input time.

You can also add a date filter to customize the format of the timestamp output. For example, the date filter added in the example below would output the format 2020-12-15 12-36-34 -0700:

{{ "now" | in_time_zone: "America/Denver" | date: "%Y-%m-%d %H-%M-%S %z" }}

TIP: The date format can be modified using the same format as Ruby’s time.parse.

Advancing to a specific day

The advance_date_to_next filter will move the input date to the same time on the upcoming selected weekday. For example, the following example would output the date of the following Monday:

{{ "now" | advance_date_to_next: "monday" }}

☝️NOTE: If the input date happens to already be on that weekday (so in the above example, if “now” was already on a Monday), then it will advance it by one week.

Resetting time to midnight

The at_midnight filter will generate a time that represents midnight as the beginning of the input date (so the output time will always be before the input time). This can be useful for normalizing dates.

{{ "now" | at_midnight }}

Number of days or weeks since or until

With the days_since and days_until filters, you can output the number of days since or until a date of your choosing. The calculation is relative to the time the email was sent.

For example, the following will output the number of days since January 1, 2000 (relative to the time an email was sent):

{{ "2000-01-01" | days_since }}

Similarly, the following will output the number of days until December 31, 2022 (relative to the time an email was sent):

{{ "2022-12-31" | days_until }}

This is available for weeks, too! Just use weeks_since and weeks_until instead.

☝️NOTE: The total number of days/weeks will be truncated (i.e., the decimals removed). For example, a value of 3.9 weeks would be output as 3 weeks. The same applies to negative numbers, if you use one of these filters on a date in the past (that is, a value of -3.9 would become -3).

Using Liquid on custom field values

You can also apply Liquid directly to custom field values inside of your automations. To act on a custom field value inside of an automation, first add an Action step and then select ‘Set custom field’, as follows:

From here, select the custom field upon which you want to act from the dropdown (please note that only custom fields you’ve created will be included here, so the default first name & email address fields won’t be available to select). Inside of the ‘Field value’ section is where you can use Liquid to generate or reformat the value of that field.

Here are a couple of examples of how you can use this:

Storing dates

If you want to use a custom field to store the date of when a particular action occurred, you can do so by using a date filter like the following: {{ "now" | date: "%d-%m-%Y" }}

This example would output the date in ‘dd-mm-YYYY’ format as that custom field’s value (e.g. November 10, 2020 would become 10-11-2020).

☝️TIP: You can adjust the date format to your liking — it uses the same format as Ruby’s time.parse.

Keeping count

Liquid can also be used to keep track of how many times something has occurred. For example, say you want to keep track of how many times a subscriber of yours has purchased one of your products. You could create a custom field to keep track of this, and then automatically increase the count of its value by 1 in your automation whenever a purchase occurs, by using a plus filter as follows: {{ subscriber.purchase_counter | default: 0 | plus: 1 }}

Then you can even create a segment to filter for subscribers whose counter value is greater than (or less than) a certain number, by using a custom field filter:

☝️NOTE: The custom field must be lowercase i.e. subscriber.purchase_counter

Looking for more?

We’d recommend checking out our Liquid basics article below, if you haven’t already! It covers the fundamentals of using Liquid in your emails, including how to preview personalized content, plus frequently asked questions:

Did this answer your question?