Ticket tagging taxonomy starter
A ready-to-adapt ticket tagging scheme built on separate fields for contact reason, root cause, and resolution, plus the naming, governance, and quarterly-maintenance rules that stop tag sprawl, for teams whose ticket data is too messy to report on.
What this is
A starter taxonomy for tagging support tickets, built around a single rule: every tag must change a decision. If a value never routes a ticket, triggers a workflow, or shows up in a report someone acts on, it is clutter. Delete it.
This is a starting point, not a finished scheme. Copy the tables below, keep the dimensions that map to decisions you actually make, fill the [bracketed] placeholders with your own product, and delete the rest before you turn tagging on for the team.
The three questions a good taxonomy keeps separate
Most tag fields are a mess because they cram three different questions into one list. Separate them and your reporting stops contradicting itself.
| Dimension | Answers the question | Example values |
|---|---|---|
| Contact reason | Why did the customer reach out? | Billing, Login, Bug, How-to, Feature request |
| Root cause | What was actually wrong? | Product defect, Docs gap, User error, Third-party |
| Resolution | What did we do about it? | Resolved, Workaround, Escalated, Refund, No action |
"Billing" is a reason. "Docs gap" is a cause. "Refund" is an outcome. A single ticket can be all three at once. If they share one field, you can never answer "how many billing tickets were caused by a docs gap and resolved with a refund" — which is the exact question that funds a fix. Keep them in separate fields.
Design principles
- Structured fields beat freeform tags for anything you report on. A drop-down for Contact reason gives clean counts. A freeform tag bucket gives you
login,log-in,Loginand three dashboards that disagree. Reserve freeform tags for genuinely ad-hoc flags. - Start with ~10–15 top-level reasons that cover most of your volume. Add a value only when a pattern is worth tracking, never in anticipation of one.
- One required level, optional depth. Make Contact reason mandatory. Make any sub-reason optional so a rep is never blocked when nothing fits perfectly.
- A ticket gets exactly one contact reason. Multi-select reasons destroy your ability to sum a report. Use the other fields for the other facts.
- Every value maps to a decision. Write that decision next to the value. If the "drives" column is blank, cut the value.
The starter taxonomy
Field 1 — Contact reason (required, single-select, set at open)
| Reason | Use when | Drives |
|---|---|---|
| Account & access | Login, permissions, seats, SSO | Routing, self-serve gaps |
| Billing & payments | Invoices, charges, plan changes | Finance loop, churn risk |
| Bug / not working | Something is broken | Bug reports, reliability trend |
| How-to / usage | "How do I…" questions | KB & self-serve backlog |
| Feature request | Wants something not built | Product backlog |
| Integration / API | Third-party or developer issues | Specialist routing |
| Onboarding / setup | New-customer configuration | Onboarding fixes |
| Cancellation / churn risk | Wants to leave or is unhappy | Retention play |
| Complaint / escalation | Formal complaint or demand | Escalation path |
| Other (review monthly) | Nothing above fits | Taxonomy diagnostic |
The Other bucket is a diagnostic, not a category. If it climbs past a few percent of volume, something real has no home — read a sample and add a value.
Field 2 — Product area (required, single-select, set at open)
Replace these with your own surfaces:
| Area | Owning team |
|---|---|
[Area A — e.g. Dashboard] | [team] |
[Area B — e.g. Mobile app] | [team] |
[Area C — e.g. Billing] | [team] |
[Area D — e.g. API] | [team] |
[Area E] | [team] |
Field 3 — Root cause (single-select, set at close)
| Value | Means |
|---|---|
| Product defect | A genuine bug — a ticket should be filed |
| Documentation gap | The answer exists but the customer couldn't find or follow it |
| Missing feature | The product doesn't do the thing |
| Expected behaviour | Working as designed, even if unwanted |
| User error | Mistake on the customer's side |
| Third-party / upstream | Caused by a system you don't own |
| Data / migration | Bad or missing data, import issues |
| Unknown | Genuinely couldn't determine |
Root cause is the field product and engineering actually read. Documentation gap and Missing feature are the two that pay for themselves — they turn a support queue into a prioritized backlog.
Field 4 — Resolution (single-select, set at close)
| Value | Means |
|---|---|
| Resolved by agent | Rep answered it directly |
| Self-serve pointer | Sent them to an existing article/answer |
| Workaround provided | Unblocked them without a real fix |
| Escalated (kept) | Sent up but rep owns the follow-up |
| Escalated (handed off) | Ownership moved to another team |
| Refund / credit | Money changed hands |
| No action needed | Nothing to do (info, thanks, spam) |
| Duplicate | Same issue as another ticket |
Field 5 — Flags (freeform / multi-select, optional)
Keep this list short: vip, at-risk, bug-filed, feature-logged, follow-up-needed, kb-candidate, coaching-example.
Naming conventions
- Lowercase, hyphenated, singular:
feature-request, notFeature Requests. - One concept, one value — retire synonyms (
loginvslog-in) on sight. - Never encode two facts in one value (
billing-refund). That is what separate fields are for. - Don't build a second taxonomy inside the freeform flag field.
Governance — decide these before you launch
- One named owner (
[name]) who is the only person allowed to add or retire values. - A request path: anyone can propose a value, the owner decides, changes get announced.
- A bar for adding a value: it must cover at least
[X]%of tickets or unlock one specific decision. - A definition doc: one line per value stating exactly when to use it. Ambiguity is what kills consistency.
Rollout checklist
- Draft the fields above with your real product areas filled in.
- Write the one-line definition for every value.
- Load them into the help desk as structured fields, not freeform, wherever you report.
- Set which fields are required at open (reason, product area) vs at close (root cause, resolution).
- Run a calibration session: take 10–15 sample tickets, have the whole team tag them independently, compare, and resolve every disagreement out loud. Repeat until people converge.
- Turn it on. Watch the Other and Unknown rates for the first two weeks.
Quarterly maintenance
- Pull tag-usage counts. Any value under
[1–2]%of volume: merge it up or retire it. - Check Other and Unknown rates. Rising numbers mean the scheme is drifting from reality.
- Spot-check 15 recently closed tickets for tagging accuracy. Low agreement means retrain the team or simplify the scheme.
- Delete any value whose "drives a decision" column has gone blank.
- Confirm every remaining value still maps to a live report, route, or workflow.
Anti-patterns to avoid
- Tag sprawl. A tidy list of 20 values quietly becomes 150 nobody trusts. Prune every quarter.
- The "General" / "Miscellaneous" dumping ground. A default that hides the real issue instead of naming it.
- Multi-select contact reasons. They make the totals un-sum-able.
- Freeform-only reporting. Typos and casing quietly split one category into five.
- Tagging for its own sake. If nobody reads a field, stop requiring it.
- Letting AI auto-tag into a taxonomy no human curates. A model will happily apply a broken scheme at scale — garbage in, confident garbage out. Fix the taxonomy first, then automate it.
Continue exploring