Generic cold emails get ignored. Personalized emails referencing a prospect's actual online presence get replies. This tutorial builds a SERP audit pipeline that researches each prospect's company, finds their top-ranking pages, identifies content gaps, and generates personalized email opening lines. Each audit costs 2-3 search queries ($0.010-0.015) and produces actionable intel for your email.
Prerequisites
- Python 3.9+ installed
- requests library installed
- A Scavio API key from scavio.dev
- A list of prospect company names or domains
Walkthrough
Step 1: Define your prospect list
Load prospect companies to audit. Each gets a mini SERP research session.
prospects = [
{'name': 'Acme SaaS', 'domain': 'acmesaas.com', 'contact': 'jane@acmesaas.com'},
{'name': 'TechFlow', 'domain': 'techflow.io', 'contact': 'mike@techflow.io'},
{'name': 'DataSync Pro', 'domain': 'datasyncpro.com', 'contact': 'sarah@datasyncpro.com'},
]
queries_per_prospect = 3 # brand, competitors, content
total_cost = len(prospects) * queries_per_prospect * 0.005
print(f'{len(prospects)} prospects x {queries_per_prospect} queries each')
print(f'Estimated cost: ${total_cost:.3f}')Step 2: Run the SERP audit for each prospect
Search for the company name, their competitors, and their content to build a profile.
import requests, os, time
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
def search(query: str) -> list:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
json={'query': query, 'country_code': 'us', 'num_results': 10})
return resp.json().get('organic_results', [])
def audit_prospect(prospect: dict) -> dict:
name = prospect['name']
domain = prospect['domain']
# Query 1: Brand presence
brand_results = search(f'{name} reviews')
brand_mentions = len([r for r in brand_results if domain in r.get('link', '')])
# Query 2: Competitor landscape
competitor_results = search(f'{name} alternatives competitors 2026')
competitors = [r['title'].split(' - ')[0] for r in competitor_results[:3]
if domain not in r.get('link', '')]
# Query 3: Content presence
content_results = search(f'site:{domain}')
top_pages = [r['title'] for r in content_results[:5]]
time.sleep(0.3)
return {
'prospect': name,
'brand_mentions_in_top10': brand_mentions,
'competitors': competitors[:3],
'top_pages': top_pages,
'has_blog': any('blog' in r.get('link', '').lower() for r in content_results)
}
# Audit first prospect
audit = audit_prospect(prospects[0])
for key, val in audit.items():
print(f' {key}: {val}')Step 3: Generate personalized email opening lines
Use the audit data to craft a personalized opening line for each prospect. Reference their actual content and competitive position.
def generate_opening(audit: dict) -> str:
name = audit['prospect']
templates = []
if audit['has_blog']:
page = audit['top_pages'][0] if audit['top_pages'] else ''
templates.append(
f'I noticed {name} has been publishing content like "{page[:40]}" -- '
f'curious if you are tracking how that ranks against {audit["competitors"][0] if audit["competitors"] else "competitors"}.'
)
if audit['brand_mentions_in_top10'] < 3:
templates.append(
f'{name} only appears {audit["brand_mentions_in_top10"]} times in the top 10 '
f'for brand searches. That is a quick win we could help with.'
)
if audit['competitors']:
templates.append(
f'Noticed {audit["competitors"][0]} is showing up in "{name} alternatives" '
f'searches -- are you monitoring that?'
)
return templates[0] if templates else f'Researched {name} and found some ranking opportunities.'
# Generate for all prospects
for p in prospects:
audit = audit_prospect(p)
opening = generate_opening(audit)
print(f'To: {p["contact"]}')
print(f'Opening: {opening}')
print()Python Example
import requests, os, time
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
def search(query):
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
json={'query': query, 'country_code': 'us', 'num_results': 10})
return resp.json().get('organic_results', [])
def audit(name, domain):
brand = search(f'{name} reviews')
competitors = search(f'{name} alternatives 2026')
content = search(f'site:{domain}')
return {
'mentions': len([r for r in brand if domain in r.get('link', '')]),
'competitors': [r['title'].split(' - ')[0] for r in competitors[:3]],
'top_pages': [r['title'] for r in content[:3]]
}
result = audit('Acme SaaS', 'acmesaas.com')
print(f'Brand mentions: {result["mentions"]}')
print(f'Competitors: {", ".join(result["competitors"])}')JavaScript Example
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
async function search(query) {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query, country_code: 'us', num_results: 10 })
});
return (await resp.json()).organic_results || [];
}
async function audit(name, domain) {
const brand = await search(`${name} reviews`);
const competitors = await search(`${name} alternatives 2026`);
return {
mentions: brand.filter(r => r.link?.includes(domain)).length,
competitors: competitors.slice(0, 3).map(r => r.title.split(' - ')[0])
};
}
audit('Acme SaaS', 'acmesaas.com').then(r => {
console.log(`Mentions: ${r.mentions}`);
console.log(`Competitors: ${r.competitors.join(', ')}`);
});Expected Output
3 prospects x 3 queries each
Estimated cost: $0.045
prospect: Acme SaaS
brand_mentions_in_top10: 2
competitors: ['RivalCRM', 'BetterSaaS', 'CloudTools']
top_pages: ['Acme SaaS - All-in-One CRM', 'Acme Blog: Sales Tips']
has_blog: True
To: jane@acmesaas.com
Opening: I noticed Acme SaaS has been publishing content like "Acme Blog: Sales Tips" -- curious if you are tracking how that ranks against RivalCRM.