Question
How can I reveal CCs in a notification email using Liquid markup?
Answer
While there are many pieces of information to display in notifications, one of the most common requests is the ability to display who else is CCed on a particular request.
Using Liquid markup to display CCs
Liquid markup makes this quite simple. Add this block of code to any triggers or automations in which yo want CCs to be listed:
{% if ticket.cc_names != empty %}
{% capture ccedusers %}
{% for cc in ticket.ccs %}
{% unless forloop.last %}
{{ cc.email | append: ', ' }}
{% else %}
{{ cc.email }}
{% endunless %}
{% endfor %}
{% endcapture %}
{{ ccedusers | strip_newlines }}
{% else %}
Nobody
{% endif %}
This only lists the CCs by email address. Add some text to clarify that these email addresses belong to users who are CCed on this request, as well as any further formatting.
Below you can see how this renders in the email client:
Breaking it down
Make sure that if there aren't any CCs on the request that you don't just leave an empty line. Start by wrapping the code in an If...Else statement to print Nobody if the ticket doesn't have any CCs, and to list those CCs if it does.
{% if ticket.cc_names != empty %}...
{% else %}Nobody
{% endif %}
If the request does have some CCs, grab them and apply some formatting to prevent them from all being globbed together. Start by creating the ccedusers variable to hold all of the CC'ed email addresses with some of our formatting applied so that we can easily reference them later.
{% capture ccedusers %}
...
{% endcapture %}
Iterate over all of the CCs on the ticket, grab the email address for each, and add them to our email variable separated by a ', ' (for all but the last CC) to make them more readable.
{% for cc in ticket.ccs %}
{% unless forloop.last %}
{{ cc.email | append: ', ' }}
{% else %}
{{ cc.email }}
{% endunless %}
{% endfor %}
Print out the freshly constructed list of email addresses. We do this with the following line, making sure we strip the newline characters that would otherwise list each email address individually on its own line.
{{ ccedusers | strip_newlines}}
Alternatives
To include the CCed names, use the following code:
{% if ticket.cc_names != empty %}
{% capture ccedusers %}
{% for cc in ticket.ccs %}
{% unless forloop.last %}
{{ cc.name | prepend: '"' | append: '" '}} {{ cc.email | prepend:'<' | append: '>, ' }}
{% else %}
{{ cc.name | prepend: '"' | append: '" '}} {{ cc.email | prepend:'<' | append: '>' }}
{% endunless %}
{% endfor %}{% endcapture %}
{{ ccedusers | strip_newlines | replace:'"','"' | replace:'<','<' | replace:'>','>' | replace:';','' }}
{% else %}
Nobody is CC'd
{% endif %}
For a complete list of placeholders available to you, please refer to our Placeholders Reference. For more information about Liquid markup, see Liquid for Designers.
32 Comments
Hi Matt,
It doesn't look nice for customer to see text below:
"CCs on Ticket:
Nobody"
Is it possible to modify code so that if there is not CC's on ticket, there's not this text at all? But when there's CC's, then text appears naturally.
Do you have tips how to code this?
Tiina,
Absolutely. You'd simply move the 'CCs on Ticket:' text into/below the following if block:
{% if ticket.cc_names != empty %}
Finally, delete the 'Nobody' in the {% else %} clause.
Hi Matt,
I'm using Dynamic content, because we've 5 different languages and Dynamic content isn't working inside the code.
How can I create code to support these 5 languages?
The code that I have right now is this:
{{dc.aa_ccs_on_ticket}} <-dynamic content supported by 5 languages
{% if ticket.cc_names != empty %}
{% capture ccedusers %}
{% for cc in ticket.ccs %}
{% unless forloop.last %}
{{ cc.email | append: ', ' }}
{% else %}
{{ cc.email }}
{% endunless %}
{% endfor %}
{% endcapture %}
{{ ccedusers | strip_newlines }}
{% else %}
-
{% endif %}
BR,
Tiina
Matt, thanks for this great explanation. I read up on Liquid and the {% for %} loop actually does its own check for empty and guarantees it will only iterate over the items if they exist. In fact, you can add an {% else %} to the {% for %} loop to put your "Nobody" in the main loop if it's got no items.
There's an additional optimization. You're using prepend and append on cc.name and cc.email, which are guaranteed to exist, right? Also, you don't need to double the entire output for the {% else %} block, when all you really need to do on the last iteration is NOT add the ", ".
Taking all these optimizations together, you'd shorten your code quite a bit to:
{% capture ccedusers %}
{% for cc in ticket.ccs %}
"{{ cc.name }}" <{{ cc.email }}>
{% unless forloop.last %}, {% endunless %}
{% else %}
"Nobody" <nobody@nobody.com>
{% endfor %}
{% endcapture %}
{{ ccedusers | strip_newlines | replace:'"','"' | replace:'<','<' | replace:'>','>' }}
And, like others have mentioned, this display is only for readability and comprehension. When you actually put this in your Dynamic Content editor, put it in as:
{% capture ccedusers %}{% for cc in ticket.ccs %}"{{ cc.name }}" <{{ cc.email }}>{% unless forloop.last %}, {% endunless %}{% else %}"Nobody" <nobody@nobody.com>{% endfor %}{% endcapture %}{{ ccedusers | strip_newlines | replace:'"','"' | replace:'<','<' | replace:'>','>' }}
Hope this helps!
Hi Everyone,
Thank you for your comments, it's been very helpful!
I copied and paste the last code that Ace posted. Would you know how to remove the "Nobody" <nobody@nobody.com> when no one is copied?
Thanks for your help :)
@Emilie: Just remove these two lines:
{% else %}
"Nobody" <nobody@nobody.com>
I just added them as an example of the "else" clause, you don't need it if you're not wanting always at least someone Cc'ed.
Cheers,
...A
Hello, there is actually a mistake in the article above. The article recommends inserting the following line if you had lines above showing the name of the CC'd user along with the e-mail:
{{ ccedusers | strip_newlines | replace:'"','"' | replace:'<','<' | replace:'>','>' }}
The issue is that if you go back into the trigger, you will see it converts the line to this (it's converting the code into actual characters):
{{ ccedusers | strip_newlines | replace:'"','"' | replace:'<','<' | replace:'>','>' }}
Therefore, instead you can use this line - tested and working!
{{ ccedusers | strip_newlines | replace:'"','"' | replace:'<','<' | replace:'>','>' | replace:';','' }}
I have tried using this Liquid code for CC's on my tickets. Although the logic appears to work as in it knows there are other people cc'd it doesn't show any details for them.
Andy idea why this will be the case ?
Hi All,
I'm using the method described here to add CC'd parties to my tickets, and 'not show' if there are no CC's
Here is the code I have modified -
{% if ticket.cc_names != empty %}The following email addresses are copied on this ticket - {% capture ccedusers %}{% for cc in ticket.ccs %}{% unless forloop.last %}{{ cc.email | append: ', ' }}{% else %}{{ cc.email }}{% endunless %}{% endfor %}{% endcapture %}{{ ccedusers | strip_newlines }}{% else %}{% endif %}
The challenge I have is that it shows the 'personal' emails of our support team when they CC themselves...., which I would like to avoid, as this could cause customers to try to reach out to individual agents via direct email, instead of our main support channel.
I'm wondering if there is a way with Liquid to, for example, 'not show email addresses which end in '@mydomain.com' ?
Or any other suggestions you may have here?
@Matt, of course. Here you go:
Legend Eli, thank you. I owe you a beer! (or wine?)
It works well except for one edge case - where the 'only' cc's on the ticket are @mydomain.com email addresses.
In that case, the 'People CC'd on this ticket' text shows correctly (as there are CC's), but there are none listed (as the only ones CC'd are hidden)
I'm sure there is a way to beat that too.... thoughts?
Must get to know this Liquid Markup better :)
Hmm...yeah I see that happening by me as well. I imagine we can do a for loop first that checks whether or not yourdomain.com shows up in a CC and if not, set a variable to "1", and only if the variable is "1" at the end, should we display the CC's. It's 12:30am though and I don't have the head to code that now, but it's some food for thought.
Maybe, instead of putting the "People CC'd on this ticket:" in the beginning, we can save it for the end, and do something like this:
Hey @Matt, I figured it out! Thanks for challenging me to do this, because it bothered me also that it would say "People CC'd on this ticket:" and then not show any names. So here you go:
First, remove "People CC'd on this ticket:" from the top part of the code, then...
Replace this:
with this:
Eli, that's two beers I owe you. Thanks! Glad it helped your implementation too :)
If you're in Sydney one day soon, look me up!
Glad it worked out for you. I’m across the world in Chicago, but ya never know...
Have a good one “mate”!
Hi Everyone,
I want to copy old ticket's CCs to the new tickets, how can I do this with JSON?
My JSON:
{
"ticket": {
"subject":"{{ticket.title}}",
"description":"{{ticket.description}}",
"type":"{{ticket.ticket_type}}",
"priority": "{{ticket.priority}}",
"tags":"{{ticket.tags}}",
"status": "{{ticket.status}}",
"comment":"{{ticket.comments_formatted}}",
"requester": { "name": "{{ticket.requester.name}}", "email": "{{ticket.requester.email}}" },
"collaborators":["{% capture ccedusers %}{% for cc in ticket.ccs %}{% unless forloop.last %}{{ cc.email | append: '", "' }}{% else %}{{ cc.email }}{% endunless %}{% endfor %}{% endcapture %}{{ ccedusers | strip_newlines }}{% else %}{% endif %}"]
}
}
This doesn't work...
I also tried.. "collaborators":["{% for cc in ticket.ccs %}{% unless forloop.last %}{{ cc.email | append: '",' }}{{ cc.email }}{% endunless %}{% endfor %}"]
I'm sorry @Jen, but I don't really understand what you are trying to accomplish here. Perhaps explain a bit more?
Folks, thanks for all this great information. Below I have the code we are using to reveal CC's, but in the actual emails, there is too much unnecessary empty space after the line "This ticket has been updated" and before the words "People CC'd on this ticket". How can I remove that spacing?
This ticket () has been updated.
People CC'd on this ticket:
blah@blah.com
---------------------------
CODE:
This ticket (#{{ticket.id}}) has been updated.
{% if ticket.cc_names != empty %}
{% capture ccedusers %}
{% for cc in ticket.ccs %}
{% unless forloop.last %}
{{ cc.name | prepend: '"' | append: '" '}} {{ cc.email | prepend:'<' | append: '>, ' }}
{% else %}
{{ cc.name | prepend: '"' | append: '" '}} {{ cc.email | prepend:'<' | append: '>' }}
{% endunless %}
{% endfor %}
{% endcapture %}
{% if ccedusers contains '@' %}
People CC'd on this ticket:
{{ ccedusers | strip_newlines | replace:'"','"' | replace:'<','<' | replace:'>','>' | replace:';','' }}
{% endif %}
{% endif %}
{{ticket.comments_formatted}}
It doesn't look like you have any extra lines in your code, but the extra lines are what would cause the white space. There is some white space built in on top of the {{ticket.comments_formatted}} but shouldn't be that much. Make sure there are no spaces or tabs at the end of these lines:
People CC'd on this ticket:
{{ ccedusers | strip_newlines | replace:'"','"' | replace:'<','<' | replace:'>','>' | replace:';','' }}
{% endif %}
{% endif %}
Actually, you should check EVERY line to make sure there's no extra spaces or tabs, and keep the code tight.
Hi,
Thank you so much for a great article and comments. This has been really helpful! If I follow the codes mentioned to get a list of CCs,I have an issue with where the list of CC is placed in the email to the end-user.
If you look at my attached picture, the bottom message "test" is from the end-user. Then I tried one answer without anyone on CC "Hei Terje. Klart det.". Then the top one is another answer with someone on CC "Ingen problemer Terje. Odd, kan du se på saken?".
What I notice is that even though I only added someone on CC for my last message, the list of the people on CC is all the way down at the bottom of the email. Ideally, I would like it to show right under my last message to the end-user.
Anyone know how to make that happen?
Hi Terje!
My guess is that you added the CC information to the Email template in your settings, so it appears at the bottom of the email. I think you can get the info to display in your most recent comment by adding it to the email body in your Triggers and Automations.
Hi Jessie,
Thanks for you feedback. Actually, I added the following information in the triggers only:
{{ticket.comments_formatted}}
{% if ticket.cc_names != empty %}
If there are any additional contributors to this ticket then their email addresses will appear here:
{% capture ccedusers %}
{% for cc in ticket.ccs %}
{% unless forloop.last %}
{{ cc.email | append: ', ' }}
{% else %}
{{ cc.email }}
{% endunless %}
{% endfor %}
{% endcapture %}
{{ ccedusers | strip_newlines }}
{% else %}
{% endif %}
Any thoughts?
Hi Terje!
That type of coding is, unfortunately, not something I'm familiar enough with to be able to say whether it's correct or not. I'll see if one of our Community Moderators can check it for you!
Hello,
I hope someone can help me. Till yesterday I used this code in Zendesk to reveal the mailaddress of an CC.
{% if ticket.cc_names != empty %}
{% capture ccedusers %}
{% for cc in ticket.ccs %}
{% unless forloop.last %}
{{ cc.email | append: ', ' }}
{% else %}
{{ cc.email }}
{% endunless %}
{% endfor %}
{% endcapture %}
{{ ccedusers | strip_newlines }}
{% else %}
Nobody
{% endif %}
However since today this code does not work anymore. Is it just a temporary thing or does Zendesk not support liquid markup anymore?
Hi Merijn! I'm sorry to hear you're having problem with this.
I see that you've also submitted a ticket about this. As you now know, it's a known issue and we're currently working on a fix. We'll let you know when everything is done in your ticket!
Hello @Marijn,
FWIW until you get a fix, this much simpler markup is still working for us for this purpose:
{% if ticket.cc_names != empty %}{% capture ccedusers %}{% for cc in ticket.ccs %}
{{ cc.email }}{% endfor %}{% endcapture %}{{ ccedusers }}{% else %}None{% endif %}
I'd be curious what the specific problem is for your markup.
Hi all,
Thank you for all the helpful comments in this threat that helped us notify the requester of who's CC'ed.
Does anyone know how to include in the email that goes out to the CC's, the email addresses of the other CC's and the requester?


Currently this is what each CC sees.
This is what our requester sees. And this is what we'd like our CC's to see as well.
Thank you.
In the admin section of Zendesk under "Tickets", find the spot where you can modify the e-mail that goes to the CC'd, and replace it with this (or something like it):
Thank you so much Eli. Really appreciate the help you've given me and others prior!

Do you have any opinion with the code I have below in regards to any issues it may have/cause. I like that it comes out in separate rows without commas, quotations or '<' so that its much more noticeable for our clients and is very simplified.
Do you know how to modify so that I can embed "The following email addresses are copied in this email:" It seems that I need an IF statement so that it won't appear if there are no CC entries?
Also, if I wanted my agents emails to show as CC's would I just remove
and
Much thanks in advanced!
Please sign in to leave a comment.