Understanding Liquid markup and Zendesk Support

Return to top
Have more questions? Submit a request


  • Oliver Knigge

    Hi Guys,

    I need also help with the ticket.tags attribute. I did not get the ticket.tags assigned to an array correctly.

    This is what I have tried:

    {% assign tags = ticket.tags | split: ' ' %}
    {% for tag in tags %}{% case tag %}
    {% when 'tag_1' %}{% assign newtag = 'YES' %}
    {% when 'tag_2' %}{% assign newtag = 'YES' %}
    {% else %}{% assign newtag = 'NO' %}
    {% endcase %}{% endfor %}

    Current: {{newtag}} (Just to test, which assigning was used)

    {% for comment in ticket.comments offset:1 %}
    {% if newtag == 'YES' %}{% if forloop.last == true %}{% break %}{% endif %}{% endif %}
    {% endfor %}

    'newtag' is always assigned with "NO" - so my if-expression will not work properly. 

    What I want to do:

    I would like to have a comment history in the e-mail notification. 
    When having specific tags in the ticket, I do not want to show the earliest/first ticket comment (=submit) in the ticket history. So the forloop should break if 'tag_1' or 'tag_2' is present and it is the last iteration of the forloop (forloop.last). 

    I have tried so many versions and nothing has worked for me until now.

    I have also tried an if-expression instead of the % CASE % to find out, if one of the tags is present in the ticket:

    {% assign tags = ticket.tags | split: ' ' %}
    {% if tags contains 'tag_1' or 'tag_2' %}{% assign newtag = 'YES' %}{% else %}{% assign newtag = 'NO' %}{% endif %}

    Current: {{newtag}} (Just to test, which assigning was used)

    {% for comment in ticket.comments offset:1 %}
    {% if newtag == 'YES' %}{% if forloop.last == true %}{% break %}{% endif %}{% endif %}
    {% endfor %}

    In this case 'newtag' is always assigned with "YES". I don't know why and this lets me freak out :)

    Both versions are not working.
    Hopefully you can help me :)



    I have also posted this in the community:

  • Jason Littrell

    @Oliver  In your first block of code, the most likely problem is that your "newtag" variable is being overwritten by subsequent tags. Essentially, the last tag that is evaluated by the for loop will determine what the "newtag" variable is set to. To get around this, add a {% break %} tag after assigning "newtag" to "YES" to exit out of the for loop.

    Regarding your second attempt, using "tags contains" is much simpler than the for loop you created, but you have to be careful with how you code multiple boolean conditions. In your case, you have two conditions:

         tags contains 'tag_1'



    Liquid is trying to evaluate the string 'tag_2' by itself and it considers any strings to be truthy (more info here). To fix this, you have to be explicit about what you do with the 'tag_2' string. This code should do what you want:

    {% assign tags = ticket.tags | split: ' ' %}
    {% if tags contains 'tag_1' or tags contains 'tag_2' %}{% assign newtag = 'YES' %}{% else %}{% assign newtag = 'NO' %}{% endif %}

    Hope this helps!

  • Oliver Knigge

    Finally, this helps! :)

    Now the conditions are working as expected.

    Thank you so much Jason!

  • Jennifer Rowe
    Zendesk Documentation Team

    Jason, you're awesome! Thanks so much for helping out. 

    Oliver, glad it's working now!

  • Todd Meyer

    I set up an IF/ELSE condition in a macro and noticed several lines of whitespace being generated when the macro is invoked.  

    Looking at the Liquid documentation here: https://shopify.github.io/liquid/basics/whitespace/ they have a way to eliminate the whitespace, but I can't get Zendesk to accept the syntax.

    It keeps telling me:

    • A template placeholder is in an invalid format: Liquid syntax error: Tag '{%- if ticket.description contains 'Banana' -%}' was not properly terminated with regexp: /\%\}/

    Is this a bug in ZD? Do they need to update their installation to account for this? Is there another way to remove all the whitespace that gets generated in the meantime?

    Thanks in advance 😀

  • Oliver Knigge

    Hi Todd.

    Maybe try to use this documentation:


    There you will find the following filters:

    • lstrip - strips all whitespace from the beginning of a string
    • rstrip - strips all whitespace from the end of a string
    • strip - strips all whitespace from both ends of the string

    I don't know how to use this exactly, but I think you should capture the ticket.description first with one of the filters 

    {% capture description = ticket.description | strip %}
    {% if description contains 'Banana' %}

    Greetings, Oliver

  • Dan Stolero



    I'm trying to create a condition like {% if ticket: Comment == Present, and requester can see the comment %}

    What would be the correct format for the field name and the value?


    Thank you,


  • Simone Chimera

    Hi there. I am looking for some help using Liquid markup in my macros and email notifications.


    I am currently using {{ticket.description}} howver the result is really ugly. Here is an example where the placeholder is being used: https://snag.gy/rOxmyZ.jpg as you see it contains: --------------------------------------texttexttexttexttext


    What to do, to get that away?

  • Jacob J Christensen
    Community Moderator

    Hi Simone,

    When we solve a ticket we include the {{ticket.comments_formatted}}  placeholder, so the entire conversation is included. From the context of your screenshot that sounds like what you want.

    You can find the Placeholder reference article here.

  • Michael

    There is some great information here. We are running into a minor issue that we can not seem to figure out. Been checking multiple community posts trying some different solutions but to no success yet. 

    Here is our issue:

    When a user writes in on a ticket, we want to address them by their first name if it is available. If not, we just want a simple "Hi There" as a response. I am thinking this shouldn't be that complicated but it has stumped us. 

    Through some of the other posts on this site, here is what we have tried:

    {% if ticket.ticket_field_2993840 == empty %}Hi,
    {% else %}Dear {{ticket.ticket_field_2993840}}
    {% endif %}

    {% if ticket.requester.first_name == "Unknown" %}Hi,
    {% else %}Dear {{ticket.requester.first_name }},
    {% endif %}

    {% if ticket.ticket_field_29938409 == empty %}Hi,
    {% elsif ticket.ticket_field_29938409 == null %}Hi,
    {% else %}Dear {{ticket.ticket_field_29938409}},
    {% endif %}

    Hi {% if ticket.requester.first_name == null %}there{% else %}
    {{ticket.requester.first_name}}{% endif %}

    Hi {% if ticket.requester.id == current_user.id %}there{% else %}
    {{ticket.requester.first_name}}{% endif %}

    Hi {% if ticket.requester.id == current_user.id %}{% raw %}
    {{ticket.requester.first_name}}{% endraw %}{% else %}
    {{ticket.requester.first_name}}{% endif %}

    None of these variations will give us the outcome for both scenarios. We just want to avoid it pulling their email address and instead just say a simple Hi or Hi There.

    Anyone who could help would be amazing. This has bothered us for a long time and would save time from fixing these on each ticket.

    Thanks for your help!


  • Becca
    Zendesk Team Member

    Hi Michael - 

    I did some research and brainstorming on this and unfortunately I am thinking this is likely not directly possible. Some type of value is always going to be required in the name field for a user and this value, if a single string will be considered the first name by the name placeholders. As a result, if the name is unknown and Zendesk pulls in the beginning of the email address, this would still be considered the first name value meaning the {{ticket.requester.first_name}}  placeholder would always see some type of value. 

    Once option I did think maybe promising is implementing some type of regex in your Liquid on the value of the first name to determine if it matches the beginning to the ticket requester's email address. However this would have downsides as in some cases the email could be the same as their first name. 

  • James Taqvi

    Hello - how can I show all ticket comments apart from the most recent?

    I've used liquid markup to display the most recent comment in plain text when replying to tickets.

    I then want to add the past activity below this. I am happy for this to be formatted as Zendesk usually does.

    To do this just used the {{ticket.comments_formatted}} placeholder and tried a number of things to remove the most recent comment e.g. {{ticket.comments_formatted | remove_first }} but can't get anything to work.

    Could anybody point me in the right direction? Thank you in advance!

  • Chris Swinney

    Hey, I am looking to check the individual values assigned the to a given tags string, Splitting the tags into an array is outlined above, so all is OK there,
    The tag I am after will contain a prepended string, then a numeric reference, such that 

    ticket.tags = "tag1 tag2 issue_12345 tag4"

    So the goal is to identify firstly if the tags contains a tag that has "issue_????", then to extract the numeric reference. In the above case, we want to return "12345"

    So far I have (with dummy text to see output:

    {% assign tags = ticket.tags | split: ' ' %}
    {% for tag in tags %}
    {% if tag contains 'git_'}
    {% assign issue = {{ {{ tag }} | remove: "issue_"}} %}
    {{ tag }}
    {% endif %}
    {% endfor %}

    {{ issue }}

    The `for` and the `if` block do what I am looking for (although not sure if this is the most efficient way to achieve the goal), however, I can't seem to `assign` and use the filter `remove` on the current `tag` variable. The output of `{{ tag }}` is correct (is shows `issue_12345`), but variable output for `{{ issue }}` is blank (and I expect `12345`}

    Further, is there any testing for Liquid within Zen, so you can see dummy input and output, rather than trying to modify a trigger and action the trigger?

  • Chris Swinney

    FWIW, I have tried a bunch of different syntax changes of the `assign` line, such as:

    {% assign issue = tag | remove "issue_" %}
    {% assign issue = tag %}
    {% assign issue = {{ tag }} %} 

    (with the last two I would have manipulated the variable `issues` later)

    But with not much luck so far.

    I even tried:

    {% capture issue %}{{ tag | remove: "issue_" }}{% endcapture %}

    But this result in a syntax error as Zen doesn't seem to understand the `{% endcapture %}` tag

  • Chris Swinney

    Ahhhhhh, rookie mistake. In my hackery, I managed to delete a trailing `%` from the opening `if` statement. Looks like `capture` does the trick.

  • Jennifer Rowe
    Zendesk Documentation Team

    Glad you figured it out, Chris! Thanks for letting us know.

  • Brendan Farrar-Foley

    Is it possible to pull in external content using Liquid Markup?

    We want to pull in a quote of the day into the agent signature and have not yet figured out a good way to do this.  

  • Jacob J Christensen
    Community Moderator

    Hi Brendan, maybe this will help you:
    Send out different notification messages using liquid.


  • Hector Latorre



    Why is that Zendesk/Liquid prepends backslashes when splitting?

    Example liquid markup:

    "tags" : {{ticket.tags | split:" " }}

    Result in JSON:

    "tags" : [\"_2d1\", \"_82xs\", \"passed_macro\", \"not_customer_contact__outbound\"]

    With this the server can't parse the JSON, I've tried using the remove function with no success.


    Anyone knows?


    EDIT: Got it thanks to Chris.

    "tags" : [{% assign tags = ticket.tags | split:' ' %}
    {% for tag in tags %}
    {% if forloop.last == false %},
    {% endif %}
    {% endfor %}],
  • Lars

    Hey everybody!

    We have two different groups in our Zendesk support. I am currently trying to implement dynamic sentences into a macro. Those sentences are supposed to be different for the two groups
    If a ticket is in group 1 I want to add website A,
    if a ticket is in group 2 I want to add website B.

    I tried this, but it did not work. Does anyone have ideas? :-)

    {% if ticket.group.name == '1‘ %}
    Website A
    {% elsif ticket.group.name == '2‘ %}
    Website B
    {% endif %}

    The output I get is this error: "Liquid error: Unknown operator href="

    Also, I was not even able to get a code from https://github.com/Shopify/liquid/wiki/Liquid-for-Designers <https://github.com/Shopify/liquid/wiki/Liquid-for-Designers> to work.

    {% if user.name == 'tobi' %}
    Hello tobi
    {% elsif user.name == 'bob' %}
    Hello bob
    {% endif %}

    That code did not display anything. Even when I changed the names to the names that were actually in the ticket.

    Thank you so much!

  • Jacob J Christensen
    Community Moderator

    Hi Lars,

    Just a thought - it seems like you're using two different apostrophes in your first example above. 

    Try using only this type -> '

    See if that does anything for you.

  • Lars

    Hi Jacob!

    Thanks for your reply.

    Sadly, that did not make it work. Do you have any other ideas? :-)



  • Jacob J Christensen
    Community Moderator

    Hi Lars,

    I just tried it out and got the same error the first couple of times, the error seems to be introduced in the Macro rich text editor (I think) - the placeholder text becomes auto-hyperlinked.

    What worked for me was to

    • cut the text from the macro editor
    • remove all formatting (notepad),
    • paste it back into the editor,
    • hyperlink the text you want to link and save.

    I hope that helps you out.

  • Tsvetan

    Hi guys,

    I need help. I am struggling with the following case. I would like to make a check about signature in the Brands>>Agent signature section. Currently the check is as follows - if it's not specific agent then enter empty space, otherwise enter the predefined signature. Here is the code. So far is working nice, however I want now to extend the logic, where even if it's that agent, to additionally check for specific ticket.tag and if it's there, to enter again an empty space.

    I have tried with almost everything, but it seems I cannot make it working. Something which makes me to think that this cannot happen is that, that from the Agent signature section I cannot collect the ticket.tags. Probably the ticket is still not created at that stage. Where the Notification triggers collect and shows the ticket.tags.

    One of the examples:


    {% assign tags = ticket.tags | split: " " %}
    {% for tag in tags %}{% if tag == 'testtag' %}
    {% assign x = true %}
    {% endif %}{% endfor %}

    {% if agent.email != 'agent@email.com' and x = true %}
    left blank
    {% esle %}
    My signature
    {{% endif %}}


    I have tried with capture and many different things, but couldn't make it working. Any assistance or advises will be much appreciated.

  • Sarah Seiwert

    New day, new question! I'd like our liquid macro to do a couple of things:

    1. Go from public to private mode when a specific tag is selected. 

    2. Include private notes as a prompter for the agent to consider before replying to the customer. They would then delete them and use the macro as needed. 

    What are the commands needed to make the above happen, and where should the be placed? 

    {% if ticket.requester.last_name == ticket.requester.first_name %}Hi there! {% else %}Hi {{ ticket.requester.first_name | capitalize }},{% endif %}

    {% assign tags = ticket.tags | split: ' ' %}

    {% if tags contains 'ielts' %}

    {% elsif tags contains 'toefl' %}






    {% else %}

    Macro currently for SAT, ACT, TOEFL, MCAT, GMAT, and GRE only.


    {% endif %}

  • Karen

    Hi All,

    I am looking to include some liquid markup so that the current day can be displayed.

    I have worked out how to have the greeting show for the correct time of day, but displaying the day is alluding me.

    Any help on this would be great.


  • Ajay Paul

    Hi, I am attempting to use liquid markup to update a multi-select field based on comment strings. Please note this is a hack attempt to use one trigger as opposed to multiple. However the following statement only seems to update the first dropdown option and not multiple dropdown options:

    {% capture comment %} {{ticket.latest_comment}} {% endcapture %}

    {% if comment contains "24th December" %}


    {% else comment contains "25th December" %}


    {% else comment contains "26th December" %}


    {% else comment contains "27th December" %}


    {% else comment contains "28th December" %}


    {% else comment contains "29th December" %}


    {% else comment contains "30th December" %}


    {% else comment contains "31st December" %}


    {% else comment contains "1st January" %}


    {% else comment contains "2nd January" %}


    {% endif %}

  • Fernando Duarte



    Liquid is used to update the formatting of text, not fields

  • Josh Keller

    Fernando Duarte - Liquid is great for putting logic into the body of HTTP Targets. When you do that in a trigger with a Zendesk ticket endpoint, field update dreams are achieved.

  • Raman Kalia

    I would like to send all URL from my KB based on matching words in the ticket body at the time of creation or update by the end user. Generally liquid markup examples are around if/else statements. My requirement is around sending all those URLs, whose conditions tag found matching in the ticket content/comment.


Please sign in to leave a comment.

Powered by Zendesk