Why "loved your latest video" now reads as spam
Outbound is sales where you reach out first, the opposite of inbound where the prospect contacts you. The dominant flavor over the past few years has been signal-based outbound. A signal is an observable change at the target company: a new job posting, a funding round, a video the founder just published. You detect the signal and open your email by mentioning it.
The problem is that detecting and mentioning is trivially easy to automate. A script that scrapes a YouTube title, summarizes it, prepends "really enjoyed your latest video," and moves on to the pitch takes half a day to build. So everyone sends the same thing. On the receiving end, that sentence is no longer evidence that someone looked at you. It is evidence that someone ran a tool.
Choi Hyun-jong, who leads go-to-market at AB180, put it bluntly in a recent interview: this play is dead. One of the things a salesperson must not do is exactly what everyone else is doing, and signal name-dropping is now precisely that. In the same interview the host said he receives close to 300 partnership emails a month and discards 98% of them, because the format is identical every time.
So what is left? Anything easy to automate no longer differentiates. What you need is something that is still automated but genuinely costs effort to produce. That is the subject of this article.
What to send instead — a document they can use today
What people put in a first touch has evolved through three stages. Stage one is a well-written message. Stage two is a useful asset: an industry report, a relevant case study. Stage three, the subject here, is building an actual deliverable for that specific company and handing it over.
That third stage is what Choi demonstrated. Selling to overseas subscription-app founders, he found they were all sitting on the same question — what should we fix first — so he built reports that pulled their app's store reviews and analyzed them. On the screen shown in the interview, a Duolingo report covered 1,000 reviews, classified 118 of them as churn signals, split iOS against Android, surfaced eight recurring patterns, and closed with what to address first.
From the recipient's side this is not an ad. It is about their own company, answering a question they already had. That is why it gets read to the end. That is the entire mechanism.
There are two goals. The obvious one is booking a meeting. The second is that even if they do not buy now, you are the first person they think of when the problem actually bites. Choi argues the second is far more likely, and defines the core of sales as making the customer come to you when they have a problem.
So design one thing into the report: do not give everything. Leave a passage that says "you can verify this part yourself, but this other part requires our data." That is what creates a reason to talk. A document that only helps ends with a thank-you note.
Where do the reviews come from — App Store

From here on, this is not from the interview. The video shows only the finished report; it never says how the data was collected. What follows is a path that actually works for building the same thing.
Apple publishes a customer review feed for every app. No developer account, no API key, no login. If you know the URL it opens in a browser. The response is JSON.
First you need the app's numeric ID. It is the number after id in the App Store web URL, and the search API returns it directly.
curl -s "https://itunes.apple.com/search?term=duolingo&country=kr&entity=software&limit=5" | jq -r '.results[] | [.trackId, .trackName] | @tsv'APP=570060128
for p in $(seq 1 10); do
curl -s "https://itunes.apple.com/kr/rss/customerreviews/page=$p/id=$APP/sortby=mostrecent/json" | jq -c '.feed.entry[]? | {rating: .["im:rating"].label, version: .["im:version"].label, title: .title.label, body: .content.label}'
done > reviews-kr.jsonl
wc -l reviews-kr.jsonlWhere the 500 ceiling comes from

The loop stops at 10 for a reason. The feed returns 50 reviews per page and only pages 1 through 10 exist. Request page 11 and you get an error instead of JSON. So 500 is the maximum from one store in one country.
That also explains how the interview's 1,000 was possible. Swap kr for us or jp in the URL and you get another 500 from that country's store. Add Android and the total climbs well past that. One caution when mixing countries: complaints differ by market, so keep the country as a field in your data. Otherwise you cannot later say "billing complaints cluster in Japan."
The sort option is adjustable too. Change sortby=mostrecent to mosthelpful and reviews with the most helpful votes come first. Use recency to see what broke in the latest build, and helpfulness to see long-standing grievances.
What about Google Play
Google does not expose a public feed like Apple's. Use an open-source package instead. google-play-scraper is the de facto standard; the version at the time of writing is 10.1.3. The app ID here is a package name rather than a number — the value after id= in the Play Store URL (com.duolingo for Duolingo).
Each call returns up to 200 reviews plus a token pointing at the next page. Feed that token back in to continue. The script below loops five times for 1,000 reviews.
npm init -y
npm i google-play-scraperimport gplay from "google-play-scraper";
const out = [];
let token;
for (let i = 0; i < 5; i++) {
const r = await gplay.reviews({
appId: "com.duolingo",
lang: "ko",
country: "kr",
sort: gplay.sort.NEWEST,
num: 200,
nextPaginationToken: token,
});
out.push(...r.data);
token = r.nextPaginationToken;
if (!token) break;
}
for (const r of out) {
console.log(JSON.stringify({ rating: r.score, version: r.version, body: r.text }));
}node reviews-play.mjs > reviews-play.jsonl
wc -l reviews-play.jsonlHow raw reviews become a report
A pile of raw reviews is worth nothing on its own. The prospect can read their own reviews. Value appears at classification. Fix your axes in advance, sort everything along them, then count how many fall in each axis and which app version they cluster around. That is the skeleton of the report.
Five axes are enough. The set below is a general-purpose starting point for app products; swap one or two to fit the prospect's category.
| Axis | What it holds | Why it matters |
|---|---|---|
| Churn signal | Deleted it, cancelled, switched | The only axis tied directly to revenue |
| Feature request | Missing this makes it painful | Evidence for roadmap priority |
| Billing complaint | Too expensive, no refund, auto-renew | One step before churn in subscriptions |
| Bug | Breaks on a specific screen or build | Pair with version and the cause narrows |
| Praise | This is why I use it | Goes straight into marketing copy |
A human does not do the classifying
Reading 500 reviews by hand costs a day. Then the method does not scale, and if it does not scale it is not outbound. Hand classification to the model and keep only the axis definition for yourself.
One command does it. The form below pipes the JSONL you just built straight into standard input.
claude -p "This is app-review JSONL. Classify each line as one of churn/feature/billing/bug/praise. Output CSV only: class,rating,version,quote (under 30 chars). If ambiguous, mark other — do not invent new classes." < reviews-kr.jsonl > classified.csvcut -d, -f1 classified.csv | sort | uniq -c | sort -rnThe one thing the report must keep — verbatim quotes
There is a reason the prompt demands a fragment of the original text alongside each label. A report with only summaries cannot be verified, and an unverifiable document does not earn trust. "41 billing complaints" is far weaker than "41 billing complaints, and one of them reads like this."
It is also a guard against fabrication. A model can produce a plausible pattern that does not exist; forcing a verbatim quote exposes that immediately. Checking whether the quote is actually in the source file is one grep.
The final artifact does not need to be impressive. A single page with four things is enough: how many reviews were examined, counts and shares per axis, two or three notable patterns tied to a version or country, and a recommended order of attack. That last item is the only actionable thing the recipient walks away with.
Customize only the first line
Once the report exists, write the email. The common mistake is rewriting the whole body for each prospect. It costs more time and money while quality drops. Choi's working rule is simple: customize the subject and the first line after the greeting, and repeat the best-performing template for everything else.
The first line comes out of the report. Since the analysis is already done, a sentence like "118 of 500 reviews were churn signals, and half of those cluster in your last two builds" writes itself. That is a different class of thing from a scraped video title, because it is the recipient's own data and they can check it.
Choi frames it as making the recipient feel they were looked at, whether or not they actually were. What separates this from the dead play is that here the raw material for that feeling is real data.
Why a follow-up exists even with no reply
Send the report as a link and track whether it was opened. That is why a link beats an attachment: you learn whether they opened it and how often.
That gives you a next move without a reply. "Looks like you had a look — I can help further with this part" is a completely different object from a nudge sent with no basis. It stands on the fact that they showed interest.
The same structure works outside sales. Another example from the interview is recruiting product-interview participants: pull a list of users who have been heavy on your product recently, fill only the first line with that person's usage, and ask for fifteen minutes. Usage records replace the report as raw material; the skeleton is identical.
If you want to ship one this week
Trying to set everything up first means never starting. Here is the minimum to run it once.
One, pick a company you want to pitch that ships an app. If they do not have one, change the raw material — job postings, website performance, search visibility, anything observable from outside slots into the same place.
Two, pull the reviews with the commands above. Apple alone gives 500, which is plenty for a first attempt. Ten minutes.
Three, classify along five axes and count each. Another ten minutes.
Four, write it up as one page: counts, two or three patterns, a recommended order, and a few verbatim quotes. Twenty minutes.
Five, write the email. Fill the first line with the numbers you just counted and leave the rest as your usual template. Send a link and watch the opens.
Once you have run one end to end, later rounds only swap the target. That is the point where this becomes outbound. The first one taking a while is normal — and the fact that it takes a while is exactly why it does not yet read as spam.
