Cold email outreach fails when messages are generic. The highest-performing cold emails reference something specific about the prospect: a recent blog post, a product launch, a hiring signal, or a tech stack detail. Building a one-page audit pipeline automates this research step by querying search data for each prospect domain, extracting relevant signals, and generating a brief audit that your email template can reference. This tutorial shows how to build a cold email audit pipeline that enriches each prospect with live search data from Scavio, producing personalization hooks that increase reply rates.
Prerequisites
- Python 3.8+ installed
- requests and csv libraries
- A Scavio API key from scavio.dev
- A CSV file with prospect domains
Walkthrough
Step 1: Load prospect list
Read your prospect CSV file containing company names and domains.
import os, requests, csv, json
API_KEY = os.environ["SCAVIO_API_KEY"]
def load_prospects(path):
with open(path) as f:
return list(csv.DictReader(f))
prospects = load_prospects("prospects.csv")
print(f"Loaded {len(prospects)} prospects")Step 2: Audit each prospect domain
Search for each prospect's domain to find recent news, blog posts, and company signals.
def audit_prospect(domain):
resp = requests.post("https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": "google", "query": f"site:{domain}"})
results = resp.json().get("organic_results", [])[:5]
return {
"domain": domain,
"pages_found": len(results),
"recent_content": [r.get("title", "") for r in results[:3]],
"snippets": [r.get("snippet", "")[:120] for r in results[:3]],
}
audit = audit_prospect("example.com")
print(json.dumps(audit, indent=2))Step 3: Extract personalization hooks
Parse audit results to find actionable personalization hooks for cold emails.
SIGNALS = ["hiring", "launched", "raised", "partnered", "expanded", "new feature", "blog"]
def extract_hooks(audit):
hooks = []
for snippet in audit.get("snippets", []):
lower = snippet.lower()
for signal in SIGNALS:
if signal in lower:
hooks.append({"signal": signal, "context": snippet[:100]})
if not hooks and audit.get("recent_content"):
hooks.append({"signal": "content", "context": audit["recent_content"][0]})
return hooks[:2]
hooks = extract_hooks(audit)
print(f"Found {len(hooks)} hooks")Step 4: Generate audit CSV
Run the pipeline for all prospects and export enriched audit results.
def run_pipeline(prospects):
enriched = []
for p in prospects:
domain = p.get("domain", "")
if not domain: continue
audit = audit_prospect(domain)
hooks = extract_hooks(audit)
enriched.append({
**p,
"hook_1": hooks[0]["context"] if hooks else "",
"hook_signal": hooks[0]["signal"] if hooks else "",
"pages_found": audit["pages_found"],
})
return enriched
results = run_pipeline(prospects[:5])
with open("enriched_prospects.csv", "w", newline="") as f:
w = csv.DictWriter(f, fieldnames=results[0].keys())
w.writeheader()
w.writerows(results)
print(f"Exported {len(results)} enriched prospects")Python Example
import os, requests
API_KEY = os.environ["SCAVIO_API_KEY"]
def audit(domain):
resp = requests.post("https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": "google", "query": f"site:{domain}"})
results = resp.json().get("organic_results", [])[:3]
return {"domain": domain, "pages": len(results),
"titles": [r["title"] for r in results]}
print(audit("stripe.com"))JavaScript Example
const H = {"x-api-key": process.env.SCAVIO_API_KEY, "Content-Type": "application/json"};
async function audit(domain) {
const r = await fetch("https://api.scavio.dev/api/v1/search", {
method: "POST", headers: H,
body: JSON.stringify({platform: "google", query: `site:${domain}`})
});
const results = (await r.json()).organic_results || [];
return {domain, pages: results.length, titles: results.slice(0,3).map(r=>r.title)};
}
audit("stripe.com").then(console.log);Expected Output
An enriched CSV of prospects with personalization hooks extracted from live search data, ready for cold email templates.