listen · detectors
Detector kinds
The five kinds of monitoring rule.
In Detectors
Detector kinds: the five ways a monitoring rule decides it found something.
A detector is a monitoring rule: where to watch and what to match for one trigger. Every one of the 74 detectors in the library is one of five kinds. The kind decides what the rule can read, how noisy it will be, and what the signal it emits carries.
Triggers → Detector catalog → Detector kinds → Signal catalog
Pick by where the moment shows — Words, a number, a dated record, a changed page, or your own events.
Different kinds stack — Two kinds on the same person is the strongest evidence.
Your data first — If the person is already in your funnel, no scraping is needed.
what it is
Same trigger, different evidence.
Industry names: phrase detectors are social listening or keyword monitoring; thresholds and events are intent data and trigger events; change detection is competitive monitoring; your-data detectors are product signals or first-party behavioral triggers. They differ in what they read, not in what they produce: every kind emits a signal with its own detector id, a link or record, and a date.
Phrase — Words in a post or comment, in the buyer's own language. · 30 detectors in the library
Threshold — A number on a public record crosses a line. · 18 detectors in the library
Event — A dated record appears: a launch, a job post, a funding round, a review. · 11 detectors in the library
Change — A page you watch changes: pricing, changelog, status page. · 1 detector in the library
Your data — An event in your own analytics, app, forms or Stripe. · 14 detectors in the library
choosing a kind
Start from where the moment becomes visible.
- Where does the — moment show up?
- words in a post or comment
- phrase — asks, complaints, vents
- a number on a public record
- threshold — upvotes, rating, MRR
- a dated record appears
- event — launch, job post, funding
- a page you watch changes
- change — pricing, changelog, status
- your own systems
- your data — app, forms, Stripe
two kinds beat one
Most triggers can be caught more than one way. Two detectors of different kinds firing on the same person (a low-vote launch listing and a "launched, crickets" post) is the strongest evidence a cold signal can carry. A judge can sit on top of any kind; it changes precision, not the kind.
the kind spec
What each kind reads, and what it costs.
The object every detector shares is on the Detector catalog. What changes by kind is the shape of match and the fields it emits. The sample is a threshold detector written out in full.
| Kind | Reads | Match form | Noise | Cost to run | Typical window | In the library |
|---|---|---|---|---|---|---|
| phrase | posts, comments, threads | phrases + negatives + judge | high | feed polling plus judge calls per candidate | 3 to 14 days | 30 |
| threshold | launch sites, reviews, revenue boards | field compared to a line | low | page or API reads, few judge calls | 7 to 30 days | 18 |
| event | job boards, news, listings | new record of a type, filtered | medium | listing reads, dedupe across boards | 14 to 60 days | 11 |
| change | competitor pages | diff between snapshots | low | one snapshot per page per day | 1 to 7 days | 1 |
| your data | app, analytics, forms, Stripe | condition across your events | lowest | your own events, no scraping | 1 to 60 days | 14 |
| Field | Type | What it holds |
|---|---|---|
kind | enum | phrase | threshold | event | change | owned |
reads | field list | Which fields of the source item the rule can see. |
match | rule | Phrases for phrase; field + operator + value for threshold; record type + filters for event; watched fields for change; a condition across events for owned. |
judge | optional | A question with a rubric and a minimum confidence, for any kind. |
emits | field list | Always detector_id, a link or record and a date; plus what this kind can read. |
a threshold detector, as data
{
"kind": "threshold",
"id": "det.tried-it-and-it-failed.uneed",
"version": 1,
"source": "uneed",
"reads": [
"listing.name",
"listing.domain",
"listing.launched_at",
"listing.upvotes",
"listing.spotlight"
],
"match": {
"field": "upvotes",
"op": "<",
"value": 10,
"within": {
"field": "launched_at",
"days": 7
},
"boost_if": {
"spotlight": true
}
},
"judge": {
"question": "Is this a software product sold by a small team, not an agency or template?",
"min_confidence": 0.7
},
"strength": "strong",
"fresh_for": "7 days",
"exclude": [
"agencies",
"templates",
"non-software listings",
"icp.not_if",
"lead_rules.never"
],
"emits": [
"detector_id",
"link",
"date",
"owner",
"field_values"
]
}the five kinds
Each kind, in depth.
Phrase — industry: social listening, keyword monitoring · 30 in the library
Words in a post or comment, in the buyer's own language.
- use when
- The moment is said out loud: an ask, a complaint, a vent, a hiring post.
- avoid when
- The moment never gets written down (a quiet churn), or the words are too common to separate.
- noise
- cheap to build, noisiest to run
- strength
- weak to strong; strong only for direct asks
- window
- 3 to 14 days
- emits
detector_id,link,posted_at,author,matched_text- example
"what do you use for" {job}on Reddit, 7 days, strong- breaks on
- Sarcasm, vendors answering themselves, very common pain words.
mechanism
- Pull new items from the source on a schedule
- Fill placeholders from the brief: {job}, {category}, {competitor}
- Keep items that hit any_of and all_of phrases, drop none_of
- Send survivors to the judge with the trigger's rubric
- Score strength, check freshness and exclusions, emit
Threshold — industry: threshold alert, rule-based scoring on public records · 18 in the library
A number on a public record crosses a line.
- use when
- A public number shows the moment: upvotes on a launch, a star rating, MRR, review count.
- avoid when
- The number isn't public, or the line is arbitrary and you haven't checked it against real examples.
- noise
- little noise, limited to sources with numbers
- strength
- medium to strong
- window
- 7 to 30 days
- emits
detector_id,link,date,owner,field_values- example
upvotes < 10within 7 days on Uneed, strong- breaks on
- Records with no reachable owner; vanity metrics that don't mean pain.
mechanism
- Read the record and its fields (upvotes, rating, MRR, launch date)
- Compare against the line, e.g. upvotes < 10 within 7 days of launch
- Attach the owner (maker profile, company domain)
- Optional judge: is this a real product in the ICP?
- Emit with the field values frozen
Event — industry: event monitoring, intent data, trigger events · 11 in the library
A dated record appears: a launch, a job post, a funding round, a review.
- use when
- The record itself is the moment, and its date tells you the window is open.
- avoid when
- Records arrive long after the moment (news lag), or the event is too common to mean anything alone.
- noise
- medium; depends on how clean the listing is
- strength
- medium to strong
- window
- 14 to 60 days
- emits
detector_id,link,event_date,owner- example
- new job post titled
{role}at a company in the ICP's size range, strong - breaks on
- Agencies posting for clients; duplicate listings across boards.
mechanism
- Watch for new records of a type
- Filter by the ICP's size and category
- Read the event date, not the capture date
- Join to a person or company
- Emit with event_date
Change — industry: web change detection, competitive monitoring · 1 in the library
A page you watch changes: pricing, changelog, status page.
- use when
- One change moves many people at once: a price rise, a plan removed, an outage, an acquisition.
- avoid when
- You can't connect the change to people yet. Pair it with a phrase detector for the spike that follows.
- noise
- low noise once layout is ignored
- strength
- strong as an event, weak per person
- window
- 1 to 7 days
- emits
detector_id,page,before,after,seen_at- example
{competitor}/pricingdiffers from yesterday on price or plan names- breaks on
- Cosmetic redesigns; A/B tests showing different prices to different visitors.
mechanism
- Snapshot the page on a schedule
- Diff against the last snapshot, ignoring layout
- Classify the change: price, plan, end-of-life, outage
- Emit one event for many people
- Arm phrase detectors on the competitor's name for the next few days
Your data — industry: first-party behavioral triggers, product signals · 14 in the library
An event in your own analytics, app, forms or Stripe.
- use when
- The person is already in your funnel: they replied, signed up, stalled, paid, failed to pay, cancelled.
- avoid when
- Never the wrong tool when the data exists; the limit is permission, not detection.
- noise
- most reliable; no scraping, no third-party terms
- strength
- usually strong
- window
- 1 to 60 days
- emits
detector_id,person_or_account,event,at- example
invoice.payment_failedfrom Stripe, strong, 1 day- breaks on
- Test accounts and your own team; seasonal usage dips.
mechanism
- Subscribe to your own events (webhooks, app events, form posts)
- Evaluate a condition across events, e.g. signed_up AND no activation within 24h
- Check permission: what may we send?
- Emit with the account or person id
- Hand to the lifecycle play
all 74, by kind
The whole library, filtered by kind.
Every detector from the Detector catalog.
| Trigger | Source | Kind | Match | Strength · fresh |
|---|---|---|---|---|
| Asking for a recommendation cold | phrase | "what do you use for" {job} · "best tool for" {job} · "any recommendations" + {category} | strong 7 days | |
| Asking for a recommendation cold | X | phrase | "recommend" {category} · "what do you use for" {job}, with a product link in the author's bio | medium 3 days |
| Asking for a recommendation cold | Threads | phrase | the same asks on Threads | medium 3 days |
| Asking for a recommendation cold | Hacker News | phrase | Ask HN titles with {category} + "recommend" or "what do you use" | strong 7 days |
| Asking for a recommendation cold | Indie Hackers | phrase | forum posts asking which tool to use for {job} | strong 7 days |
| Asking for a recommendation cold | Discord, Slack and Skool | phrase | the same questions in member communities | strong 7 days |
| Comparing options cold | phrase | "{competitor} vs" · "alternative to {competitor}" · "{competitor} or {competitor}" | strong 14 days | |
| Comparing options cold | X | phrase | the same comparisons, plus "switching to" | medium 7 days |
| Comparing options cold | G2 | event | a new review on a {competitor} page that names an alternative it was compared with | weak 30 days |
| Comparing options cold | Google Alerts | phrase | "{competitor} alternative" | weak 30 days |
| Unhappy with their current tool cold | G2 | threshold | new review of {competitor} with rating ≤ 3 | strong 30 days |
| Unhappy with their current tool cold | Capterra | threshold | new review of {competitor} with rating ≤ 3; note role, industry and company size | strong 30 days |
| Unhappy with their current tool cold | Trustpilot | threshold | new review of {competitor} with rating ≤ 2 | medium 30 days |
| Unhappy with their current tool cold | Apple App Store | threshold | rating ≤ 2 on {competitor}'s app | medium 30 days |
| Unhappy with their current tool cold | Google Play | threshold | rating ≤ 2 on {competitor}'s app | medium 30 days |
| Unhappy with their current tool cold | Shopify App Store | threshold | rating ≤ 2 on a competing app; the review names the store | strong 30 days |
| Unhappy with their current tool cold | Chrome Web Store | threshold | rating ≤ 2 on a competing extension | medium 30 days |
| Unhappy with their current tool cold | phrase | "cancelling {competitor}" · "switching from {competitor}" · "{competitor} is too expensive" | strong 7 days | |
| Unhappy with their current tool cold | X | phrase | the same phrases on X | medium 3 days |
| Competitor shake-up cold | Competitor pages | change | {competitor}/pricing or changelog changes: a price rise, a removed plan, an end-of-life notice | strong 3 days |
| Competitor shake-up cold | Competitor pages | event | the status page reports a major outage | medium 1 day |
| Competitor shake-up cold | News and funding | event | acquisition or shutdown news naming {competitor} | strong 7 days |
| Competitor shake-up cold | phrase | a spike of posts naming {competitor} with angry words, after one of the above | medium 3 days | |
| Tried it and it failed cold | Uneed | threshold | launched in the last 7 days with upvotes < 10; a paid Spotlight slot makes it stronger | strong 7 days |
| Tried it and it failed cold | PeerPush | threshold | publishedAt in the last 7 days and low votes | strong 7 days |
| Tried it and it failed cold | Product Hunt | threshold | launched in the last 7 days, low votes and no comments | medium 7 days |
| Tried it and it failed cold | Hacker News | threshold | a Show HN in the last 7 days with points < 5 and no comments | medium 7 days |
| Tried it and it failed cold | BetaList | event | listed in the last 14 days, read with a post about no traction | medium 14 days |
| Tried it and it failed cold | Other launch sites | threshold | a paid or featured slot with single-digit upvotes (Smol Launch, Fazier) | strong 7 days |
| Tried it and it failed cold | X | phrase | "launched" + "crickets" / "0 signups" / "no sales" | strong 7 days |
| Tried it and it failed cold | phrase | the same phrases in founder subreddits | strong 7 days | |
| Tried it and it failed cold | Meta Ad Library | threshold | ads running 60+ days for a store with few reviews | medium 30 days |
| Trying again cold | Product Hunt | event | the same product or domain launching a second time | strong 14 days |
| Trying again cold | Other launch sites | event | the same domain listed twice across launch sites | strong 14 days |
| Trying again cold | X | phrase | "relaunching" · "launching again" · "v2 is live" | medium 7 days |
| Venting about the problem cold | phrase | pain phrases in the buyer's own words, from audience research | weak 14 days | |
| Venting about the problem cold | X | phrase | the same phrases on X | weak 7 days |
| Venting about the problem cold | Threads | phrase | the same phrases on Threads | weak 7 days |
| Venting about the problem cold | Discord, Slack and Skool | phrase | the same phrases in member communities | medium 14 days |
| Doing it by hand cold | phrase | "template for" {job} · "spreadsheet" or "google sheet" + {job} · "I built a script" | strong 14 days | |
| Doing it by hand cold | X | phrase | the same phrases on X | medium 7 days |
| Doing it by hand cold | Indie Hackers | phrase | posts sharing a homemade workflow for {job} | medium 14 days |
| Doing it by hand cold | Discord, Slack and Skool | phrase | template and spreadsheet requests | strong 14 days |
| Set up, but no results cold | Revenue boards | threshold | customers > 0 and MRR = $0, or flat for 3+ months | strong 30 days |
| Set up, but no results cold | Shopify App Store | threshold | a listing live 6+ months with 0 or 1 reviews | medium 30 days |
| Set up, but no results cold | Apple App Store | threshold | an app live 6+ months with very few ratings and a recent update | medium 30 days |
| Set up, but no results cold | Meta Ad Library | threshold | ads running 60+ days for a store with very few reviews | medium 30 days |
| Crossed a threshold cold | X | phrase | "just crossed" · "just hit" + users, customers or revenue · "we raised" | medium 14 days |
| Crossed a threshold cold | News and funding | event | funding for a company in the ICP's size range | strong 30 days |
| Crossed a threshold cold | Revenue boards | threshold | MRR crosses a line that matters, like $1k or $10k | medium 30 days |
| Hiring for the job you do cold | Job boards | event | a new post titled {role} at a company in the ICP's size range | strong 30 days |
| Hiring for the job you do cold | Hacker News | event | the monthly "Who is hiring?" thread, filtered for {role} | medium 30 days |
| Hiring for the job you do cold | X | phrase | "hiring a" {role} · "looking for a VA" | medium 14 days |
| New in the role cold | event | job change into {role}, or a new company page | strong 60 days | |
| New in the role cold | X | phrase | "quit my job to go full-time" · "just opened my practice" · "day 1 at" | medium 30 days |
| Taking stock cold | X | phrase | "month 1" · "MRR update" · "year in review" with numbers | medium 7 days |
| Taking stock cold | phrase | the same posts in founder subreddits | medium 7 days | |
| Taking stock cold | Indie Hackers | phrase | milestone posts with flat or zero numbers | medium 7 days |
| Taking stock cold | Revenue boards | event | a new revenue-board listing | weak 30 days |
| Engaged with your content warm | Replies and mentions | your data | a reply, mention or comment from someone who isn't a lead yet | medium 3 days |
| Engaged with your content warm | Forms and email list | your data | a new newsletter subscriber | weak 7 days |
| Hand-raise warm | Replies and mentions | your data | a reply under your offer post that contains a URL or asks for the offer | strong 2 days |
| Hand-raise warm | Forms and email list | your data | a lead-magnet submission, or answers to waitlist survey questions | strong 2 days |
| Checked your pricing warm | Site analytics | your data | an identified visitor views /pricing twice in 7 days | strong 3 days |
| Signed up, didn't start warm | Your app | your data | signed_up and no activation event within 24 hours | strong 1 day |
| Trial ending, not converted warm | Stripe | your data | customer.subscription.trial_will_end (3 days before the end) with low usage | strong 3 days |
| Went quiet warm | Your app | your data | no login or key action for 30 days after some use | medium 30 days |
| Payment failed warm | Stripe | your data | invoice.payment_failed | strong 1 day |
| Using it less warm | Your app | your data | key actions down by half or more over 4 weeks against the 4 before | medium 7 days |
| Outgrowing their plan warm | Your app | your data | hits a plan limit, or adds a second product, location or teammate | strong 7 days |
| Outgrowing their plan warm | X | phrase | the customer announces a second product or location | medium 14 days |
| Just had a win warm | Your app | your data | a milestone event: first result, first payment caught | medium 7 days |
| Just had a win warm | Replies and mentions | your data | a happy reply, mention or survey score of 9 or 10 | strong 7 days |
| Cancelled warm | Stripe | your data | customer.subscription.deleted, with the reason from cancellation_details if your cancel flow asks | strong 60 days |
failure modes
How each kind goes wrong.
| Kind | Failure | How to catch it |
|---|---|---|
| phrase | Matches the words, misses the meaning: sarcasm, quotes of other people, vendors answering themselves. | A judge with a rubric, plus none_of negatives learned from every false match. |
| phrase | Vocabulary written by the founder, not the buyer. | Take phrases from audience research in the buyer's own words; review misses monthly. |
| threshold | The line is a guess (why 10 upvotes?). | Pick the line from 30 days of real records, then check precision on a sample. |
| threshold | Records with no owner you can reach. | Mark the detector research-only; route its signals to content, not outreach. |
| event | News lag: the event is old by the time it is captured. | Freshness on event_date, never on capture time. |
| change | Layout changes or price tests read as a price change. | Diff only the fields that matter: prices, plan names, end-of-life text. |
| your data | Test accounts and your own team fire triggers. | Exclude internal accounts by id; label them in the app. |
| any | The source changes format and the detector silently returns nothing. | Source health: alert when a detector that normally fires goes quiet. |
data to capture
Record the kind with every match.
So precision and yield can be compared across kinds, not just across detectors.
record
- kind and detector version on every match
- per run: items scanned, candidates, judge calls, matches, cost, duration
- for threshold rules: the field values at capture, frozen
- for change rules: the before and after snapshot
label
- founder real or not on a sample per kind
- signal became a lead, a reply, a join, a payment
trains
- precision and yield per dollar, by kind and source
- which kind combinations predict a reply (stacking weights)
test
- phrase vs threshold for the same trigger, on the same weeks
- line value for a threshold (under 5 vs under 10 upvotes), offline on stored records