How the lead list is built
Public sources → company websites → facts with proof → the right person → a ranked list for sales.
Find companies
Clean the list
Research agent
Pull out facts with proof
Find the right person
Score and deliver
Good customer, and can we reach them?
A great customer we can't reach is not a first call. So fit and reachability are scored apart.
Fit score 0–100
What makes a good customer for Heidi.
Meters read by hand must be remote-readable from 1 Jan 2027, so these firms must act soon.
Access score 0–100
How directly we reach the person who decides.
A LinkedIn profile for the contact adds +10.
What each step does
Each step adds something a salesperson can use, and the costly steps run only on companies that are still in the list.
1Find companies
Search maps and industry directories for every property manager and housing company with a Berlin office.
2Clean the list
The same website, phone, or name and postcode means one company. Metering competitors and pure brokers are set aside before any paid step, and a Berlin address (or Berlin on their pages) is required.
3Research agent
An AI agent reads the company's own pages (legal notice, team, contact and services), and searches the web for firms without a website to find their directory or listing pages.
4Pull out facts with proof
An AI model (Claude Haiku) reads the pages and notes what the company manages, how many apartments, how heating costs are billed today, metering company, software, meters still read by hand, contract end or provider change, and contacts. A second pass looks for anything missing.
- A fact is kept only if its quote is really on the page.
- Own pages are trusted; ranges are ignored.
- A Germany-wide total is never counted as Berlin.
5Find the right person
Look for named staff and property-manager job titles on LinkedIn, personal e-mails and direct lines on team pages, and named contacts in public job ads. A likely e-mail built from the company's own address pattern is labelled as such. Nothing is kept unless it appeared in the search results.
Before → after this step, across all leads:
6Score and deliver
Two separate scores: Fit says how good a customer the company would be, and Access says how directly we reach the person who decides. Together they set the tier (A call first, B good, C weaker).
Where the information comes from
Only public sources: maps and directories find the companies, their own pages give the facts, searches find the people. Bubble size = how many each source gave.
Lead map district outlines: Berliner Morgenpost Berlin-Geodaten (Amt für Statistik Berlin-Brandenburg), CC-BY.
One command, end to end
A small Python pipeline runs every step and can be re-run any time.
Python pipeline
One command runs find → clean → read → facts → score → contacts → export.
Website crawler
Scrapy fetches each company's own pages.
Claude Agent SDK
Claude Agent SDK with Haiku reads pages and runs web searches.
Google Places API
Finds property offices across Berlin.
One database
SQLite keeps every company, fact and a snapshot of every page read.
Resumable runs
Runs pick up where they stopped after any interruption.
150+ automated tests
Guard the rules, scoring and export on every change.
How the data was checked
Three layers: text matching, strict data rules and AI checks. Every value traces back to the page it came from.
1 · Text matching
- A fact's quote must be on the saved page (exact, or at least 80% of its words).
- Every number, phone and e-mail must appear in that quote.
- A LinkedIn person is kept only if the link and name were in the search results; a job-ad contact only if they are in the ad.
- Facts are rechecked at every export; the dashboard shows the quote and source for every value.
2 · Data types and rules
- Every fact must fit a strict schema: field, category, number, scope and date.
- Values must be one of fixed categories (e.g. WEG, rental or own stock; meters read by hand or remote).
- Rules: ranges ignored, approximate figures labelled, company-wide totals never counted as Berlin, old facts never read as current, Berlin required.
- Duplicates merged; brokers, metering competitors and service firms set aside, with hand checks of samples.
3 · AI checks
- The reading model must quote its source and pick a category for every fact.
- When the code rejects a fact, the model gets the reason and one repair attempt.
- A second AI pass looks for facts that are still missing.
- In the contact search, the model keeps only people whose result shows a current job at the company.
- A separate AI reviewer double-checked facts in the pilots; it was dropped for the full run for speed and cost, and the code checks stayed.
Built to be trusted and cheap to run
Five choices that shape the list.
Proof for every fact
Each fact links to the quote and page it came from.
Fit and reachability kept separate
Sales sees both why a firm matters and how to get through.
AI reads, rules score
The model only collects facts; plain rules rank them, so every score is explainable and cheap.
Company sources and exact numbers first
Facts come from the company's own pages first; an exact published number beats an approximate one, and approximate figures are labelled.
No logins, contacts stay private
Only public pages are read, and the contact list stays inside the sales team.
Under ten cents per lead
Average cost per company at each step. Paid steps run only on companies still in the list.
What's still hard, and what comes next
Honest gaps today, then the natural next steps to add value and to scale.
Limits today
- Personal e-mails are rarely public.
- LinkedIn results often lack job titles.
- Metering provider and contract dates are rarely published (1–2% of companies).
Next steps: more value per lead
- Confirm who manages the apartments. Add job titles from a licensed LinkedIn data provider, so every contact shows whether they run buildings.
- Verified personal e-mails. Check likely addresses with an e-mail verification service before outreach.
- Fresh buying signals. Re-check job ads and websites weekly and flag new hiring, growth or a provider change.
- Learn from sales. Sync leads and call outcomes with the CRM, and tune the fit score on the leads that converted.
Next steps: scale
- All of Germany. Run the map search city by city and postcode by postcode, and add the regional VDIV and housing-association directories.
- Refresh only what changed. Keep the saved pages and re-read only pages that changed, so repeat runs cost a fraction.
- Scheduled runs. A monthly run keeps the list current without manual work.