Outbound qualification

Lead qualification engine

Reads public business listings, audits every website, and puts a ranked batch in front of a person. Most of the work is deciding who not to contact.

  • 12,370

    listings read in one run

    Public business listings across 60 cities.

    One run, 4 Oct 2026

  • 2,739

    sites held back before a word is written

    330 carried another business's name; the rest did not load or had nothing worth raising.

    One run, 4 Oct 2026

  • 0

    repeat sends

    Checked by business and by address.

    9 Sep – 3 Oct 2026

The same figures, restyled

One run · 4 Oct 2026

  1. Discover12,370
  2. Filters8,184
  3. Audit7,632
  4. Fit gate5,445
  5. Recipients3,008
  6. Batch250

Counts from the run. Each stage keeps only what passed.

The problem

We know who we want to reach. We can’t tell which of a thousand listings deserves a person’s attention.

Before and after

Before

  • A list from a map search, sorted by nothing.
  • Addresses copied off web pages, valid or not.
  • The same owner reached twice through two listings.
  • Sending stops when someone remembers to stop it.

After

  • Every site audited and scored; sites that fail to load, belong to another business, or have nothing to raise are held back.
  • Every address matched against a strict pattern, then checked by a verifier, before it is used.
  • One sent-log, checked by business and by address.
  • A bounce-rate breaker halts sending. A person approves each day’s plan.

Coverage — one run, 4 Oct 2026

Sixty cities read. Most of what was read never reaches a person.

One ring per city, sized by listings read; the filled disc is what passed the fit gate.

Rank 1: 1,862 read, 854 passedRank 2: 646 read, 257 passedRank 3: 559 read, 243 passedRank 4: 455 read, 251 passedRank 5: 445 read, 139 passedRank 6: 404 read, 184 passedRank 7: 401 read, 247 passedRank 8: 398 read, 226 passedRank 9: 371 read, 162 passedRank 10: 366 read, 114 passedRank 11: 351 read, 216 passedRank 12: 341 read, 122 passedRank 13: 332 read, 115 passedRank 14: 295 read, 103 passedRank 15: 173 read, 90 passedRank 16: 159 read, 88 passedRank 17: 150 read, 55 passedRank 18: 149 read, 61 passedRank 19: 148 read, 91 passedRank 20: 145 read, 76 passedRank 21: 145 read, 80 passedRank 22: 144 read, 82 passedRank 23: 143 read, 44 passedRank 24: 140 read, 85 passedRank 25: 139 read, 37 passedRank 26: 137 read, 77 passedRank 27: 135 read, 46 passedRank 28: 133 read, 41 passedRank 29: 133 read, 76 passedRank 30: 133 read, 59 passedRank 31: 132 read, 73 passedRank 32: 122 read, 59 passedRank 33: 119 read, 72 passedRank 34: 119 read, 66 passedRank 35: 116 read, 29 passedRank 36: 116 read, 46 passedRank 37: 116 read, 71 passedRank 38: 116 read, 71 passedRank 39: 110 read, 38 passedRank 40: 108 read, 74 passedRank 41: 108 read, 30 passedRank 42: 106 read, 41 passedRank 43: 106 read, 46 passedRank 44: 103 read, 16 passedRank 45: 100 read, 14 passedRank 46: 100 read, 53 passedRank 47: 96 read, 55 passedRank 48: 95 read, 17 passedRank 49: 94 read, 33 passedRank 50: 93 read, 15 passedRank 51: 85 read, 33 passedRank 52: 83 read, 32 passedRank 53: 81 read, 15 passedRank 54: 79 read, 38 passedRank 55: 77 read, 12 passedRank 56: 75 read, 27 passedRank 57: 57 read, 17 passedRank 58: 54 read, 21 passedRank 59: 42 read, 4 passedRank 60: 30 read, 6 passed
60 cities across 6 countries. Dot size is listings read; the lit share is what passed the fit gate.

12,370

listings read

5,445

passed the fit gate

Ten largest coverage areas by listings read
AreaRankReadPassed
City A11,862854
City B2646257
City C3559243
City D4455251
City E5445139
City F6404184
City G7401247
City H8398226
City I9371162
City J10366114

Run replay

One run, stage by stage.

From 12,370 public listings to a batch of 250: 4,186 dropped by hard filters, 552 sites that did not load, 2,187 held back by the fit gate, 2,437 with no usable recipient, then the top 250.

Design decisions

What we chose, and what we turned down.

01

The fit gate and the opening line are code, not a model.

Rejected

Have a model read each site and write a personal opening line.

Why

A line that goes to a real business can only restate a field the audit measured. A lookup table cannot invent a fact; a model can, and nobody reads 250 lines for it. Where the audit’s vocabulary is still thin, an unclassifiable booking path gets copy that makes no booking claim.

02

An address is validated twice: when it is extracted and again when it is used.

Rejected

Validate once, at extraction.

Why

Cached audit records are returned as stored, so they never pass a rule added later. One definition of “an address we will try to send to”, applied at both ends, fails closed.

03

A bounce-rate breaker with no timer.

Rejected

Pause for a day, then resume.

Why

The rate is measured over the last sends, so waiting changes nothing; the cause is in the data. Above 8% over the last 100 known sends the gate holds until a person fixes the cause and overrides on purpose. A newer mailbox halts at two hard bounces.

04

Deduplicate by address as well as by business, in a ledger this system owns.

Rejected

Key the log by business only, in a ledger shared with other systems.

Why

Two listings once published one owner’s mailbox; a business-keyed log would have written to it twice, minutes apart. A shared ledger ties this system’s failures to every other’s, so this one reads outside ledgers and never writes them.

Human in control

What a person still decides

The plan is computed before the day starts. Nothing sends until someone approves it on a local page. If no one does within 12 hours, the page closes and nothing is sent. Replies are drafted by the system and sent only after approval.

Mock — illustrative data
BusinessCityAddress checkContacted before
Example Guesthouse AExample Cityokno
Example Guesthouse BExample Cityriskyno
Example Guesthouse CAnother Cityrefusedno
Example Guesthouse DAnother Cityokno
Approve planDeclineIllustrative data.

The hard part

Placeholder addresses reached the send gate

Symptom

In the first batch, 3 of 60 leads carried only obfuscated placeholder addresses, such as a masked “co*****@***.com”. Every send attempt to them failed over four days.

First fix

The extractor took mailto links verbatim. We required a full match against a strict address pattern.

Recurrence

Over the next five days the same masked values kept reopening the send gate.

Root cause

Cached audit records are returned as stored. They had never passed the new check.

Fix

One definition of a sendable address, applied at extraction, on cached records, and again at send.

Now guaranteed

A malformed address cannot reach a send, whichever path produced it.

Stack

Python; a headless browser for listing discovery; a self-hosted address verifier; a transactional email API and an SMTP mailbox; scheduled jobs. State is JSON, written to a temp file and renamed, so a crash cannot leave half a file.

Cost to run

The qualification path makes no model calls and pays no per-lookup fee.

Where this engineering shows up

The same pattern, a written rule deciding and no model in the pass/fail path, is what checks every certificate in our vendor insurance compliance service.

Start here

Know which vendors are actually covered. Every week, without chasing anyone.

Within 7 business days you get a deficiency report: each certificate, each requirement it fails, and the page that shows it. No contract, no sales call.