Using Liquid markup to customize comments and email notifications

Using Liquid markup to customize comments and email notifications

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 (#{{ticket.id}}) 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:
http://{{ticket.url}}

{{ticket.comments_formatted}}

{% else %}

Hello {{ticket.requester.first_name}}

Your request (#{{ticket.id}}) 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:
http://{{ticket.url}}

{{ticket.comments_formatted}}

{% 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 (#{{ticket.id}}) è stata ricevuta, è stato esaminato dal nostro staff di assistenza.

Per esaminare lo stato della richiesta e aggiungere ulteriori commenti, segui il link qui sotto:
http://{{ticket.url}}

{{ticket.comments_formatted}}

{% when 'Danish' %}

Hej {{ticket.requester.first_name}}

Din anmodning (# {{ticket.id}}) 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}}

{{ticket.comments_formatted}}

{% else %} 

Hello {{ticket.requester.first_name}}

Your request (#{{ticket.id}}) 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:
http://{{ticket.url}}

{{ticket.comments_formatted}}

{% 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) and you use the names (the exact text string) as displayed in the list of languages on that page.

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 ticket.organization.name 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 %}

   Comment:
   {{comment.created_at}}
   {{comment.created_at_with_time}}
   {{comment.author.name}}
   {{comment.value}}

   Attachment:
   {% for attachment in comment.attachments %}
   {{attachment.filename}}
   {{attachment.url}} 

   {% 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

Comments

  • Avatar
    Claire

    what date format is required for ticket.due_date

  • Avatar
    Anton de Young

    Claire,

    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. 

  • Avatar
    Claire

    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}} ?

  • Avatar
    Anton de Young

    Claire, 

    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. 

  • Avatar
    Claire

    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.

  • Avatar
    Quinton McCombs

    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...

  • Avatar
    Anton de Young

    Claire, 

    It turns out that due_date is not currently supported by the mail API (http://www.zendesk.com/api/mail-api).

  • Avatar
    Anton de Young
  • Avatar
    Rafal Kalicki

    Hi

    {{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?

     

     

  • Avatar
    Idunckel

    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 %}
    {{attachment.filename}}
    {{attachment.url}}

    {% endfor %}

  • Avatar
    Björn Bauer

    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,

    Björn 

  • Avatar
    Anton de Young

    Björn, 

    I assume you're referring to this tip of the week: http://www.zendesk.com/blog/showing-whos-been-ccd-in-email-notifications

    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? 

  • Avatar
    Alun Carp

    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.

  • Avatar
    Alun Carp

    Zendesk, any comment of formatting dates please?

  • Avatar
    Skip Moore

    @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 .

  • Avatar
    Alun Carp

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

  • Avatar
    Skip Moore

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

  • Avatar
    Alun Carp

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

  • Avatar
    Skip Moore

    @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 

  • Avatar
    Lorraine Joubert

    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?

  • Avatar
    Lorraine Joubert

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

  • Avatar
    Skip Moore

    @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}}

  • Avatar
    Alun Carp

    @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 %}

    Comment:

    {{comment.created_at}}

    {{comment.created_at_with_time}}

    {{comment.author.name}}

    {{comment.value}}

    {% endfor %}

  • Avatar
    Alun Carp

    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.

  • Avatar
    Rob Eyre

    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 %}
  • Avatar
    Thomas Moreau

    Hello, 

    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?

  • Avatar
    Will Dobbins

    @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...

  • Avatar
    Skip Moore

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

  • Avatar
    Will Dobbins

    Skip,

    Formatted comments come out:

    User, Jun 29 09:47 (CDT):

    Comment

    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.

  • Avatar
    Eli Blankers

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

Please sign in to leave a comment.