Turning Support Tickets Into FAQ Content With a Small Python Script
Support tickets are the most honest keyword research you have. Customers write questions in their own words, in their own language, and they repeat the ones your website fails to answer. Those same questions are what peo
Support tickets are the most honest keyword research you have. Customers write questions in their own words, in their own language, and they repeat the ones your website fails to answer. Those same questions are what people type into ChatGPT or Perplexity. This post shows a small script that groups ticket subjects into question clusters so a content team can turn the biggest clusters into FAQ answers.
Export and clean
Most helpdesks can export a CSV with a subject and a body. We only need the subject and the first customer message. Strip signatures, order numbers and email addresses before doing anything else; you do not want personal data in a content workflow.
import csv, re
from collections import defaultdict
def clean(text):
text = re.sub(r"\S+@\S+", " ", text) # emails
text = re.sub(r"#?\d{5,}", " ", text) # order or ticket numbers
text = re.sub(r"https?://\S+", " ", text) # links
return re.sub(r"\s+", " ", text).strip().lower()
rows = []
with open("tickets.csv", newline="", encoding="utf-8") as f:
for r in csv.DictReader(f):
rows.append(clean(r["subject"] + " " + r["body"][:300]))
Cluster with TF-IDF
You do not need embeddings for a first pass. TF-IDF plus a simple clustering step is fast, cheap and easy to explain to non-engineers.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
vec = TfidfVectorizer(stop_words="english", ngram_range=(1, 2), min_df=3)
X = vec.fit_transform(rows)
km = KMeans(n_clusters=25, n_init=10, random_state=1).fit(X)
clusters = defaultdict(list)
for text, label in zip(rows, km.labels_):
clusters[label].append(text)
terms = vec.get_feature_names_out()
for label, items in sorted(clusters.items(), key=lambda x: -len(x[1])):
centre = km.cluster_centers_[label].argsort()[-5:][::-1]
print(len(items), [terms[i] for i in centre], items[0][:90])
The output is a ranked list: cluster size, its top terms, and one example ticket. The top ten clusters usually cover more than half of all tickets.
From cluster to FAQ entry
For each large cluster, a person writes one question in the customer's phrasing and a direct answer of 40 to 80 words, followed by detail. Keep the answer specific: numbers, steps, limits. Publish the questions as visible text, and add FAQ markup only for what is shown on the page.
Multilingual tickets
If you serve several markets, run the script per language rather than translating everything into English first. The phrasing differs by market, and those differences are exactly what you want on localised pages.
Repeat quarterly
Rerun the script every quarter. New clusters signal product changes or confusing pages; shrinking clusters show which FAQ entries worked. This loop is one of the cheapest ways to produce content that both customers and answer engines find useful. It sits naturally inside a broader GEO process such as our ten-step GEO checklist.
Published by PandaWM, an overseas marketing team based in Hong Kong.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.