Cold Email Personalization at Scale: The Middle Ground
Between generic mass emails and hyper-personalized few. Search-based enrichment signals at $0.015/prospect. Full workflow breakdown.
There are two broken approaches to cold email in 2026: generic mass blasts that get 0.5% reply rates, and hyper-personalized emails that take 10 minutes each and do not scale past 20/day. The middle ground is search-based enrichment -- pulling real signals about each prospect at $0.015/contact and using them to generate emails that reference specific, verifiable details.
The three enrichment signals that matter
Not all personalization signals are equal. Three categories move reply rates: recent company news (funding, product launches, pivots), hiring activity (what roles they are adding signals what they are investing in), and tech stack indicators (what tools they use tells you what problems they have). Everything else -- company size, industry, location -- is table stakes that every competitor also has.
Signal extraction workflow
For each prospect, run three targeted searches. The queries matter more than the tool. Generic queries like "Company X" return homepage noise. Specific queries like "Company X series B 2026" or "Company X engineering blog" surface actionable signals.
import requests, os, json
from openai import OpenAI
API = "https://api.scavio.dev/api/v1/search"
H = {"x-api-key": os.environ["SCAVIO_API_KEY"]}
llm = OpenAI()
def enrich_prospect(name: str, company: str, domain: str) -> dict:
"""Pull three signal categories for a prospect."""
searches = {
"news": f"{company} news funding launch 2026",
"hiring": f"{company} hiring jobs careers",
"tech": f"site:{domain} blog engineering stack tools"
}
signals = {}
for category, query in searches.items():
resp = requests.post(API, headers=H, json={
"query": query, "platform": "google", "num_results": 5
})
results = resp.json().get("organic_results", [])
signals[category] = [
{"title": r["title"], "snippet": r.get("snippet", "")}
for r in results[:3]
]
return {"name": name, "company": company, "signals": signals}
def generate_email(prospect: dict) -> str:
"""Generate personalized email using real search signals."""
signals = json.dumps(prospect["signals"], indent=2)
prompt = f"""Write a 4-sentence cold email to {prospect['name']} at {prospect['company']}.
Real search signals about this company:
{signals}
Rules:
- First sentence references ONE specific signal from the search results
- Second sentence connects that signal to a problem you solve
- Third sentence states the value prop concretely (numbers if possible)
- Fourth sentence asks a specific question, not "would you be open to a chat"
- Do not invent any facts not present in the signals above"""
resp = llm.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
max_tokens=300
)
return resp.choices[0].message.content
# Process a batch
prospects = [
{"name": "Jane Chen", "company": "Acme Corp", "domain": "acmecorp.com"},
{"name": "Mike Torres", "company": "DataFlow", "domain": "dataflow.io"},
]
for p in prospects:
enriched = enrich_prospect(p["name"], p["company"], p["domain"])
email = generate_email(enriched)
print(f"--- {p['name']} ---")
print(email)Cost per prospect breakdown
Three search queries: 3 x $0.005 = $0.015. One LLM call (GPT-4o, ~500 tokens in, ~150 out): ~$0.003. Total: $0.018/prospect. For 1,000 prospects/month: $18. Compare that to Clay at $150-300/mo for similar enrichment, or doing it manually at 10 minutes/prospect (166 hours/month for 1,000 contacts). The search-based approach is cheaper than Clay and 100x faster than manual.
Quality control: the human review step
Do not auto-send. Generate emails as drafts in your email client or sequencer. Spend 15-20 seconds reviewing each one. You are checking for two things: did the LLM hallucinate a fact that is not in the search signals, and does the email read like a human wrote it? The LLM will occasionally invent details. Catching these before send protects your credibility.
When this approach does not work
Search-based enrichment fails for stealth-mode startups with no public presence, very small companies with minimal web footprint, and prospects in industries that do not produce public content. For these segments, fall back to LinkedIn-based signals (manual) or skip personalization and lead with a strong value prop instead. Not every prospect is worth the enrichment cost.
Scaling past 1,000/month
At 5,000 prospects/month, the search cost is $75 (15,000 credits). Scavio's $30/mo plan covers 7,000 credits. Beyond that, credits are $0.005 each. The LLM cost scales linearly. The bottleneck shifts from cost to review time: 5,000 emails at 20 seconds each is ~28 hours of review. At this scale, you need to prioritize which prospects get the enriched treatment and which get a simpler template.
How Scavio fits
Scavio provides the search layer at $0.005/credit. Three credits per prospect, structured JSON response, Google and other platforms available. The free tier at 250 credits/mo covers ~83 fully enriched prospects for testing. The predictable per-credit pricing makes it easy to forecast costs as volume scales -- no surprise overages or tier jumps.