Foundation
Deliverability
Can we actually reach this lead? Verify at capture, act on bounces, and put the verdict on the contact — for every brand.
Deliverability · Can We Actually Reach Them
Every brand runs on two channels it does not own. An address or a number that cannot be reached is not a small data-quality problem — it is a lead you paid for and cannot talk to, and the failure is silent by default.
Warning
The rule: an address is innocent until a provider tells us otherwise, and the verdict lives ON THE CONTACT. Not in a vendor dashboard, not in a log — on the row, where the card renders it and the sender checks it.
The two layers, and why you need both
| Layer | Catches | Cannot catch |
|---|---|---|
| Verify at capture (MillionVerifier / Twilio Lookup) | typos, dead domains, disposable addresses, no-mailbox, not-a-phone | a real address that fills up or dies later |
| Act on the bounce (provider webhook) | full mailboxes, addresses that die after capture, spam complaints, sends the provider refuses | anything, before the first send |
Neither replaces the other. Verification stops you building a sequence on a fiction; the webhook is the only thing that ever tells you the truth about a real address.
Required at every capture path
Verification runs on every entry point — web form, lead-ad webhook, chat platform, sheet import, referral inbox. One shared module, called by all of them. A path that captures a lead without verifying is a bug.
| Verdict | What to do |
|---|---|
ok · catch_all · unknown | Accept. Inconclusive is not the same as bad. |
invalid · disposable | Reject at capture with the reason. Never enrol. |
| vendor error | Accept the lead, record unverified. Never record it as a pass. |
Warning
Fail open, never fail silent. A vendor being down must not cost a lead — but "the checker broke" and "the address is good" must never be the same stored value. If they are, a broken checker is indistinguishable from a working one and stays broken indefinitely. Alert when the vendor-error rate is not near zero.
Required on the send path
- Check the contact's deliverability verdict before sending or enrolling.
- A hard bounce or spam complaint is permanent — suppress that address forever.
- A full mailbox is transient — stop the sequence, keep the address, use the other channel.
- Never schedule into a mailbox a provider has already told you is failing.
Required on the card
The rep sees the dead channel before they build a plan on it — not after they have waited on a call. Show the state and the human reason ("Email bouncing — their inbox is full. Use phone."), never a raw SMTP string.
Reconcile the provider's suppression list
Providers keep their own suppression list and silently drop sends to it. If you never read it back, your database will happily enrol a suppressed address in a nine-email sequence and log nine sends that never happened.
Where this came from
A booked consult, 2026-09-10. The lead's confirmation and her 1-hour reminder both
bounced — 552 5.2.2 user is over quota — and the rep sat waiting for a call with
someone who had no idea it was happening.
Everything that could have caught it was already built and paid for:
- The verifier had the answer. MillionVerifier returns
invalid / mailbox_fullfor that exact address. It was called at capture. - The prod API key carried a literal
\n— 27 characters where the working key is 25 — so every call returnedresult:"error", error:"Apikey not found". Note.trim()does not fix this: the value ends in the two characters backslash and n. Sanitise keys for real whitespace, quotes and literal escape sequences. "error"was on the accept-list, alongsideokandcatch_all. So the vendor failing and the address being good produced the same stored value. 126 of 126 verified contacts recorded"error"— a 100% failure rate that was invisible for months.- The bounce webhook was subscribed to
email.bouncedand discarded it. The handler mapped opens and clicks and returnedok: truefor everything else. The provider told us twice, for the same lead, and we said thank you.
Sizing it afterwards: of the last 100 sends, 66 delivered — 16 failed, 6 bounced, 6 were suppressed. Better than a quarter of the email went nowhere and none of it was visible in our own database.
Enforced, not documented
A written standard does not enforce itself — MCM was fixed and DH still carried the identical bug months later, because brand sites are hand-cloned and there is no scaffold. So the standard is code:
packages/deliverability/ | The one implementation. Edit here, never in a brand. |
npm run deliverability:sync | Installs it into every brand site. |
npm run deliverability:gate | Fails the build on: capture without verification · verifier "error" treated as a pass · a sending brand with no bounce handler · a brand copy that has drifted from canon. |
Wire the gate into CI beside security:gate.
Checklist for a brand install
| Check | |
|---|---|
| Verification called from every capture path | |
API keys sanitised for whitespace, quotes and literal \n | |
Vendor error recorded as unverified, never as a pass | |
| Alert when the vendor-error rate is not ~0 | |
| Provider webhook subscribed to bounce + complaint + failure | |
| Webhook handles them — timeline event + verdict on the contact | |
| Send path checks the verdict before sending or enrolling | |
| Permanent vs transient distinguished (hard bounce vs full mailbox) | |
| Card shows the dead channel in plain language | |
| Provider suppression list reconciled against contacts |