Handling duplicate tickets

This article explores ways to merge duplicate tickets from the same user. Customers often submit multiple requests via various channels, slowing response times. Solutions include using the Customer Context Panel, Zendesk AI-based Merge Suggestions, or automating ticket merges.

Handling duplicate tickets

Earlier this month at the Zendesk Partner Days a conversation came up about the best way to merge tickets made by the same end-user. It's a scenario that happens a lot. A customer has an urgent question and they shoot an email, web form and social message to every support channel they can find.

Not only will this not result in a faster response, it'll actually make matters worse since they are clogging up the ticket queue of agents with multiple identical questions, delaying responses for everyone. And they introduce the risk of getting different responses from different agents handling their tickets.

Since you can't block customers from doing this, we need to resort to features in Zendesk to handle this common issue.

My thanks to Next Matter for sponsoring this month's Internal Note newsletter.

Approach 1: Customer Context Panel

The easiest solution is leveraging the Customer Context Panel to find all recent tickets from a customer. You can open these tickets in new tabs and merge them with the current ticket, before you move forward handling your customers' ticket.

The downside is that it requires manual work and introduces another step for your agents, but it's a native feature that's available for all Zendesk customers so requires no additional apps or licenses.

Approach 2: Leveraging AI

One of the key selling points for Advanced AI is that it automates manual steps done by agents. In our case, the manual step of checking for duplicate tickets can be automated by leveraging Zendesk Advanced AI.

The Merge suggestions options in the Intelligence Panel will offer agents a list of similar active tickets from the same requester. Agents can select tickets and merge them, thus removing these tickets from the queue and having one single ticket with all context to work on.

This works for scenarios where users fire identical requests – even those phrased differently – across different channels, or for new tickets that are responses to or continuations of existing tickets. E.g. a customer emailing a picture of the problem in a separate email.

The upside is that the filtering is better than just looking at recent tickets and the system surfaces relevant tickets automatically, removing these additional steps from your agents' workflow. But as with everything in Zendesk Advanced AI, your agents still stay in control. It's the agent that merges tickets, preventing accidental wrong merges by simply automating the matter fully.

Approach 3: An automated, but unfiltered, approach

Internal Note wouldn't be in Internal Note if an article didn't include some over the top hack of existing Zendesk features 😅. One of the scenarios we discussed at the Partner Days was a way to automatically merge all active tickets of the same requester, regardless of their content.

So, let's do exactly that.

First we want to know if a user has an active ticket. We could do a lookup via external workers and the /api/v2/users/{user_id}/tickets/requested endpoint, but there's a way we can do this in-product.

In our approach we will store the ticket id of a requesters' latest ticket in the user profile. We can then check this value to see if a user has an active ticket, and if so merge an existing ticket into our new ticket, clearing up the queue.

💡
I purposefully use the latest ticket as the remaining ticket so that if a customer manages to resolve their inquiry themselves, that's the first message an agent will see.

Storing the latest ticket

In order to store the latest ticket, we need to create a new user field first called Latest Ticket with field key latest_ticket.

Once setup we can use a trigger to update this field whenever a ticket is created. For this we need a webhook that updates user profiles. I wrote a full tutorial on the topic in this article:

Update a requester name via webhooks and custom fields
Update a requesters’ profile based on form field input.

But in essence you need to create a webhook that calls api/v2/users/{{ticket.requester.id}}.json.

🔒
Do make sure to use admin@domain.com/token:API_TOKEN as the authentication method, leveraging a Zendesk API token. You no longer can use passwords for API authentication as of this summer!

Once you've configured the webhook, create a trigger with the following conditions:

And the following action:

{
  "user":{
    "user_fields": {
      "latest_ticket": {{ticket.id}}
    }
  }
}

Once setup this trigger will look at each created ticket and check if the value of Latest Ticket is blank. If blank, it'll update the user field with the ID of our current ticket.

Merging new Tickets

If you're wondering why we check for the presence of the Latest Ticket in the previous ticket instead of just updating it every time a new ticket is created – nice catch!

The reason we need to check and can't just update the value anytime a ticket is created is simple: if we always update the ID with the latest value upon creation, we always overwrite previous values and loose the chance to merge tickets.

In this final step we'll wrap up our workflows and merge new tickets into existing tickets if they're available. First we need to create a webhook we can use to merge tickets. Similarly to the previous step, this is based on an earlier article on this blog:

Escalating a customer request to a Zendesk Help Center form for more information.
This article shows you how to escalate an existing ticket to a new ticket form submission and merge the result.

Here to, we need a webhook that calls api/v2/tickets/{{ticket.id}}/merge with a configuration like the screenshot below:

We then create a new trigger with the following conditions:

In this scenario we run the trigger when we do detect a Latest Ticket value. Our trigger will then do two things:

  1. Merge the older ticket into this the newer ticket
  2. Update the Latest Ticket field with the newer Ticket ID.
💡
We can update the Latest Ticket field ince we already fired our merge webhook first. Even though it might not have finished, we passed the Latest Ticket value so we can safely update our user field now.

Merging Tickets

{
  "ids":[{{ticket.requester.custom_fields.latest_ticket}}],
  "source_comment": "Closing in favor of #{{ticket.id}}",
  "target_comment": "Combining with #{{ticket.requester.custom_fields.latest_ticket}}"
}

Update User

And identical to the first trigger:

{
  "user":{
    "user_fields": {
      "latest_ticket": {{ticket.id}}
    }
  }
}

The Result

Once enabled, whenever a user creates a ticket, we'll check if they have a previous ticket. If they do, we will merge that ticket into their most recent active ticket each time they create a new ticket.

Since closed tickets can't be merged, we can be sure we'll only merge active tickets

Naturally, the approach above is crude. If a customer emails about different topics we still merge tickets. You can prevent this by leveraging more conditions in your triggers. For example, if you have Advanced AI you could only merge tickets with similar intents. Or you could set an automation that, if a ticket is older than a week, you set the Latest Ticket value to blank so that our trigger doesn't run,...

Regardless, during my conversation at the Partner Days we were explicitly talking about this broad approach, and promises be promises, here's the article for those present on is how I would tackle it in more detail.

Approach 4: Leveraging the Zendesk Marketplace

When it comes to Zendesk you can be sure that if there is a process that can be done via triggers, API and webhooks, there's bound to be a Partner on the Marketplace that used those elements to create an app.

Merge Tickets by Knots (disclaimer, they sponsored this blog a few months ago) is such an app. It offers a nice UI to setup different conditions and it will then will automatically merge tickets that match those rules.

You can merge tickets with the same requester, category, subject or other custom field, add an internal note with information about the different merged tickets and even choose to turn comments from other tickets into internal comments.
The latter is useful if you combine information from different users. For example: a ticket from a customer complaining about a delayed delivery gets merged with the feedback from the delivery partner. You don't want either part to see each others' comments.

The app from Knots is only one of many on the Marketplace that offer similar capabilities, all in different forms and functions. I kinda like how this one integrates with the rest of their suite of ticket automation apps though.

Conclusion

The problem of duplicate tickets in support is an annoying issue. It inflates ticket numbers, duplicates agents work and might make appear certain topics bigger than they are in reporting if multiple copies of a ticket are raised by the same customer.

Self Service, good documentation and documented processes are a way to prevent duplicate tickets. Similarly, enabling an internal SLA on first reply time will motivate faster reply times, hopefully preventing customers' from duplicating requests due to lack or slowness of feedback.

But if those all fail, the native features in Zendesk – being it Customer Context for agents or AI suggestions – can downside this issue, and API integrations can assist with cleaning up tickets in bulk.