Freshdesk model

Agent performance by month

Per agent per month: replies sent, tickets they gave the first response on and how fast, tickets currently assigned to them, and the CSAT they received.

Grain
month x freshdesk_account x agent
Built from
  1. 6
    Raw tables
  2. 5
    Staging
  3. 2
    Core
  4. 1
    Analytics
Reads from Freshdesk
agentgroupsatisfaction_ratingsatisfaction_rating_valueticketticket_conversation
Ships as
Weld and dbt SQL, open source on GitHub
core.freshdesk.agent_performance_by_month
1-- core.freshdesk.agent_performance_by_month
2-- Per agent per month: replies sent, tickets they gave the first response on and
3-- how fast, tickets currently assigned to them, and the CSAT they received.
4-- Grain: month x freshdesk_account x agent.
5-- Depends on: core.freshdesk.ticket_lifecycle, staging.freshdesk.ticket_conversation,
6--             staging.freshdesk.satisfaction_rating, staging.freshdesk.agent
7--
8-- Each column is dated on its own event and attributed to the agent who did it:
9--   replies_sent          the reply's date, the agent who sent it
10--   first_responses       the first reply's date, the agent who sent it
11--   tickets_assigned      the ticket's creation date, its CURRENT assignee
12--                         (no assignment history is synced)
13--   csat_*                the survey answer's date, the agent on the response
14-- So never divide one column by another from a different line above and call it
15-- a rate. Medians do not roll up across months.
16
17WITH tz AS (
18    SELECT DISTINCT freshdesk_account, reporting_timezone
19    FROM {{staging.freshdesk.ticket}}
20),
21
22replies AS (
23    SELECT
24        c.freshdesk_account,
25        c.user_id                                       AS agent_id,
26        DATE_TRUNC(DATE(c.created_at, tz.reporting_timezone), MONTH) AS month,
27        COUNT(*)                                        AS replies_sent
28    FROM {{staging.freshdesk.ticket_conversation}} c
29    JOIN tz ON tz.freshdesk_account = c.freshdesk_account
30    JOIN {{staging.freshdesk.agent}} a
31      ON a.freshdesk_account = c.freshdesk_account
32     AND a.agent_id          = c.user_id
33    WHERE NOT COALESCE(c.is_incoming, FALSE)
34      AND NOT COALESCE(c.is_private, FALSE)
35      AND c.source_code IS DISTINCT FROM 2
36      AND NOT c.is_auto_response
37    GROUP BY 1, 2, 3
38),
39
40first_responses AS (

This model and the 7 it depends on. Deploy them together; refs like {{staging.…}} resolve to the matching folders in Weld, and the dbt view uses source() and ref().

Notes

How it counts. And where it stops.

Each column is dated on its own event and attributed to the agent who did it: replies_sent the reply's date, the agent who sent it first_responses the first reply's date, the agent who sent it tickets_assigned the ticket's creation date, its CURRENT assignee (no assignment history is synced) csat_* the survey answer's date, the agent on the response So never divide one column by another from a different line above and call it a rate. Medians do not roll up across months.

Raw tables it reads

  • raw.freshdesk.agent
  • raw.freshdesk.group
  • raw.freshdesk.satisfaction_rating
  • raw.freshdesk.satisfaction_rating_value
  • raw.freshdesk.ticket
  • raw.freshdesk.ticket_conversation

Put Freshdesk in front
of your agents.

Connect Freshdesk, deploy the models, and ask questions in Claude, Cursor or ChatGPT. Free for 14 days, no credit card.