Detect intent signals

Hiring, funding, technology and job changes.

Large radio telescope under a stormy sky

A signal is a dated change at an account that makes your offer more relevant this month than it was last month. Four families cover most B2B needs: hiring, funding, technology and job changes. Collect only the ones you can tie to a specific buying reason, store each one as a dated event, and let its value expire.

By this stage your accounts carry a fit score from the scoring chapter. Fit says who could buy, and signals decide who moves to the top of this week’s queue. Throughout this chapter, say you sell payroll software to French SMEs with 20 to 249 employees. The points, durations and volumes below are illustrative.

Write the buying reason before you collect anything

Each signal needs a sentence that starts with “because”. If you can’t finish the sentence, you are collecting noise with a date on it.

Signal Because Where it shows Usable for (starting guess)
Job ad for a payroll or HR administrator Payroll workload is growing, or the person running it is leaving LinkedIn Jobs, job boards, careers page 45 days
New HR director or CFO New owners review their tools in their first months LinkedIn, press 90 days
Funding round Hiring follows, and payslip volume with it Press, company news 120 days
Headcount moving up a band More payslips and more complexity than the current setup was chosen for Registry bands, LinkedIn staff count 90 days
Past customer or champion changes company Someone who knows your product now sits in a new account Your CRM contacts, re-enriched 90 days
HR or accounting tool added or dropped An integration need, or a replacement project under way Website detection, job ads naming the tool 60 days

Those durations are where I would start. After one quarter, your own reply data replaces them.

How to collect each family

Hiring

Job ads tend to be the most useful signal because the title tells you which team is getting budget.

Derrick does this step with Company Hiring Signal (I co-founded Derrick, so read this with that in mind). You give it a column of LinkedIn company URLs and can narrow by country, posting date or keywords, here “paie” and “RH” with a recent posting date. It writes back isHiring, openPositions, topJobTitles and jobsUrl, for 1 credit per company checked, from the web app, Google Sheets, the API or an MCP client.

It has two limits worth knowing. It reads LinkedIn Jobs, so an SME that only publishes on its own careers page or a regional job board looks like it isn’t hiring. And openPositions shows “10+” once the first page is full, so it can’t size a large recruitment drive. Without a tool, open LinkedIn Jobs by hand for your top accounts, or keep saved keyword searches on job boards and match the company names against your table.

Funding

Announcements surface in the press and in company news. In Derrick, Google News Scraper takes a column of company names and a lookback from 24 hours to 12 months. It returns the most relevant recent article for each company (title, url, publisher, published), at 1 credit per news found. To sort the headlines, run Ask Claude on the title column, 2 credits per row, with a closed list of answers:

Headline: {title}
Answer with one word from this list:
funding, acquisition, new_executive, expansion, layoffs, other.

One article per company means a funding story can lose to a louder headline, and many small rounds never reach the press at all. The manual route is alerts on your Tier A company names plus a weekly read of the trade press in your sector.

Technology

Website Technologies takes a column of URLs and returns cms, technologies and urlStatus, for 2 credits per call. Any detector of this kind only sees what the public site loads: CMS, analytics, chat and marketing tags.

For our payroll example that is close to useless, since payroll software leaves no trace on a homepage. Job ads asking for experience on a named payroll suite will tell you more. Use website detection when your product sits next to something the site loads.

One run gives you a state, and the signal is the change between two runs. Keep dated snapshots and compare them:

SELECT cur.account_domain, cur.technology AS added, cur.seen_at
FROM tech_snapshots cur
LEFT JOIN tech_snapshots prev
  ON prev.account_domain = cur.account_domain
 AND prev.technology = cur.technology
 AND prev.run_id = 41
WHERE cur.run_id = 42
  AND prev.technology IS NULL;

Job changes

If you have past customers or champions, this is the signal I would set up first, because the person already knows what your product does.

Signal watches a list of leads or accounts daily in the background and alerts you on the types you toggle on, such as job change, funding round or tech-stack move. It costs 1 credit per signal triggered, needs a paid plan and runs from Google Sheets today. It only watches what you put in, so it won’t find accounts missing from your list. The manual version: every month, re-run Enrich Leads (1 credit per profile) on your champions, or check them by hand, and compare the current company with the one you stored. That list holds personal data, so it falls under the rules in the maintenance chapter.

Set a cadence by tier

Periodic checks cost money every time, so spend them where a reply is worth the most. With 300 Tier A accounts checked weekly and 900 Tier B accounts checked monthly, the hiring check comes to about 2,100 credits a month (300 × 4 + 900). Tier C waits until it moves up.

Dish antenna in silhouette at dusk

Store signals as events, one row each

Keep signals in their own table. Writing “hiring: yes” on the account row erases the date, and the date is what gives a signal its value.

Column Example Note
signal_id 18342 Unique
account_domain example-pme.fr Same key as the accounts table
signal_type hiring_payroll From a closed list
signal_value Gestionnaire de paie The raw evidence, reused in the message
source linkedin_jobs Where it came from
event_date 2026-10-28 When it happened, or your best estimate
detected_at 2026-11-02 When you saw it
used_in_campaign outbound_q4_b Blank until someone acts on it
Radio telescopes at sunset

Score signals with an expiry date

Fit acts as the gate and the signal sets the order inside it. A signal on an account outside your fit tiers stays in the table and gets no action.

signal_type points useful_days
champion_moved 40 90
hiring_payroll 30 45
new_executive 25 90
headcount_band_up 20 90
funding 20 120
tech_change 15 60

The value decays in a straight line until it reaches zero. In a sheet, with points in C, the event date in D and useful days in E:

=MAX(0, C2 * (1 - (TODAY() - D2) / E2))

In a database, per account:

SELECT s.account_domain,
       ROUND(SUM(r.points * (1 - (CURRENT_DATE - s.event_date)::numeric / r.useful_days))) AS signal_score
FROM signals s
JOIN signal_rules r USING (signal_type)
WHERE CURRENT_DATE - s.event_date < r.useful_days
GROUP BY s.account_domain
ORDER BY signal_score DESC;

The output is a ranked list per tier, refreshed weekly. Each rep starts the week from the top of it, with the signal_value ready to quote in the first line of the message. The outbound chapter covers how to build those sequences.

Test each signal against your own replies

A signal earns its points when accounts showing it answer more often than similar accounts without it. Take one tier, send the same offer to both groups in the same period, and compare positive replies.

Signal Accounts with Positive replies Accounts without Positive replies Decision
hiring_payroll
funding
champion_moved

Wait for at least a hundred accounts per group, because below that you are mostly reading chance. Raise the points on what clearly beats its control group, cut what doesn’t, and shorten the useful days when old signals stop getting answers.

Your next step: write the “because” sentence for each signal you are considering, keep the three you can defend, and run one on your Tier A accounts this week. Log every result as a dated row, then move on to sizing the market.