YouTube Keyword Research

Turns a topic into a validated search filter over every YouTube title, description and transcript we index, plus the channels and videos it selects.

Use in Claude Code Set up your agent
Command
/tl-keyword-research
Run modes
Quick, or deep with 3+ refinement rounds
Returns
Filter set, report link, videos and channels

Give it a topic in plain words. It expands that into candidate keywords, runs a live query for each against the 687M videos we index, drops the ones whose matches are off topic, and returns a filter plus the channels or videos it selects.

What you get

  • A filter set, always. Reusable keyword groups, a link that opens a report with the filter applied, and the Boolean expression so anyone can re-run or audit it.
  • Trend data. Matching uploads, sorted and windowed, with prevalence numbers: how many videos, how many distinct channels.
  • Channel targets. Channels tiered by how much they cover the topic, ranked, context-validated, and flagged for whether you can book them.
Try this prompt
> I want to find YouTube channels that cover cold plunge and cold-water recovery. Run tl-keyword-research on it, deep mode, channel targets.

Give it the topic and say what you want back. Leave either out and it asks.

To Claude

Why a synonym list falls short

A hand-written keyword list
tl-keyword-research
No way to know which terms were dead, or which you missed.
A live query per candidate: matching videos, distinct channels, samples to read.
A term that matches for the wrong reason pollutes everything downstream.
Samples judged against your sentence. Off-topic terms dropped, with the reason.
One spelling. The index treats the others as different words.
Every spelling probed separately, then folded into one group.
A flat list, which can only mean OR.
Required terms, scoped exclusions, per-group field targeting.
Everything searched at once, so the noisiest field decides the results.
A term too noisy in transcripts survives as a title-only match.
No way to tell an enthusiast from a passer-by.
Channels tiered by how much of their output is the topic.

What people use it for

A brand sizing a niche

how big is the home espresso topic on YouTube, and is it growing?

Prevalence numbers and the matching uploads by date.

An agency building a target list

find channels for a retirement client, deep, channel targets

Tiered, context-validated channels with subscribers, price, and outreach email where on file.

A creator-sourcing analyst

keywords that represent budget meal prep content

A filter set, and the report link showing where the list came from.

Someone chasing a launch

make a topic for this week's product launch, run autonomously

A web lookup for the real product names, then expansion covering its siblings.

A researcher writing it up

how common is each of these keywords?

Counts per keyword, ranked, with the scope stated.

How it works

Seven stages. Scripts do the deterministic work at no model cost; classification runs on small fast models in batches.

  1. Stage 0: Set up

    Your sentence is kept verbatim as the intent, since every later check is judged against it. Scope, operator and a breadth judgment are stated back before anything is spent.

    One cheap probe asks whether a channel-identity version of the topic exists, or whether the market is channels that keep returning to it.

    runs expand_entities.py

  2. Stage 1: Expand

    Each named entity expands into its family: company, product line, version, codename, and the sibling that shipped alongside. 8 to 15 candidates for a narrow niche, 30 to 50 for a multi-facet event.

    A shallow synonym list is the biggest failure mode. Coverage is won or lost here.

  3. Stage 2: Probe

    One live query per candidate returns matching documents, distinct channels reached, and real samples. Recency rides the same query free, flagging terms that live off an old back catalogue.

    Samples collapse to distinct channels, so one prolific creator cannot flood the evidence.

    runs probe.py

  4. Stage 3: Validate

    Each keyword's samples are checked against your intent, and off-topic terms are dropped with the reason shown. At scale a batch classifier does it, with a completeness check that re-sends anything left out.

    Relevance is judged from samples. Scope is your call, so those come back with snippets attached.

    runs select_keywords.py

  5. Stage 4: Refine

    At least three rounds of recomposing the filter. Each measures coverage, scores fitness, records the query, and names its move: narrow, expand, or backtrack.

    A move that reduces fitness is discarded and a different axis tried.

  6. Stage 5: Materialize

    One aggregation tiers every matching channel by how much of its output is the topic. Results are then built from the final filter verbatim.

    The tier table is 2 to 3 queries however many channels match, so it runs before any per-channel spend.

    runs search_channels.py --intensity

  7. Stage 6: Deliver

    Filter set, report link, results, and the Boolean expression. Anything pruned or translated is listed. Nothing is saved unless you say so.

    runs build_report.py

Every spelling is a different word

The index lowercases and splits on whitespace and punctuation, but does not split letter-digit runs and does not stem. One product name written four ways produces four sets of tokens.

You writeTokensMatching videos
fable 5fable 51,215
fable-5fable 51,215, identical to the spaced form
fable5fable594
fable fivefable five118
fablefivefablefive1

Four populations, one product. All-time counts, verified live in our index when the skill was written, so they drift as new videos land.

So anything with a number, version or model name is probed in every spelling, and the survivors fold into one group. Inflections too, since nothing is stemmed: invest, investing and investments are three terms.

When the model does not know the names

For a topic newer than the model’s knowledge, recently renamed, or thick with insider jargon, a web lookup runs first in an isolated context. It returns names only. Each then earns its place through the same probe and validation as any other candidate, and a hallucinated one probes to zero and drops.

The word is there. Is the topic?

Every probe returns two counts: total documents, and distinct channels. Judge a niche by the second, since one prolific creator can produce a thousand matches alone.

Samples are then read against your sentence. Two verified examples from one retirement run:

  • "social security" reaches 228 channels, a good share of them Brazilian pension-law firms. Excluding INSS leaves 192.
  • annuity reaches 596, including finance coursework: annuity due, ordinary annuity, present value. Excluding that cluster leaves 557.

Neither term is wrong, and neither problem is visible until you read what the term matched.

Whether matches are on topic is judged from evidence. Whether a sub-topic belongs in your scope is your call, so those come back with snippets and an in-or-out question.

Content fields

FieldWhat it holdsCharacter
titleThe video titleCleanest signal, weighted highest in ranking
summaryThe creator’s own description under the videoMain field for description text. Misleadingly named: not an AI summary
transcriptThe full spoken transcript, with timingsWidest reach, noisiest by far
channel_descriptionThe channel’s About text, indexed so whole domains stay single termsMatch a channel by what it links to, such as patreon.com
channel_topic_descriptionA description of what the channel coversFocused, but on only about a third of channels
hashtagsThe video’s hashtagsCatches handle-style spellings

Ranking weights them title^4, summary^2, transcript^1. A term too noisy corpus-wide is often precise in titles alone, so rather than drop it, the skill probes per field and keeps the group with a field restriction attached. Fields are set per group, not once for the filter.

Boolean queries a list cannot express

Every group is a self-contained Boolean query. Groups combine with OR; inside one you get required terms, alternatives and exclusions with real precedence.

Scope an exclusion to its own arm

A whole-filter exclusion hits groups that never had the problem. Inside its own group, it de-noises only the family that needed it:

("mythos 5" | mythos5) -keto

On one live run this kept 51 on-topic documents a global exclusion had removed.

Guard against over-exclusion

Re-run the core with and without the exclusion; the count should barely move. Excluding bare film from a Cannes Lions core cut it 24%, since on-topic content shares the word. The phrase "film festival" cut 4%, so that is the one that ships.

Anchor a root too broad to use alone

A place name has no single polluter to cut. Require an anchor token plus a domain qualifier:

cannes +lions +(advertising | agency | campaign | "young lions") -"film festival"

"cannes lions" fires only when the words sit side by side; cannes +lions fires when both appear anywhere, catching “Young Lions at Cannes”. The qualifier supplies the precision, which bare cannes +lions lacks. Measured live, that group added roughly 815 distinct channels beyond the phrase, around 80% on topic.

Judge a broad term on its residual

Probe the candidate with the core phrase excluded and read those samples. Relevance scoring otherwise floats covered documents to the top and hides how little is new.

Research operators never ship

* catches inflections, ~1 absorbs typos, "a b"~2 catches near-phrases. None survive into a report filter, so variants are enumerated first: retire* becomes (retire OR retiring OR retirement).

The grammar translation

A report link uses the uppercase words AND, OR and NOT; raw |, + and - are literal text there. Groups are translated on the way out:

("fable 5" | fable5) -keto

("fable 5" OR fable5) AND NOT keto
Top: the group as probed. Bottom: the same group as a report link speaks it.

Every translation is listed, and an unsupported operator fails loudly. This is the most common way a hand-built filter breaks: the link looks right and is matching a literal plus sign.

Channels tiered by coverage

Few channels are entirely about any topic, so “channels about X” alone returns a near-empty list for most niches.

TierWhat it meansUse it for
coreRecurring, and at least half their outputThe obvious targets, often a short list
recurringThree or more matching uploadsFor a niche topic, the actual sponsorship market
occasionalA couple of mentionsTrend math, usually the wrong target
one_offTouched it onceTrend math, almost never a target

The top tiers are context-validated: the text around each keyword occurrence is classified on topic, mixed or off topic, with an evidence quote and confidence. Mixed channels are kept and labelled, only clear misses excluded, and the excluded list shown. Channels you cannot book are flagged, not filtered out.

If a topic has almost no core channels, you are told, with the recurring tier framed as the market. A near-empty list is never padded.

Run modes

ModeWhat runsRough cost
QuickOne pass: expand, probe, validate, deliver. Spelling variants, entity-family expansion and sample validation all still run10 to 20 credits
DeepEverything above, plus 3 or more refinement rounds and full materialization with context validation60 to 120 credits

Say which you want, or answer when it asks; it will not pick silently. Say run autonomously to skip every check-in, which implies deep with both result types. Spend is narrated at every stage transition. Report links are free, and so is asking the skill to explain itself.

Try it

uv tool install thoughtleaders-cli
tl auth login
tl setup claude
Installs the tool, logs you in once, and drops the skills where your agent reads them.

The skill arrives as a slash command. The full setup page covers other installers, headless machines, and the one-liners for Codex, Gemini CLI and Cursor.

Start on a topic you know well, so you can check the output against your own knowledge.

Try this prompt
> /tl-keyword-research "cold plunge" quick

A single pass on a niche small enough to sanity-check yourself. Watch which terms it drops, and why.

To Claude

Good next prompts:

  • how does tl-keyword-research work? for the built-in guide, free
  • keywords that represent budget meal prep content, quick for a starter filter
  • how big is the GRWM trend on youtube right now? trend data only for prevalence, no channel list
  • find channels covering Medicare for a retirement client, deep, channel targets
  • make a topic for cannes lions, run autonomously, both for no pauses

Options, in plain words

You sayWhat changes
”quick” or “deep”The run mode
”trend data”, “channels to sponsor”, or “both”Which results come back
”run autonomously”No check-ins. Implies deep, and both result types
”include shorts and live”Widens the longform-only default
”newest first”, “biggest videos”, “since June”Sorts and windows the trend feed
”one video per channel”Dedupes the feed to each channel’s best match
”only channels that cover it repeatedly”Focuses on the recurring tier. Default is 3 uploads; name a number to change it
”title matches only”Restricts a keyword to titles
”exclude [word or sense]“Adds an exclusion, scoped so it does not over-cut
”broaden it” or “narrow it to X”Changes breadth mid-run
”save it as a report”Persists a named, shareable report
”keyword counts”The distribution table instead of the full pipeline

Scope and limits

YouTube uploads only, longform by default. Shorts and live on request, and the scope in force is echoed back with every result.

Headline counts are all-time. Recency rides the same query, so a term living only in an old back catalogue is tagged stale.

There is no universal right result size. A few dozen channels is complete for a narrow niche and a miss for a broad one, so breadth is stated up front and measured at the end. If mining runs dry, a small result is reported as correct, not padded.

The corpus is the boundary. This searches what we index, titles, creator descriptions and transcripts across 1,302,318 tracked channels, not the open web. It is the same data our sponsorship matching runs on.