Step 1 — Define the ICP as filters, not vibes
“Mid-market SaaS companies” is a vibe. “B2B software, 50–500 employees, US/EU, currently hiring SDRs” is a filter set. Write your ideal customer profile as criteria a spreadsheet can evaluate — industry, headcount band, geography — plus at least one behavioral signal (hiring, fundraising, tech adoption) that indicates timing, not just fit. Fit gets you a list; timing gets you replies.
Step 2 — Source raw accounts, breadth first
At this stage quantity beats quality — filtering is cheap later, discovering is expensive later. Pull candidates from directories and review sites, industry communities, job boards (whoever hires for the role your product serves), and list-output research agents that can populate rows from a prompt like “find B2B fintechs headquartered in the DACH region.”
Step 3 — Dedupe on import
Overlapping sources mean duplicate accounts, and duplicates mean two reps emailing the same prospect. Import everything with a dedupe key — domain is the reliable one for companies — so re-imports and multi-source pulls merge instead of stacking. Rule: dedupe is an import-time setting, not a quarterly cleanup project.
Step 4 — Enrich in waterfalls, pilot first
Now the blanks: firmographics to score fit, named contacts to reach, and one or two researched columns that power personalization (pricing model, current vendor, a relevant initiative). Chain sources in a waterfall so no single vendor’s coverage caps your list.
Step 5 — Verify every email
Whatever found the address — an enrichment step, an export, a form — verify it before any sequence sends. Sort by status: ok goes to sequences, catch_all to a low-volume track, role/disposable/invalid out of outreach entirely. This single step is the difference between a 0.5% and a 15% bounce rate.
Step 6 — Filter, sync, and keep it alive
Save a view — ICP match ∧ email ok ∧ research found — and treat it as the product of the whole pipeline. Push it to your CRM via webhook as rows finish, or export the filtered CSV for your sequencer. Then keep the sheet running: new raw accounts land at the top, enrichment fills them, verification gates them, and the qualified view stays current without anyone rebuilding anything.
The anti-patterns
- Buying a “verified” list. It was verified when the vendor built it, not when you send. You inherit everyone else’s bounces.
- Enriching before deduping. You pay to enrich the same account twice, then argue about which copy is canonical.
- Personalizing from stale fields. “Congrats on the Series A” eighteen months late is worse than no personalization.
- One mega-export at quarter start. Lists are living things; a static export is dead in six weeks.