Using Liquid markup to customize comments and email notifications

enterprise plan

If you're familiar with placeholders in Zendesk, then you already know something about Liquid markup. It's the templating language we use to enable them. Placeholders are used in automations, macros, targets, triggers, and widgets as containers for dynamically generated ticket and user data. What you may not know about Liquid markup is that you can also use it to customize how this data is selected and displayed as output. This is because Liquid also allows you to create simple programming logic such as case statements, if statements, for loops, and so on.

By writing simple control statements directly in the comment/description action in macros and the email user action in automations and triggers, you can accomplish in one automation, macro, or trigger what you used to have to do in multiple automations, macros, and triggers. You can also customize how comment text is presented.

A brief introduction to Liquid markup

You can find the Liquid documentation at Liquid for Designers. All of the elements of the language are described in detail. Here, however, is a brief introduction to how it works.

Liquid is a templating language for rendering email and HTML. In Zendesk, Liquid is the mechanism that enables the automated placement of data in comments and email notifications using placeholders.

There are two types of markup in Liquid:
  • Output, which is text output contained in double curly brackets.
  • Tags, which contain the programming logic that determines how the data is expressed with placeholders.

If you simply equate output with placeholder, you're about half way to understanding what Liquid is and how it's used in Zendesk. What you may not know about Liquid output however is that in addition to expressing ticket and user data, there are also methods available to manipulate text strings and arrays. In Liquid, these methods are referred to as filters. Using a filter you can transform text to uppercase characters, for example. But that's one of the simplest examples of what filters can be used for. See the Liquid documentation for more information.

The other half of understanding of how Liquid can be used in Zendesk comes from knowing what tags are and how they are used. Tags provide the programming logic that you can use to select and present data.

Using Liquid tags you can create:

  • if else statements
  • case statements
  • for loops
  • cycles
  • variable assignments

As an example, based on ticket properties you can create different responses in your business rules. This example shows how you can modify the Notify requester of received request trigger (or any other trigger that serves the same purpose) to return a response based on your business hours.

{% if ticket.in_business_hours == 'true' %}

Hello {{ticket.requester.first_name}}

Your request (#{{}}) has been received and is being reviewed by our support staff. 

To review the status of the request and add additional comments, follow the link below:


{% else %}

Hello {{ticket.requester.first_name}}

Your request (#{{}}) has been received and will be reviewed by our support staff during regular business hours (Monday - Friday, 8am - 6pm PST). 

To review the status of the request and add additional comments, follow the link below:


{% endif %}

Using a simple if...else statement, the first response is sent if the request is received during business hours and the other is sent if it is not. The if statement tests the ticket.in_business_hours property and responds accordingly. The ticket property is in the same format that you're familiar with when it's used as a placeholder, although not contained within double curly brackets for the simple reason that it's not being used as output here but rather as part of the logic determining what will be included in the comment when it's sent to the requester as an email notification.

For several other examples of how these simple statements can be used in Zendesk, see Using Liquid markup to support multiple languages in automations, macros, and triggers and Customizing the formatting and placement of text in comments and email notifications below.

These are just several examples of what you can do with these simple but powerful Liquid tags.

Using Liquid markup in Zendesk

Here are several more examples of how Liquid markup is commonly used in business rules to customize comments and email notifications.

For the complete list of Zendesk data objects that can be used in your Liquid code, see Zendesk data object (placeholders) reference.

Note: You may find it convenient to test your Liquid markup in a test macro since you can see the results immediately by applying the macro to a ticket.

Using Liquid markup to support multiple languages in automations, macros, and triggers

Many companies and organizations support end-users who speak languages other than English and there are a number of ways to manage this in Zendesk. In this example, a case statement is used to determine what response is sent to the end-user based on their language setting. The email body of the Notify requester of received request trigger contains the following Liquid markup:

{% case ticket.requester.language %}

{% when 'Italiano' %}

Ciao {{ticket.requester.first_name}}

La tua richiesta (#{{}}) è stata ricevuta, è stato esaminato dal nostro staff di assistenza.

Per esaminare lo stato della richiesta e aggiungere ulteriori commenti, segui il link qui sotto:


{% when 'Danish' %}

Hej {{ticket.requester.first_name}}

Din anmodning (# {{}}) er blevet modtaget og bliver gennemgået af vores supportmedarbejdere.

At gennemgå status for anmodningen og tilføje yderligere kommentarer, skal du følge nedenstående link:
http:// {{ticket.url}}


{% else %} 

Hello {{ticket.requester.first_name}}

Your request (#{{}}) has been received, and is being reviewed by our support staff. 

To review the status of the request and add additional comments, follow the link below:


{% endcase %}

The language preference is set in the user's profile. Language support is defined by an administrator (on the Localization tab of the Account page). The table below shows the corresponding language property value for each of the languages available on that page.

Table 1.
LocaleLanguage property value
Arabic (Egypt) Arabic (Egypt)
Arabic Arabic
Malay Bahasa Melayu
Catalan Català (Catalan)
Serbian (Montenegro) Crnogorski (Montenegrin)
Danish Dansk
German Deutsch
Austrian German Deutsch (Austria)
Swiss High German Deutsch (Switzerland)
Estonian Eesti keel (Estonian)
English English
Australian English English (AU)
Canadian English English (Canada)
English (Ireland) English (IE)
British English English (UK)
Spanish Español
European Spanish Español (España)
Latin American Spanish Español (Latinoamérica)
Filipino Filipino
French Français
French (Belgium) Français (Belgium)
Canadian French Français (Canada)
français (France) français (France)
Swiss French Français (Switzerland)
Croatian Hrvatski
Indonesian Indonesian
Italian Italiano
Latvian Latvian
Lithuanian Lietuvių kalba
Hungarian Magyar
Flemish Nederlands (Belgium)
Dutch Nederlands (Dutch)
Norwegian Norsk
Polish Polski (Polish)
Brazilian Portuguese Português (Brasil)
Portuguese Português (Portugal)
Romanian Romana
Slovak Slovak
Slovenian Slovenian
Serbian Srpski
Finnish Suomi (Finnish)
Swedish Svenska
Thai Thai (ไทย)
Turkish Türkçe
Vietnamese Vietnamese
Icelandic Íslenska
Czech Čeština
Greek Ελληνικά (Greek)
Russian Русский
Ukranian Українська
Hebrew עִבְרִית (Hebrew)
Hindi हिंदी
Japanese 日本語 (Japanese)
Simplified Chinese 简体中文 (Simplified Chinese)
Traditional Chinese 繁體中文 (Traditional Chinese)
Korean 한국어 (Korean)
Note: This example just shows the notify trigger. You'd also want to do the same thing for the update and solved triggers and any other business rules that generate comments and email notifications to the end-user.

In this example, we could have also explicitly declared the English text like the others ({% when 'English' %}). However, if the default language is English it's not necessary. The English text will be displayed to all users who have not otherwise chosen a language setting.

As you can imagine, you can use something like this for any number of reasons, not just to support multiple languages. For example, maybe you want custom responses for users in different organizations for some reason. If so, you use in a case statement like this.

Customizing the formatting and placement of text in comments and email notifications

By default, many of the Zendesk business rules use the {{ticket.comments_formatted}} placeholder to include comments into email notifications. If you want more control over how the comments are presented to requesters, you can access more details about comments and their attachments using Liquid markup.

A comment is an element within a ticket and there are a number of placeholders available that you can use to include comments in email notifications. For example, you can include all comments, public comments, the last comment, etc (see Comment data).

If you want more control over how comments are displayed in email notifications, you can use Liquid markup and a for loop, as in this example:

{% for comment in ticket.comments %}


   {% for attachment in comment.attachments %}

   {% endfor %}

{% endfor %}

This returns the items in both arrays (ticket.comments and comment. attachments). In other words, the properties for every comment and attachment contained in the ticket.

If you want to only return the last comment, you can use the limit and offset attributes as in the following example:
{% for comment in ticket.comments limit:1 offset:0 %}
You can do a lot with arrays in for loops. Refer to the Liquid documentation (Liquid for Designers) for more details.
Have more questions? Submit a request

Sign in to leave a comment


  • 0

    what date format is required for ticket.due_date

  • 0


    When you set the ticket type as task, you can select a due date from the calendar control and it's displayed in the ticket in this format: June 10, 2011. But when you return that data it's in this format: Jun-10. Same as the other dates. Thanks for catching that. 

  • 0

    Thanks, Anton … I’d like to do this on the email subject line of tasks I am inserting from another system … is it possible to do something like … {{assignee:JoeAgent ticket_type:task due_date:20111225}} ?

  • 0


    Yes that works. You'll also want to include a description in the subject line or your ticket subject will be blank because, of course, the code is setting ticket properties. 

  • 0

    When I use the above format, the ticket comes in with today's date rather than the date I specified. I assumed it was the date format I used.

  • 0

    Does this also work in the HTML email template as well?  For example, I would like to change the format for the template based some data in the ticket or some attribute or the user or organization...

  • 0


    It turns out that due_date is not currently supported by the mail API (

  • 0
  • 0


    {{comment.created_at}} reutrn eg Jul-22, how can I achieve such a format Jul-22 09:37 (CEST)

    Also, I noticed that formatted_comments placeholder by default displayes the most recent one, whereas the rest of the comments is hidden and available to watch via -show quoted text- - how can I achieve that?



  • 0

    How do you make the text the URL. When I used your suggestion, I got a long link and a filename...

    {% for attachment in comment.attachments %}

    {% endfor %}

  • 0

    Hi Anton!

    Great feature. I'd like to display all CC's except they are agents (to prevent direct mailing to the light agent).

    Can I do something like "If CC is a user, display CC" ?

    Thanks for the help,


  • 0


    I assume you're referring to this tip of the week:

    There's no way to do what you're asking using Liquid. Not that I can figure out anyway. But, an end-user ticket requester sees other end-users who have been CC'd by default (in the email header) not any agents who have also been CC'd. Is that what you're after? 

  • 0

    I too would like to know how to format dates in notification emails.

    If I let Zendesk create the comments/descriptions it appears to formats with "%b-%d %H %M (%Z)"  eg. Nov-25 06:05 (CET). If I format the comments myself and use the created_at placeholder without formatting it will only display Nov-25, if I add the same formatting it displays as Nov-26 00:00 (UTC).

    Having the time as well as the date is useful to have in emails, how do we get that?

    For example, I have this liquid markup:

    {{ticket.created_at | date: "%b %d %H %M %Z"}}

    Yet the time and time-zone are always 00:00 UTC, probably because created_at is a string containing just the date.

    The information is obviously available when Zendesk creates the comments in emails, please make it available to those of us who are trying to do this ourselves.

  • 0

    Zendesk, any comment of formatting dates please?

  • 0

    @David, I looked into this and the liquid markup {{ticket.created_at}} only contains the Month and Day. This is why you are seeing 00:00 UTC when using %H %M %Z, because there is no data to convert. I have to talked with product and we are planning to create a new markup that will contain the full date, I'll update you when it's deployed .

  • 0

    @Skip, any news on that update to provide the full date?

  • 0

    @Alun, I don't have a status update today . I will go bug the dev's 

  • 0

    @Skip, how did bugging the dev's go?

  • 0

    @Alun it's on the schedule for next week for dev time.  So another week for QA in about 2 weeks. Sorry for the long wait but we haven't forgotten it 

  • 0

    I would like to strip html from e-mails entering Zendesk and thus automatically generating a ticket.  Currently, if an e-mail contains html, this ends up in the description of the Zendesk ticket in plain html and looks terrible to the user when communication is sent that needs to include the ticket description.  How can I strip this html at ticket creation?

  • 0

    Does anyone have any feedback on my last comment, please?

  • 0

    @David @Alun you can now get the full time by adding _with_time to a time based placeholder for example {{ticket.created_at_with_time}}

  • 0

    @Skip, has this been promoted to production?

    I have just tried the following markup and get a blank line for the 'with_time" placeholder.


    {% for comment in ticket.comments limit:1 offset:0 %}






    {% endfor %}

  • 0

    Ok, it looks like this was only added to ticket.create_at as ticket.created_at_with_time does include the time.

    Using the filter  date: "%b %d %H %M %Z" does now format the date and time but I still get UTC for the timezone whereas our portal is configured as CET. I can see from the text when no filter is used that this is because no timezone information is included in the _with_time variant.

    Perhaps a _full variant needs to be implemented so that the full date filtering available in liquid markup can be used on any date (ticket, comments, description, etc.) available for notifications.

  • 0

    A couple of discoveries that might save some headaches:

    • Warning: if Zendesk can't compile your Liquid template in eg a dynamic content block, it will just send through the code
    • the 'elseif' tag is actually elsif:
      {% if a == 1 %}one{% elsif a == 2 %}two{% endif %}
  • 0


    I'm trying to set widgets in the right language for our users, as we have a bilingual Zendesk (French and English).

    Our customers have language preferences set in the web platform we've created. When they click on 'support', it generates a tag in Zendesk to that user, with the language preference ('fr' or 'en').

    Using Liquid programming, I've built custom widgets like:

    {% if tags == 'fr' %}

    Visitez notre aide en ligne !

    {% else %}

    Online help available here!

    {% endif %}

    Those widgets are placed on different places, but mainly on the homepage, to welcome them in their own language.

    Besides, I've set a trigger that says:

    "If tags contain at least on of the following: fr, then requester's language is French".

    All of this doesn't work:

    • my custom widgets are displaying only what is contained after the {% else%} tag, whatever tag the user has.
    • the language preference of a user with corresponding menu items 'check your existing requests' being 'vérifier vos demandes' in French doesn't change.

    Please, can you help, as it's been a long time we're trying to set things properly and better satisfy our customers.

    What should we do to have the language preference of our system automatically reflected in Zendesk?

  • 0

    @Skip, trying to customize my notifications to users based on their feedback and I'm unable to do so effectively because fundamental fields are simply not available...  The default formatted comments contain everything I need, however those same value's aren't exposed so I can't customize my formatting...

    The specific issue is the with_time feature discussed above, it seems half-done to add with_time to one field and ignore another...

  • 0

    @Will which issue? The same one Thomas is having?

  • 0


    Formatted comments come out:

    User, Jun 29 09:47 (CDT):


    I am unable to replicate this with the available Liquid Markup as it doesn't appear that the date/time/timezone is exposed on the COMMENT object.

  • 0

    Is there a way to add the 'Related  Topics' to an email through placeholders?

Powered by Zendesk