Signal-Driven Outreach

Signal-driven outreach inverts the usual prospecting motion. Instead of starting with a target account list and looking for buying intent, you start with a signal stream (e.g. weekly Trustpilot scrape, LinkedIn job posting feed) and let the signal pick the accounts.

When this pattern wins

  • You have a small product team and can’t afford to research a 1,000-account list.
  • Your motion is event-driven — you sell churn-prevention to companies actively losing customers, or you sell sales tooling to companies actively hiring SDRs.
  • You want a stream of fresh targets rather than a static list.

The flow

INPUT: signal type (e.g. "negative support reviews")
1. signal_* (run the detector on a target list)
↓ (filter to fired)
2. get_linkedin_company_url (only for fired domains)
3. list_linkedin_company_employees (filtered by signal-relevant title)
4. get_email
5. send_linkedin_invitation (with signal evidence quoted)

Concrete example: churn-prevention motion

You sell a CX agent that handles support tickets. Your highest-converting prospects are companies with rising negative support reviews. Skip qualification — the signal is the qualification.

1const KEY = process.env.GTM_TOOLS_API_KEY!;
2
3const TARGETS = [
4 "gymshark.com",
5 "mammaly.de",
6 "kettleandfire.com",
7 "spanx.com",
8 // ... your watchlist
9];
10
11async function call<T>(tool: string, body: unknown): Promise<T> {
12 const res = await fetch(`https://api.gtm-tools.sh/api/v0/${tool}`, {
13 method: "POST",
14 headers: {
15 "Authorization": `Bearer ${KEY}`,
16 "Content-Type": "application/json",
17 },
18 body: JSON.stringify(body),
19 });
20 if (!res.ok) throw new Error(`${tool}: ${res.status}`);
21 return res.json();
22}
23
24for (const domain of TARGETS) {
25 // 1. Single-signal probe (5 tokens)
26 const sig = await call<any>("signal_trustpilot_negative_support_reviews", {
27 domain,
28 });
29 if (!sig.fired) continue;
30
31 // 2. Find CX leadership (2 + 30 tokens)
32 await call("get_linkedin_company_url", { domain });
33 const { results } = await call<any>("list_linkedin_company_employees", {
34 domain,
35 title_filters: "(VP OR Director OR Head) AND (CX OR Support OR \"Customer Experience\") NOT intern",
36 limit: 5,
37 });
38 if (!results.length) continue;
39
40 // 3. Verify email for top candidate (5 tokens)
41 const lead = results[0];
42 const { email, is_catch_all } = await call<any>("get_email", {
43 name: lead.name,
44 domain,
45 });
46
47 // 4. Compose message with signal evidence
48 const evidence = sig.evidence?.[0]?.snippet ?? "negative support reviews";
49 console.log({
50 domain,
51 name: lead.name,
52 email,
53 is_catch_all,
54 angle: `Saw recent feedback: "${evidence.slice(0, 80)}..."`,
55 });
56}

Token math

StepTokens (per fired domain)
signal_trustpilot_negative_support_reviews5
get_linkedin_company_url2
list_linkedin_company_employees30
get_email5
Total42

Plus 5 tokens for each non-fired domain. At a 20% fire rate: 100 domains = 100 × 5 + 20 × 37 = 1,240 tokens ($12.40).

Why this beats account-first prospecting

In account-first prospecting, you commit 30 tokens to employee search before knowing the account is actually qualified. Signal-first defers that 30-token call until the signal has fired, so you only spend it on hot leads.

For a 1,000-account watchlist with a 5% fire rate:

ApproachTokens spent
Account-first (30 + 5 + 5 every account)40,000
Signal-first (5 every account, 37 only on fired)6,850

Same end result, 6× cheaper.