phase 2 · listen
Signals
Go deeper
A signal is one real person caught in one trigger: the post, listing or event a detector matched, frozen as it was, judged, and routed. This page defines the signal as an object, explains how the judge decides and where signals go, and lists the top signal types with the play that answers each.
trigger · the kind of event → detector · the rule that watches → signal · one person caught → lead · signals merged by person
in industry terms
An intent signal: evidence that one person is in a buying moment.
Sales and marketing teams call this an intent signal (or buying signal). It sits between a raw match, which is only a rule firing, and a lead, which is a person you'd actually contact. Most matches never become signals, and most signals never become leads on their own.
match — A rule fired · A detector found words, a number or a dated record that fits its rule. Nobody has checked it yet. Cheap and noisy. · "any tool for" + "release notes"
signal — A real person, in the moment · The match passed freshness, exclusions and the judge, and there's a person behind it.
lead — A person worth a message · One or more signals on the same person, merged, who fits the ICP. Leads get scored, tiered and handed to a playbook. · Hot · 2 signals · fits 3 of 3 lines
Who — A real person or a small team you can reach, not a brand account, a bot or a news site.
What — The exact text, listing or event, frozen at capture. Posts get edited and deleted; the signal keeps what you saw.
Which trigger — Exactly one trigger from the map. A post that shows two triggers becomes two signals.
How sure — The detector's strength plus the judge's verdict and confidence.
How fresh — When it was posted, not just when it was caught. The window closes on the post's clock.
Where next — The queue it was routed to, or the reason it was thrown out.
SIGNAL · EXAMPLE — A CHANGELOG TOOL
- Text
- "is there anything that writes release notes from commits? doing it by hand every friday is killing me"
- Source
- r/SaaS · posted 3 hours ago
- Trigger
- Asking for a recommendation
- Detector
det.ask-reco.redditv4- Strength
- strong
- Judge
- yes · 0.91 · "asks for exactly the job; solo founder with a live SaaS"
- Routed
- pain queue
what happens next
merged with any other signal on the same person, checked against the ICP, then scored as a lead and offered the listen-and-reply play
the signal object
Every signal is one record with the same fields.
This is the shape a signal takes in the library and in code. Everything the judge and the founder later decide is written onto it or next to it, so the record is also the training row for the match judge.
| Field | Type | What it holds |
|---|---|---|
signal_id | string | Stable id, e.g. sig_01J…. Every lead, move and touch it leads to carries it. |
detector_id | id + version | The detector that caught it, with the version that was live: det.ask-reco.reddit v4. |
trigger_id | trigger id | Exactly one trigger from the Buying Moments Map. |
person | person ref | Who it is: handle, profile url and any linked identities. Merged into a person record at the lead stage. |
source | source id | Where it was caught: subreddit, X search, a launch site, your Stripe account. |
url | link | The post, listing or record itself. |
posted_at | time | When the person posted or the event happened. Freshness runs on this clock. |
captured_at | time | When the detector caught it. The gap is detection lag. |
raw | text + json | The full text and the raw payload, frozen at capture. Never edited afterwards. |
author | snapshot | Bio, follower count, linked site and account age as they were at capture. |
rule | name + score | Which part of the match fired, and its score. |
judge | verdict | yes, no or unsure; the reason; confidence 0 to 1; the model and prompt version. |
strength | strong | medium | weak | From the detector, adjusted by the judge. |
fresh_until | time | posted_at plus the trigger's freshness window. |
queue | pain | engage | listen | launch | Where the router sent it. |
discard | reason | null | Why it was thrown out, if it was. Kept as a row either way. |
one signal, as data
{
"signal_id": "sig_01JAX7Q2",
"detector": {
"id": "det.ask-reco.reddit",
"version": 4
},
"trigger_id": "ask-recommendation",
"person": {
"profile": "https://reddit.com/user/shipfast",
"site": "shipfast.dev"
},
"source": "reddit:r/SaaS",
"url": "https://reddit.com/r/SaaS/comments/…",
"posted_at": "2026-10-17T09:12:00Z",
"captured_at": "2026-10-17T09:40:00Z",
"raw": {
"title": "anything that writes release notes from commits?",
"body": "doing it by hand every friday is killing me"
},
"author": {
"bio": "solo founder, shipping shipfast",
"karma": 1840,
"account_age_days": 900
},
"rule": {
"name": "ask + job",
"score": 0.82
},
"judge": {
"verdict": "yes",
"reason": "asks for exactly the job; solo founder with a live SaaS",
"confidence": 0.91,
"model": "judge-model-id",
"prompt_version": "judge.v7"
},
"strength": "strong",
"fresh_until": "2026-10-20T09:12:00Z",
"queue": "pain",
"discard": null
}the judge and the router
Four questions decide whether a match is a signal, then a rule decides where it goes.
The judge is a model call with a written rubric. It answers the same four questions for every match, and its answer is stored with the model and prompt version that gave it.
question 1 — Is it the trigger? · Does the text actually show this buying moment, or does it only share the words? "I built a changelog tool" is not "I need one".
question 2 — Is there a person? · Someone reachable who could buy: not a brand account, a bot, a journalist or a vendor fishing for clicks.
question 3 — Is it still open? · Posted inside the trigger's freshness window, and not already answered or solved in the thread.
question 4 — Does it pass the rules? · None of the ICP's "not if" lines, not a competitor or their staff, not an existing customer.
Verdicts and confidence
| yes | It's a signal. Confidence (0 to 1) is stored and used to rank it among today's signals. |
| no | A discard, with the reason from the list below. Kept as a row: discards are the negatives the judge learns from. |
| unsure | Shown to the founder with the question the judge couldn't answer. Their answer becomes a label. |
| disagree | When the founder marks a "yes" as wrong (or a discard as real), both answers are kept. That disagreement set is the most valuable eval set the judge has. |
Where a signal goes
| pain | Public posts where someone describes the problem the product solves. The main source of cold leads. |
| engage | Replies to and mentions of your own account: people already talking to you. Each card is logged with the probability it was shown. |
| listen | On-topic conversation worth reading or joining, without a clear buying moment yet. |
| launch | Launch posts and listings: someone just shipped and is looking for users. |
Otherwise it's Watch: kept, not contacted. The lead rules (customer, never a customer, competitor) are applied on top.
Hot — Warm · Watch
the library
The top signal types, each with the play that answers it.
Cold signals come from strangers in public; warm signals come from people already touching your product. Examples use a changelog tool for solo founders; braces are filled from the brief: {job}, {competitor}, {category}.
Asking · Someone describes the job or asks for help with it.
sig.ask-reco — cold
Asks for a recommendation
any tool that writes release notes from commits? doing it by hand every friday is killing me
strong — fresh for 72 hours · phrase
- source
- Reddit, X, Hacker News
- trigger
- asking for a recommendation
- answer
listen-and-reply, Community answers
sig.public-pain — cold
Describes the pain in public
spent 3 hours on release notes again. there has to be a better way
medium — fresh for 72 hours · phrase
- source
- Reddit, X, Threads
- trigger
- public pain
- answer
listen-and-reply,offer-post-reply-loop
sig.how-do-you — cold
Asks how others handle it
how do you all handle changelogs for a small saas? do people even read them?
medium — fresh for 7 days · phrase
- source
- Reddit, Indie Hackers, Hacker News
- trigger
- researching the problem
- answer
- Community answers, Get named by AI assistants
sig.diy-fail — cold
Tried to do it by hand and gave up
wrote a script to generate our changelog. it broke on merge commits. giving up
strong — fresh for 7 days · phrase
- source
- Reddit, X, GitHub issues
- trigger
- tried it and it failed
- answer
listen-and-reply, Founder-led outreach
Competition · Someone is unhappy with, or choosing between, tools in your category.
sig.comp-complaint — cold
Complains about a competitor
{competitor} support hasn't answered in 6 days. thinking of switching
strong — fresh for 7 days · phrase
- source
- X, Reddit
- trigger
- unhappy with the current tool
- answer
comparison-interception
sig.comparison — cold
Asks for a comparison
{competitor} vs {competitor2} for a two-person team?
strong — fresh for 7 days · phrase
- source
- Reddit, X, Hacker News
- trigger
- comparing options
- answer
comparison-interception, Comparison pages
sig.alternative — cold
Looks for an alternative
looking for a {competitor} alternative that doesn't charge per seat
strong — fresh for 7 days · phrase
- source
- Reddit, X, Hacker News
- trigger
- comparing options
- answer
comparison-interception, Comparison pages
sig.bad-review — cold
Leaves a bad review of a competitor
2 stars: "export is broken and nobody replies to tickets"
strong — fresh for 14 days · event
- source
- G2, Capterra, Trustpilot, app stores
- trigger
- unhappy with the current tool
- answer
comparison-interception
sig.price-change — cold
A competitor raises its price
{competitor}/pricing: starter plan $9 → $19, changed overnight
medium — fresh for 14 days · change
- source
- competitor pricing pages
- trigger
- price shock
- answer
offer-post-reply-loop, Comparison pages
Launch · Someone just shipped and needs users.
sig.quiet-launch — cold
Launched and nobody noticed
launch listing, 6 days old, 4 upvotes, maker answering every comment
strong — fresh for 7 days · threshold
- source
- Uneed, PeerPush, Product Hunt, Show HN
- trigger
- tried it and it failed
- answer
launch-or-launch-again, Founder-led outreach
sig.launch-day — cold
Announces a launch
we're live on product hunt today, would love your feedback
medium — fresh for 3 days · event
- source
- X, Product Hunt
- trigger
- just launched
- answer
- Launch window
sig.zero-mrr — cold
Live, but no revenue
revenue board listing: MRR $0, launched 2 months ago
medium — fresh for 30 days · threshold
- source
- revenue boards (TrustMRR)
- trigger
- stuck at zero
- answer
signal-based-outbound
Company · A company-level change that opens a window.
sig.hiring — cold
Hiring for the job your product does
job post: "part-time technical writer, release notes and docs"
medium — fresh for 30 days · event
- source
- job boards, Hacker News "Who is hiring?"
- trigger
- hiring for the job
- answer
signal-based-outbound
sig.churned-tool — cold
Says they just cancelled a tool
just cancelled {competitor}. back to doing it by hand for now
strong — fresh for 14 days · phrase
- source
- X, Reddit
- trigger
- between tools
- answer
comparison-interception,listen-and-reply
Hand-raise · Someone answers you directly.
sig.keyword — cold
Comments the keyword on your post
replies "pipeline" under your post offering the template
strong — fresh for 48 hours · your data
- source
- your own posts on X, Threads, Instagram
- trigger
- raised a hand
- answer
comment-a-keyword
sig.mention — warm
Replies to or mentions you
@you does this work with gitlab or only github?
strong — fresh for 48 hours · your data
- trigger
- raised a hand
- answer
listen-and-reply
sig.inbound-dm — warm
Sends a DM or comments on Instagram
how much is it after the beta?
strong — fresh for 48 hours · your data
- source
- Instagram comments and DMs
- trigger
- raised a hand
- answer
listen-and-reply
Your product · People already in your product, waitlist or billing.
sig.waitlist — warm
Joins the waitlist
new waitlist row: name, email, "what would you use it for?" answered
strong — fresh for 7 days · your data
- source
- your waitlist
- trigger
- signed up
- answer
- Waitlist countdown
sig.signup-idle — warm
Signed up, didn't do the first thing
account created 2 days ago, no repo connected
strong — fresh for 3 days · your data
- source
- your app
- trigger
- signed up
- answer
- Activation nudge
sig.stalled-trial — warm
Trial is stalling
trial day 5, two logins, no changelog published
strong — fresh for until the trial ends · your data
- source
- your app
- trigger
- stalled trial
- answer
- Stalled trial rescue
sig.pricing-visit — warm
A known person visits pricing twice
same signed-up user on /pricing twice this week, no upgrade
medium — fresh for 3 days · your data
- source
- your analytics
- trigger
- evaluating
- answer
- Founder-led outreach
sig.payment-failed — warm
A payment fails
Stripe invoice.payment_failed, attempt 1, $19
strong — fresh for 7 days · your data
- source
- Stripe
- trigger
- payment failed
- answer
- Failed payment recovery
sig.cancelled — warm
Cancels a subscription
Stripe customer.subscription.deleted, 4 months in, reason: "too expensive"
strong — fresh for 30 days · your data
sig.replied — warm
Replies to your message
"yes, send it over" in reply to step 1 of a sequence
strong — fresh for 24 hours · your data
- source
- your inbox and DMs
- trigger
- in conversation
- answer
the next step of the sequence
discard reasons
Why a match is thrown out, and what each reason teaches.
Every discard keeps its reason. A detector that throws out most of what it catches for the same reason needs a new exclusion, not a smarter judge.
| Reason | What it means | Example | What it trains or fixes |
|---|---|---|---|
| stale | Posted outside the trigger's freshness window. | a "any recommendations?" thread from three weeks ago | the freshness window per type; detection lag |
| excluded | Hits one of the ICP's "not if" lines. | an agency asking on behalf of a client | ICP lines: which ones throw out real buyers |
| competitor | A competitor, its staff or its affiliates. | a {competitor} employee asking what people think of the new pricing | the lead rules' competitor list |
| vendor | Someone selling, fishing for clicks, or promoting their own tool. | "what tool do you use for X? (asking because I built one)" | detector exclusions; the judge's "is there a buyer" question |
| customer | Already a customer, or already in a campaign. | a current user asking a support question in public | |
| no person | A brand account, bot, news site or deleted user. | a newsletter account resharing a listicle | author-snapshot features for the judge |
| duplicate | The same person, same trigger, inside the window. | the same question cross-posted to three subreddits | person merging; counts as one signal with three sources |
| not the trigger | Shares the words but not the moment. | "I built a changelog tool, roast my landing page" | the judge's "is it the trigger" question; new negative phrases |
| answered | Already solved in the thread. | the asker replied "went with X, thanks all" | thread state as a judge input |
| out of scope | Wrong language, region or platform for the product. | asks for a tool that only works with a stack you don't support | brief fields for supported stack and region |
how it connects
Signals sit between the rules that catch people and the list you work from.
before — Buying Moments Map · Each signal belongs to exactly one trigger on the map. The trigger sets its freshness window.
before — Detector catalog · The detector that caught it, and its version. Signals are how a detector's precision is measured.
before — Your own sources · Feeds and saves the founder brings can feed detectors too, so they produce signals like any other source.
after — Lead scoring and merging · Signals on the same person merge into one lead, which is scored, tiered and checked against the ICP.
after — Playbook Library · The play that answers a signal type: see the "answer" line on each card above.
learn — GTM tracking plan · The item_matched, match_judged, match_labeled, signal_created and match_discarded events.
data to capture
Record every signal so the judge can learn from it later.
Optimizes the match judge and the router. The same rules as every stage in this guide: log the decision, version whatever decided, freeze the inputs, keep the negatives.
record
- the full raw text and an author snapshot, frozen at capture
- posted_at next to captured_at, so detection lag and decay can be measured
- detector id and version, the rule that fired, and its score
- the judge's verdict, reason, confidence, model and prompt version
- every discard with its reason
- the queue it was routed to
label
- founder: real or not, one tap, with an optional reason
- the cases where judge and founder disagree
- later outcomes on the same person: became a lead, replied, paid
trains
- the match judge, distilled into a small, cheap model
- the routing classifier
- per-signal-type value: which types turn into replies and payments
- a fitted freshness window per type, from reply rate by age
test
- judge prompt and model: offline replay against founder labels before switching
- routing rules: replay last month's signals through the new rule and compare queues
- freshness windows: by lead cohort once the decay curve exists