Module 7: Synthesizing And Deciding
Clustering findings by problem: `clusterByProblem`
Overview
You have, at this point, eight behavioral interviews' notes —run with the script you audited in module 2— plus the fake door result you ran in module 5. That's a lot of loose information, each piece noted separately, in the order it came in. Before you can say anything useful about that evidence, you need the first step, the simplest one but the one most often skipped: clustering it by the problem it describes, not by the order you collected it, and not by which buyer said it.
How this connects to the module. This lesson builds synthesize()'s first piece, the function you're going to complete in lesson 4 and run with no changes at all in lesson 8's project. clusterByProblem() doesn't count signals yet —that's lesson 3—, and doesn't classify anything as signal or noise —that's lesson 4—. It only does one thing, done well: group together what talks about the same thing, so the following lessons have something organized to work with.
An everyday analogy: freshly washed laundry
After washing several loads of laundry —maybe from different days, maybe mixed together in a rush— you have a pile on the bed: t-shirts, socks, towels, all jumbled together. Nobody puts laundry away in that state. The first thing you do, before folding anything, is sort by type: t-shirts in one pile, socks in another, towels in another. You don't decide yet which t-shirts to keep and which to donate —that comes later, with more judgment—; you just group what's the same type, so you can think about each group separately.
Mercado's eight interview notes are, arriving at this module, exactly like that pile on the bed: a note from buyer 3 about new sellers, followed by a note from buyer 5 about the forgotten cart, followed by another note from buyer 1 —again— about products they can't find. clusterByProblem() is the first step of folding the laundry: no judgment yet, just grouping what's the same type.
Worked example: clusterByProblem() over Mercado's 8 interview notes
These are the real notes, as they came out after running the eight interviews with module 2's audited script. Each note logs which buyer (user) mentioned which problem (problem), and whether the team suggested it beforehand or the buyer brought it up on their own (unprompted) — this last field isn't used yet in this lesson; you'll need it starting in lesson 3.
// L2: clusterByProblem() -- clusters Mercado's interview findings by
// problem, without yet telling signal apart from noise (that's L3-L4).
function clusterByProblem(findings) {
const clusters = {};
findings.forEach((f) => {
if (!clusters[f.problem]) clusters[f.problem] = [];
clusters[f.problem].push(f);
});
return Object.keys(clusters).map((problem) => ({
problem,
mentions: clusters[problem].length,
})).sort((a, b) => b.mentions - a.mentions);
}
// The real notes from the 8 behavioral interviews (module 2's script),
// already run with Mercado buyers. Each note logs the problem the buyer
// mentioned and whether the team suggested it beforehand (unprompted).
const findings = [
{ user: 'buyer_01', problem: "I don't discover products I'd like without searching for the exact name", unprompted: true },
{ user: 'buyer_01', problem: "I don't discover products I'd like without searching for the exact name", unprompted: true },
{ user: 'buyer_02', problem: "I don't discover products I'd like without searching for the exact name", unprompted: true },
{ user: 'buyer_02', problem: 'I forget about my cart and never go back to finish it', unprompted: true },
{ user: 'buyer_03', problem: "I don't trust new sellers without reviews", unprompted: true },
{ user: 'buyer_04', problem: "I don't discover products I'd like without searching for the exact name", unprompted: false },
{ user: 'buyer_05', problem: 'I forget about my cart and never go back to finish it', unprompted: true },
{ user: 'buyer_06', problem: "I don't discover products I'd like without searching for the exact name", unprompted: true },
{ user: 'buyer_07', problem: 'I forget about my cart and never go back to finish it', unprompted: true },
{ user: 'buyer_08', problem: 'the app crashes on its own when the phone has low memory', unprompted: true },
];
console.log('=== clusterByProblem() over the 10 notes from the 8 interviews ===\n');
const clustered = clusterByProblem(findings);
clustered.forEach((c) => {
console.log(' ' + String(c.mentions).padStart(2) + ' mention(s) -- "' + c.problem + '"');
});
What to expect. When you run the file with Node, the output is exactly this:
=== clusterByProblem() over the 10 notes from the 8 interviews ===
5 mention(s) -- "I don't discover products I'd like without searching for the exact name"
3 mention(s) -- "I forget about my cart and never go back to finish it"
1 mention(s) -- "I don't trust new sellers without reviews"
1 mention(s) -- "the app crashes on its own when the phone has low memory"
Ten raw notes turn into four clear groups, sorted by how many mentions each one has. Notice something important, which the next lesson is going to fix: the 5 mention(s) count for "I don't discover products..." doesn't yet mean it's the strongest signal of the four — it only means there are five notes about that problem, no matter whether they came from a single very talkative buyer or from several different buyers, and no matter whether some of those mentions were suggested by the team itself during the interview. That's exactly the gap clusterByProblem() deliberately leaves open: it clusters well, but it still can't tell apart five mentions from the same buyer repeating themselves from five different buyers saying the same thing without coordinating.
Why cluster by problem and not something else
You could cluster the notes many different ways: by buyer, by chronological interview order, by how long the answer was. None of those other ways get you closer to a decision about recommendations. Clustering by problem is the only one that answers this module's truly important question: which user needs show up again and again, without anyone suggesting them? — the same question module 3's opportunity solution tree already started mapping with its problem: '...' opportunities, and that this module picks back up with real collected evidence, not planning hypotheses.
Common mistakes
Clustering by buyer instead of by problem. What happens: someone on the team puts together a summary of "what each buyer said" —eight paragraphs, one per interview— instead of a summary of "which problems came up and how many times." Why it happens: the notes naturally arrive organized by interview —each session produces its own document—, and reorganizing them by topic requires an extra step that feels optional. How to spot it: if you ask the team "how many different buyers mentioned the not-finding-products problem?", they have to reread all eight full interviews to answer, instead of looking at an already-clustered summary. How to fix it: run clusterByProblem() —or its hand-done equivalent on a whiteboard— as soon as the last interview finishes, before the team starts discussing what the evidence means.
Creating a new cluster for every wording variation of the same problem. What happens: "I don't discover products I'd like" and "I can't find things that would interest me" end up in two different clusters, even though they describe exactly the same buyer need, just because the text strings don't match letter for letter. Why it happens: clusterByProblem(), as written, groups by exact equality of the problem string — it doesn't understand synonyms or paraphrasing, so two notes saying the same thing in different words end up separated. How to spot it: the cluster list has more entries than the team expected, and several of them, read side by side, clearly describe the same idea. How to fix it: before running clusterByProblem(), someone on the team —not the code— has to normalize each note's wording into a common phrase per problem, exactly like problem got normalized when mapping the opportunity solution tree in module 3. The algorithm groups well what's already well written; it doesn't replace human judgment on what counts as "the same problem."
Exercises
Exercise 1 — Add a ninth interview. Without running Node, if this new note got added to the findings list — { user: 'buyer_09', problem: 'I forget about my cart and never go back to finish it', unprompted: true } — how would clusterByProblem()'s result change? Be specific about which cluster changes and which stays the same.
See solution
Only the "I forget about my cart and never go back to finish it" cluster changes: it goes from 3 mention(s) to 4 mention(s), and with that it would tie for first place with "I don't discover products..." if that note had had four instead of five — but since "I don't discover..." stays at 5, the overall order doesn't change, only the second cluster's number. The other two clusters —"I don't trust new sellers..." and "the app crashes on its own..."— stay exactly the same, with 1 mention(s) each, because the new note doesn't touch them.
Exercise 2 — Count the clusters, not the mentions. Without running Node, how many different clusters does clusterByProblem() produce over the worked example's ten notes? Does that number match the number of interviews (8) or the number of notes (10)? Explain why it doesn't have to match either.
See solution
It produces 4 clusters. It doesn't match the 8 interviews (because several buyers mentioned the same problem, so several interviews fall into the same cluster) or the 10 notes (because a note is an individual mention, and several mentions —like the 5 for "I don't discover products..."— fall inside a single cluster). The number of clusters depends solely on how many different problems showed up across the full set of notes — it can be smaller or, in theory, even equal to the number of notes, if every note described a problem no other note mentioned.
Exercise 3 — Explain why the mentions order isn't enough to decide. In 2-3 sentences, explain why the cluster with the most mentions ("I don't discover products...", with 5) isn't automatically the one that should get the team's most attention — getting ahead, without running anything yet, of the problem lesson 3 solves.
See solution
mentions counts notes, not people — and a note can come from a buyer who repeated the same idea twice in the same interview, or from a question where the interviewer themselves already suggested the problem before the buyer said it. A cluster with mentions: 5 could, in the extreme case, come from a single very talkative buyer, while a cluster with mentions: 3 could come from three completely different buyers who never talked to each other. The second situation is much stronger evidence than the first, even though the mention count is lower — exactly the problem countUnpromptedUsers(), in lesson 3, solves by counting people, not notes.
Summary and next step
In this lesson you built clusterByProblem(findings): it clusters Mercado's eight interviews' raw notes by the problem they describe, without yet judging which of those groups is real evidence. Over the worked example's ten notes, the result was clear: four different problems, with "I don't discover products I'd like..." leading with 5 mentions — the first, organized step toward a real synthesis.
Before moving on you should be able to: explain why you cluster by problem and not by buyer or chronological order; and recognize, in your own words, why a cluster's mentions count, on its own, still doesn't tell you whether that evidence is strong or weak.
Lesson 3 takes exactly that gap and closes it: instead of counting notes, you're going to count different people — the first real step toward telling signal apart from noise.
Resources
- Teresa Torres, "The Interview Snapshot: How to Synthesize and Share What You Learned from a Single Customer Interview" — producttalk.org/interview-snapshot. The one-page artifact a continuous discovery team builds after every interview — the source of the notes
clusterByProblem()clusters in this lesson. In English. - Steve Portigal, Interviewing Users (2nd edition) — rosenfeldmedia.com/books/interviewing-users-second-edition. Its chapter on analysis and synthesis distinguishes exactly these two steps: first breaking the notes into small pieces (analysis), then bringing those pieces together into bigger patterns (synthesis) — the work that starts in this lesson. In English.
- Teresa Torres, Continuous Discovery Habits — producttalk.org/continuous-discovery-habits. The chapter on mapping opportunities uses the same problem-clustering criterion you already saw in this guide's module 3 opportunity solution tree — here it gets applied to collected evidence, not planning hypotheses. In English.