Customer Support Metrics: The 29 essential KPIs you should be tracking

Kostas Pardalis

Customer support is an important function of your company, and although in the past was considered more of a hassle that was keeping profits down, now people have started to realize that support is part of the product and the overall experience that a customer has.

In this context, customer support can contribute to the following, if it is run successfully,

  • Customer retention. By solving the problems that your customers have, you offer them a good reason to keep using your product.
  • Customer acquisition. Good customer support during the onboarding process of a new customer increases the chances of converting her into a paying customer. Additionally, happy customers are more likely to become evangelists of your product.
  • Product development. This is more apparent to startup founders, but it remains valid even when a company scales up. Customer support is a great channel for validating your product and a great source of information for your product roadmap.

But how can we offer excellent support to our customers? As with every other function in your company, from product development to marketing, the key is to start working on it early and try to understand what works for you and what not. The best way to do this is by measuring your activities and keeping track of a number of customer support metrics.

The good news is, that customer support is a function rich of data that is waiting for you to take advantage of. All it takes is to connect your favorite customer support tools with a database, and then you can easily calculate and keep track of all the customer support metrics that are relevant to you.

In this post we will go through the most important customer support metrics, calculated on data coming from one of the most popular platforms for customers support, which is Zendesk. Using Blendo, you may load all Zendesk data into a database and keep them synced, a process that it takes just a few minutes to setup. Then the customer support metrics can be calculated easily, using the queries that we will see in this post.

Customer Support Metrics Categories

No matter if you just start having your first customers or you are a multinational company, the categories of customer support metrics that are relevant, are always the same. What change is the scale of the data and how deep you should go into it to actually get your insights?

These important categories are the following:

  • Customer Experience. You should be able to understand what experience your customers perceive when they interact with your company through customer support. This is usually represented by a number of customer support metrics around Response Time.
  • Customer Satisfaction. How satisfied are you customers from the support their getting? Sounds important, right?
  • Workload. Your support agents are your hero but you need to take good care of them, at the end customer support is based on human interaction, and if one of the two participants is burned out, many bad things can happen. Additionally, as you scale up your business, your support should also scale and do this efficiently, these metrics will help you plan effectively.

So, based on these three categories we will have a number of customer support metrics, together with the queries that calculate them on data coming from Zendesk. Keep in mind that some metrics might overlap between the categories.

Customer Experience Metrics

Customer support is all about communicating effectively with your customers, this communication can significantly affect the process of resolving the issue reported by them. For this reason, it is important to understand the experience your customers are getting from your support.

There are plenty of metric related to customer experience when it comes to support, but the most fundamental ones are related to the Response Time, the time that it takes for your customer support team to respond to the customer queries.

First Response Time

It is the time it takes for your team to answer to a new ticket or customer question, for the first time. This can be measured as the minutes or hours (hopefully you will not opt for days) elapsed between the creation of a new ticket from a customer and the first message that a customer support representative sent as a reply.

A few things that you should keep in mind when working with the First Response Time metric.

As a metric, it can easily be manipulated or misleading. For example, your ticketing system, like Zendesk, might automatically respond whenever a new ticket is created. This automatic response shouldn’t be counted towards the First Response Time.

You should consider your working hours, if you do not offer 24/7 support then a ticket that is created outside your working hours, shouldn’t be measured towards the overall First Response Time, you could offset the creation time to the beginning of your working day.

As in other similar customer support metrics, you should consider different views of it, more specifically, you should take into consideration the average, median, minimum and maximum first response time.

The Average First Response Time

SELECT avg(firstResponse) from  
  (SELECT min(tmp2.ftr-tmp2.created_at) AS firstResponse
   FROM
     (SELECT a.time AS ftr, tmp1.created_at, a.ticket_id, a.metric
      FROM cont_ticket_metric_events AS a,
        (SELECT created_at, id
         FROM cont_tickets)tmp1
      WHERE (a.ticket_id=tmp1.id)
        AND (a.time>tmp1.created_at)
        AND a.metric = 'reply_time')tmp2
   GROUP BY tmp2.ticket_id)tmp3

The Minimum First Response Time

SELECT min(tmp2.ftr-tmp2.created_at) AS MinfirstResponse  
FROM  
  (SELECT a.time AS ftr,
          tmp1.created_at,
          a.ticket_id,
          a.metric
   FROM cont_ticket_metric_events AS a,
     (SELECT created_at, id
      FROM cont_tickets)tmp1
   WHERE (a.ticket_id=tmp1.id)
     AND (a.time>tmp1.created_at)
     AND a.metric = 'reply_time')tmp2

The Maximum First Response Time

SELECT max(firstResponse) from  
  (SELECT min(tmp2.ftr-tmp2.created_at) AS firstResponse
   FROM
     (SELECT a.time AS ftr, tmp1.created_at, a.ticket_id, a.metric
      FROM cont_ticket_metric_events AS a,
        (SELECT created_at, id
         FROM cont_tickets)tmp1
      WHERE (a.ticket_id=tmp1.id)
        AND (a.time!=tmp1.created_at)
        AND a.metric = 'reply_time')tmp2
   GROUP BY tmp2.ticket_id)tmp3

The Median First Response Time

SELECT median(extract(epoch FROM firstResponse)/60)  
FROM  
  (SELECT min(tmp2.ftr-tmp2.created_at) AS firstResponse
   FROM
     (SELECT a.time AS ftr,
             tmp1.created_at,
             a.ticket_id,
             a.metric
      FROM cont_ticket_metric_events AS a,
        (SELECT created_at, id
         FROM cont_tickets)tmp1
      WHERE (a.ticket_id=tmp1.id)
        AND (a.time!=tmp1.created_at)
        AND a.metric = 'reply_time')tmp2
   GROUP BY tmp2.ticket_id)tmp3

 

First Resolution Time

Is the time it took until the ticket was marked as resolved by the customer support agent for the first time. We say first time because it is not uncommon for a ticket to be reopened by the customer with further questions.

The first resolution time metric is an indication of the efficiency of customer support. Ideally, we’d like none of the tickets to be reopened while reducing this time as much as possible. This time is also perceived by the customer, and thus it affects her experience.

The Average First Resolution Time

SELECT avg(first_resolution-first_activation)  
FROM  
  (SELECT min(TIME) AS first_activation,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE (TYPE='activate')
   GROUP BY ticket_id)act
RIGHT JOIN  
  (SELECT min(TIME) AS first_resolution,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE TYPE='fulfill'
   GROUP BY ticket_id)ful ON act.ticket_id=ful.ticket_id

The Maximum First Resolution Time

SELECT max(first_resolution-first_activation)  
FROM  
  (SELECT min(TIME) AS first_activation,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE (TYPE='activate')
   GROUP BY ticket_id)act
RIGHT JOIN  
  (SELECT min(TIME) AS first_resolution,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE TYPE='fulfill'
   GROUP BY ticket_id)ful ON act.ticket_id=ful.ticket_id

The Minimum First Resolution Time

SELECT min(first_resolution-first_activation)  
FROM  
  (SELECT min(TIME) AS first_activation,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE (TYPE='activate')
   GROUP BY ticket_id)act
RIGHT JOIN  
  (SELECT min(TIME) AS first_resolution,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE TYPE='fulfill'
   GROUP BY ticket_id)ful ON act.ticket_id=ful.ticket_id

The Median First Resolution Time

SELECT median(extract(epoch  
                      FROM (first_resolution-first_activation))/60)
FROM  
  (SELECT min(TIME) AS first_activation,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE (TYPE='activate')
   GROUP BY ticket_id)act
RIGHT JOIN  
  (SELECT min(TIME) AS first_resolution,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE TYPE='fulfill'
   GROUP BY ticket_id)ful ON act.ticket_id=ful.ticket_id

 

Full Resolution Time

Another metric that usually works well together with First Resolution Time is the Full Resolution Time. This is the time between ticket creation and the timestamp of the latest change of the ticket status into “solved”.

Ideally, we’d like to see the two resolution times to be as close together as possible. A low Full Resolution Time which is close to the First Resolution Time, means that our team is reaching the holy grail of customer support which is to being able to solve the problems of our customers with the first communication that we have.

The Average Full Resolution Time

SELECT avg(first_resolution-first_activation)  
FROM  
  (SELECT min(TIME) AS first_activation,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE (TYPE='activate')
   GROUP BY ticket_id)act
RIGHT JOIN  
  (SELECT max(TIME) AS first_resolution,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE TYPE='fulfill'
   GROUP BY ticket_id)ful ON act.ticket_id=ful.ticket_id

The Maximum Full Resolution Time

SELECT max(first_resolution-first_activation)  
FROM  
  (SELECT min(TIME) AS first_activation,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE (TYPE='activate')
   GROUP BY ticket_id)act
RIGHT JOIN  
  (SELECT max(TIME) AS first_resolution,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE TYPE='fulfill'
   GROUP BY ticket_id)ful ON act.ticket_id=ful.ticket_id

The Minimum Full Resolution Time

SELECT min(first_resolution-first_activation)  
FROM  
  (SELECT min(TIME) AS first_activation,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE (TYPE='activate')
   GROUP BY ticket_id)act
RIGHT JOIN  
  (SELECT max(TIME) AS first_resolution,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE TYPE='fulfill'
   GROUP BY ticket_id)ful ON act.ticket_id=ful.ticket_id

The Median (in minutes) Full Resolution Time

SELECT median(extract(epoch  
                      FROM (first_resolution-first_activation))/60)
FROM  
  (SELECT min(TIME) AS first_activation,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE (TYPE='activate')
   GROUP BY ticket_id)act
RIGHT JOIN  
  (SELECT max(TIME) AS first_resolution,
          ticket_id
   FROM cont_ticket_metric_events
   WHERE TYPE='fulfill'
   GROUP BY ticket_id)ful ON act.ticket_id=ful.ticket_id

 

Requester Wait Time

Another important metric of customer experience is the time the client has to wait for a response from an agent.

If you think of customer support as a dialog between the customer and your company, every time the customer sends you a message it takes some time for the agent to respond back.

The total amount of this time is something that affects the overall experience that a customer has and thus it is important to keep track of it.

The Average Requester Wait Time

SELECT avg(tmp2.activations-tmp2.fulfillments) AS RequesterWaitingTime  
FROM  
  (SELECT ticket_id, sum(CASE
                  WHEN tmp.type='activate' THEN minutes
                  ELSE NULL
              END) AS activations,
          sum(CASE
                  WHEN (tmp.type='fulfill' or tmp.type='paused') THEN minutes
                  ELSE NULL
              END) AS fulfillments
   FROM
     (SELECT ticket_id,
             metric,
             TIME,
             TYPE,
             now()-TIME AS minutes
      FROM cont_ticket_metric_events
      WHERE metric = 'requester_wait_time'
        AND TYPE IN('activate',
                    'paused',
                    'fulfill') )tmp
  group by ticket_id )tmp2

The Minimum Requester Wait Time

SELECT min(tmp2.activations-tmp2.fulfillments) AS RequesterWaitingTime  
FROM  
  (SELECT ticket_id, sum(CASE
                  WHEN tmp.type='activate' THEN minutes
                  ELSE NULL
              END) AS activations,
          sum(CASE
                  WHEN (tmp.type='fulfill' or tmp.type='paused') THEN minutes
                  ELSE NULL
              END) AS fulfillments
   FROM
     (SELECT ticket_id,
             metric,
             TIME,
             TYPE,
             now()-TIME AS minutes
      FROM cont_ticket_metric_events
      WHERE metric = 'requester_wait_time'
        AND TYPE IN('activate',
                    'paused',
                    'fulfill') )tmp
  group by ticket_id )tmp2

The Maximum Requester Wait Time

SELECT max(tmp2.activations-tmp2.fulfillments) AS RequesterWaitingTime  
FROM  
  (SELECT ticket_id, sum(CASE
                  WHEN tmp.type='activate' THEN minutes
                  ELSE NULL
              END) AS activations,
          sum(CASE
                  WHEN (tmp.type='fulfill' or tmp.type='paused') THEN minutes
                  ELSE NULL
              END) AS fulfillments
   FROM
     (SELECT ticket_id,
             metric,
             TIME,
             TYPE,
             now()-TIME AS minutes
      FROM cont_ticket_metric_events
      WHERE metric = 'requester_wait_time'
        AND TYPE IN('activate',
                    'paused',
                    'fulfill') )tmp
  group by ticket_id )tmp2

The Median Requester Wait Time

SELECT median(extract(epoch  
                      FROM (tmp2.activations-tmp2.fulfillments))/60)
FROM  
  (SELECT ticket_id, sum(CASE
                  WHEN tmp.type='activate' THEN minutes
                  ELSE NULL
              END) AS activations,
          sum(CASE
                  WHEN (tmp.type='fulfill' or tmp.type='paused') THEN minutes
                  ELSE NULL
              END) AS fulfillments
   FROM
     (SELECT ticket_id,
             metric,
             TIME,
             TYPE,
             now()-TIME AS minutes
      FROM cont_ticket_metric_events
      WHERE metric = 'requester_wait_time'
        AND TYPE IN('activate',
                    'paused',
                    'fulfill') )tmp
  group by ticket_id )tmp2

 

Customer Support Workload Metrics

While it is of paramount importance to track the experience of your customers as they interact with your support, it is equally important to also measure how the support “machine” of your company behaves. Again there are plenty of different metrics that can be tracked over the Zendesk data. Here we will focus on some of the most important ones.

Tickets By Group

As your company grows bigger, sooner or later you will need to create different groups of support agents.

You might have a group of first contact agents who will try to solve the issues as soon as possible. Then, as the severity of the problem increases, an engineer might have to get involved, she will be part of another group.

It is not uncommon to have different groups of agents inside the customer support function of a company and thus it is important to keep track of how each group performs.

This is not only about performance if too many tickets end up being handled by your engineers you might have to reconsider your documentation or check with the product team to see what’s going wrong.

Tickets By Group

SELECT count(group_id),  
       group_id,
       tmp.name
FROM cont_tickets,  
  (SELECT name,
          id
   FROM cont_groups) tmp
WHERE tmp.id=cont_tickets.group_id  
GROUP BY group_id,  
         tmp.name

Another useful and related metric is the number of new tickets per group. Again, adjust the query accordingly to the timeframe you’d like to track the creation of new tickets per group on Zendesk.

New Tickets By Group

SELECT count(group_id) as NewTickets,  
       group_id,
       tmp.name
FROM cont_tickets,  
  (SELECT name,
          id
   FROM cont_groups) tmp
WHERE tmp.id=cont_tickets.group_id and status='new'  
GROUP BY group_id,  
         tmp.name

 

How many tickets get passed between groups?

Related to the previous customer support metric, it is important to not only keep an eye on the tickets per group but also, to know how tickets are exchanged between them.

This metric will help you understand if there’s a bottleneck between your groups and if you have assigned the appropriate responsibilities to each one of them.

SELECT count(*) AS passed  
FROM cont_ticket_events  
WHERE child_events_group_id != ''

 

Basic Ticket Statistics

There are some very basic metrics that you should track, regarding tickets. These are the following:

  • Number of new tickets
  • Number of solved tickets
  • Percentage of solved tickets
  • Number of one touch tickets

All the above metrics make sense inside a time frame, which might differ depending on your business context. So, adjust the queries accordingly to calculate the above metrics for the time frame you are interested.

The number of one touch tickets is quite interesting as a customer support metric. It shows the number of tickets that your agents did extremely well, as the solution was given to just one response, but also it might indicate suitable candidates for documentation entries.

So, if you see a recurrent question which is easily answered, then it might be a good idea to create a new entry about this question to your FAQ if you don’t have one already.

Number of New Tickets

SELECT count(CASE  
                 WHEN status ='new' THEN 1
                 ELSE NULL
             END) AS NEW
FROM cont_tickets

Number of Solved Tickets

SELECT count(*)  
FROM cont_tickets  
WHERE status = 'solved'

Percentage of Solved Tickets

SELECT 100*CAST (tmp.solved AS decimal)/cast(tmp.total AS decimal) AS percentage  
FROM  
  (SELECT count(CASE
                    WHEN status ='solved' THEN 1
                    ELSE NULL
                END) AS solved,
          count(*) AS total
   FROM cont_tickets) tmp

Number of One Touch Tickets

SELECT DISTINCT count(*)  
FROM cont_ticket_events a,  
  (SELECT count(child_events_comment_public) AS cnt,
          ticket_id
   FROM cont_ticket_events
   WHERE (child_events_event_type = 'Comment')
   GROUP BY ticket_id) tmp
WHERE a.ticket_id=tmp.ticket_id  
  AND tmp.cnt<=1

 

Ticket Creation Time Distribution

Another very useful customer support metric is how the creation of new tickets is distributed in time. Is there a specific time where more tickets are created? Do you get a lot of tickets during weekends?

These questions are important when you need to plan your customer support workforce accordingly to your needs while maintaining good response times.

Ticket Creation Time Distribution

SELECT date_part('hour', created_at) AS hours, 
       to_char(created_at, 'day')    AS day, 
       count(*)                      AS count 
FROM   cont_tickets 
GROUP  BY to_char(created_at, 'day'), 
          date_part('hour', created_at) 
ORDER  BY date_part('hour', created_at)ASC;

Ticket Distribution over Submission Channels

Nowadays, customer support happens across many different channels, you might exchange messages with your customer through social media and email at the same time.

So, it is important to track how tickets are distributed across the different communication channels that you maintain.

Ticket Distribution over Submission Channels

 select via_channel, count(*) from cont_tickets  
group by via_channel

Keeping track of the ticket backlog

A commonly used term in customer support is the “backlog”. Which is a nice way of referring to the “work in progress” that a customer support team has? The size of the backlog indicates the efficiency of your team, and it might signal the need for adding new members to it.

Backlog

SELECT *  
FROM cont_tickets  
WHERE status != 'closed'  
  AND DATE_PART('day', now()-created_at)*24+DATE_PART('hour',now()-created_at) <=24

 

Ticket distribution per agent

So far we have covered the metrics related to the teams. But it is important to track the workload also on an individual agent level.

If for any reason you have agents who have more work than they can handle, you should act and rebalance their workload. There’s nothing worse than agents with a burnout trying to solve complex issues from your customers.

Ticket Distribution per Agent

SELECT a.name,  
       tmp.count
FROM cont_users AS a,  
  (SELECT count(assignee_id) AS COUNT,
          assignee_id
   FROM cont_tickets
   GROUP BY assignee_id)tmp
WHERE tmp.assignee_id = a.id

 

Customer Satisfaction

Customer satisfaction is another important set of customer support related metrics that you should keep track of.

The best way of measuring customer satisfaction is through surveys that you send to your customers to give you feedback regarding the quality of the customer support they have received so far.

Zendesk offers a mechanism where whenever a ticket is closed a mail is sent to the customer to give feedback regarding the service, so there’s no excuse to not measure the satisfaction of your customers.

Customer Satisfaction

SELECT count(CASE  
                 WHEN satisfaction_rating_score ='unoffered' THEN 1
                 ELSE NULL
             END) AS unoffered,
       count(CASE
                 WHEN satisfaction_rating_score ='offered' THEN 1
                 ELSE NULL
             END) AS offered,
       count(CASE
                 WHEN satisfaction_rating_score ='bad' THEN 1
                 ELSE NULL
             END) AS bad,
       count(CASE
                 WHEN satisfaction_rating_score ='good' THEN 1
                 ELSE NULL
             END) AS good
FROM cont_tickets

Finally, you can also measure the customer satisfaction on a per agent level to see who interacts better with the customers or who might need some additional training.

Customer Satisfaction per agent

SELECT a.name,  
       tmp.unoffered,
       tmp.offered,
       tmp.bad,
       tmp.good
FROM cont_users as a,  
  (SELECT assignee_id,
          count(CASE
                    WHEN satisfaction_rating_score ='unoffered' THEN 1
                    ELSE NULL
                END) AS unoffered,
          count(CASE
                    WHEN satisfaction_rating_score ='offered' THEN 1
                    ELSE NULL
                END) AS offered,
          count(CASE
                    WHEN satisfaction_rating_score ='bad' THEN 1
                    ELSE NULL
                END) AS bad,
          count(CASE
                    WHEN satisfaction_rating_score ='good' THEN 1
                    ELSE NULL
                END) AS good
   FROM cont_tickets
   GROUP BY assignee_id)tmp
WHERE tmp.assignee_id=a.id

 

Conclussions

We have seen a number of queries that can be used to calculate a set of customer support metrics that can give a good overall view of how our customer support operates. These metrics are easy to calculate and keep track of and are relevant to any size of the company. With these queries as the foundation, you can create some beautiful dashboards that can help you keep track of your customer support performance on a daily basis, but this is something that we will investigate in a future blog post.

So give a try to Blendo its free for 14 days, load your customer support data into a database and start measuring your customer support metrics. Let me know how it goes with your queries. Good luck.

 

Become a Data Analytics superhero!

Upgrade your skills! Your company will love you and we too 😉