B2B Revenue Autopilot Kit

Technical guide · 17 October 2026 · 9 min read

AI lead scoring for local businesses: a rubric that survives real data

“Score this lead from 0 to 100” is not a rubric, it is a wish. A score is useful only if two different runs give the same number for the same business, if you can explain the number to a client, and if the cut-off you set corresponds to something you can actually sell. Here is the rubric we ship, and how to tune it without guessing.

Rule zero: the model scores, the code decides what is even worth scoring

Anything you can compute from the raw data must be computed in code — cheaper, deterministic, auditable, free. What is left for the model is judgement: is this category worth a proposal, what is the most likely commercial pain, how would a consultant open the conversation.

In practice that means the pipeline computes a cheap prior first (no website, mobile-only site, few reviews, permanently closed) and passes it to the model as context under a name like score_previo. The model sees it, may disagree with it, and the final number is the model's. Two numbers, two purposes: the prior tells you where to look, the score tells you whom to call.

The rubric: six positive signals and one veto

Weights are the part clients argue about, so they should be written down and visible rather than buried in a prompt. Ours sum to exactly 100:

SignalWeightWhy it predicts a sale
No website, or the site returns an error+35The most sellable gap in local B2B. It is visible, it is binary, and it has a fixed price.
Fewer than 30 Google reviews+15Low review volume correlates with low digital maturity and with an owner who still answers the phone.
Rating between 3.0 and 4.5+10Good enough to be operating, bad enough that reputation work has a measurable upside.
Public phone number available+15A lead you cannot call is a row, not a lead. This is also the field that moves the maps SKU.
Business is operational+15Closed permanently or temporarily is a wasted call, and a quick way to burn the list.
High value per client category+10Health, dental, legal, real estate, accounting, construction: ticket sizes that absorb a retainer.
Looks like a chain, franchise or national branch-20Veto. The decision is made at headquarters, not by the person who picks up the phone.

Two consequences worth stating out loud. First, the positive signals already add to 100, so a franchise with every other signal present lands on 80 — the veto has to be strong enough to matter, and clamping to 0–100 must be explicit or you will get 115s in your sheet. Second, the weights encode a business model: if you sell reputation management instead of websites, +35 belongs on reviews and the website drops to +10. The rubric is not universal; it is a statement about what you can deliver.

Make the model return structure, not prose

The output is a fixed JSON object with no extra keys. That is not stylistic taste — the next node needs to read fields, and every free-text sentence is a field you will end up parsing with a regex at 2 a.m.

{
  "id": "the exact id you received, unmodified",
  "score": 0,
  "motivo": "one sentence, max 20 words, justifying the score",
  "dolor_principal": "the most likely commercial pain, max 12 words",
  "servicio_sugerido": "one of: web, seo_local, automatizacion, reputacion, crm",
  "pitch": "first-contact message, max 45 words, personalised with the business name"
}

The id field is load-bearing. Batched requests come back reordered and sometimes short one item. The merging node builds a placeId → business dictionary and drops anything it cannot match. If you delete id from the output schema, every row is discarded and the flow looks broken when it is being perfectly disciplined.

Determinism is a setting, not a hope

Calibrate minScore with the discards, not with your intuition

Every threshold you set produces two lists: what passed and what did not. Most templates throw the second one away. Keep it — route the failures into a no-op node so the execution shows the count, then look at them:

  1. Nothing above 60? Your niche is saturated with businesses that already have a website. That is information about the market, not about the model: change the niche before you change the weights.
  2. Everything above 90? The model is agreeing with the prior instead of judging. Lower the temperature first, then rewrite the rubric with harder language (“be strict”, explicit negative examples).
  3. A suspicious cluster at exactly the same number? You are reading the prior, not the score. Check that the prompt asks for a computed score and that the merge node takes the model's field.

A practical sequence: start at 60, run a week against real data, then raise to 70. Raising costs nothing and saves tokens; lowering is how you end up with 200 rows and no calls made.

What not to ask the model for

The rubric is the free part; the wiring is the work

The Starter kit ships this rubric as a configuration node you edit in one place — niche, city, minimum score, model, output language — with the batching, the identifier pairing and the try/catch around parsing already solved.

See the kit Back: the pipeline

Related: the five stages of the pipeline · why the second run returns nothing · all articles