Automating Lead Enrichment Workflows: From Raw Email to Sales-Ready Contact
By Email ExtractorPublished 9 min read
On this page
What Lead Enrichment Adds
A raw email address tells you almost nothing about the person behind it. Enrichment adds the context needed to prioritise, segment and personalise outreach:
Data point
Where it comes from
How it helps
Full name
Enrichment API, LinkedIn, company website
Personalise outreach
Job title
Enrichment API, LinkedIn
Target the right decision maker
Company name
Domain lookup, enrichment API
Account-based targeting
Company size
Enrichment API, company databases
Qualify by company fit
Industry
Enrichment API, SIC/NAICS codes
Segment by vertical
Location
Enrichment API, company records
Geographic targeting, timezone scheduling
Company revenue
Enrichment API, public filings
Qualify by budget
Technology stack
Technographic data providers
Identify tool users or gaps
Social profiles
Enrichment API
Additional outreach channels
Phone number
Enrichment API, company website
Multi-channel outreach
Company funding
Crunchbase, press releases
Identify companies with budget
The Enrichment Pipeline
Overview
A typical enrichment pipeline moves data through several stages:
Start by extracting email addresses from your source materials:
Gather source files: exported CSVs from events, downloaded PDFs from directories, saved HTML pages from conference sites, spreadsheets from partners.
Upload to Email Extractor to pull email addresses from all file types.
Download as CSV with sources to track which file each address came from.
The tool deduplicates automatically (case-insensitive), so you start with a clean list.
Step 2: Verify
Before spending money on enrichment, verify the addresses exist. This saves enrichment costs by removing addresses that would never receive your email.
Step 3: Enrich
With verified addresses, enrich through APIs or no-code tools.
Building with APIs
Python enrichment script
import requests
import csv
import time
import json
class LeadEnricher:
"""Enrich email addresses with company and contact data."""
def __init__(self, api_key, provider='clearbit'):
self.api_key = api_key
self.provider = provider
self.cache = {}
def enrich_email(self, email):
"""Look up person and company data for an email address."""
if email in self.cache:
return self.cache[email]
# Example using a generic enrichment API pattern
headers = {'Authorization': f'Bearer {self.api_key}'}
url = f'https://api.example.com/v2/combined/find?email={email}'
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
data = response.json()
result = self._parse_response(data)
self.cache[email] = result
return result
elif response.status_code == 404:
return {'email': email, 'status': 'not_found'}
elif response.status_code == 429:
time.sleep(60) # Rate limited; wait and retry
return self.enrich_email(email)
else:
return {'email': email, 'status': 'error',
'error': response.status_code}
except requests.RequestException as e:
return {'email': email, 'status': 'error', 'error': str(e)}
def _parse_response(self, data):
"""Extract relevant fields from the API response."""
person = data.get('person', {})
company = data.get('company', {})
return {
'email': person.get('email', ''),
'first_name': person.get('name', {}).get('givenName', ''),
'last_name': person.get('name', {}).get('familyName', ''),
'title': person.get('employment', {}).get('title', ''),
'seniority': person.get('employment', {}).get('seniority', ''),
'company_name': company.get('name', ''),
'company_domain': company.get('domain', ''),
'company_industry': company.get('category', {}).get(
'industry', ''),
'company_size': company.get('metrics', {}).get(
'employeesRange', ''),
'company_revenue': company.get('metrics', {}).get(
'estimatedAnnualRevenue', ''),
'company_location': company.get('geo', {}).get('country', ''),
'linkedin_url': person.get('linkedin', {}).get('handle', ''),
'status': 'enriched'
}
def enrich_batch(self, emails, output_file, delay=0.5):
"""Enrich a list of emails and write results to CSV."""
fieldnames = [
'email', 'first_name', 'last_name', 'title', 'seniority',
'company_name', 'company_domain', 'company_industry',
'company_size', 'company_revenue', 'company_location',
'linkedin_url', 'status'
]
with open(output_file, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
for i, email in enumerate(emails):
result = self.enrich_email(email)
writer.writerow(
{k: result.get(k, '') for k in fieldnames})
print(f"[{i+1}/{len(emails)}] {email}: "
f"{result.get('status')}")
time.sleep(delay)
print(f"\nResults written to {output_file}")
Domain-based enrichment
When you have only email addresses, the domain itself provides company-level data without a per-contact API call:
def enrich_from_domain(email):
"""Extract company info from the email domain."""
domain = email.split('@')[1].lower()
# Skip free email providers
free_providers = {
'gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com',
'aol.com', 'icloud.com', 'mail.com', 'protonmail.com'
}
if domain in free_providers:
return {'domain': domain, 'type': 'personal', 'company': None}
# For business domains, the domain often is the company website
return {
'domain': domain,
'type': 'business',
'company_website': f'https://{domain}',
# Further enrichment: DNS, WHOIS, or API lookup
}
Building with No-Code Tools
Zapier workflow
Step
Zapier action
Purpose
1. Trigger
New row in Google Sheet (or webhook)
Start enrichment when new email is added
2. Enrichment
Clearbit (or similar) Enrich Person action
Look up person and company data
3. Filter
Only continue if enrichment returned results
Skip addresses with no data
4. Update
Update Google Sheet row with enriched data
Store results alongside original email
5. Route
Create/update CRM contact
Push enriched lead to sales pipeline
Make (Integromat) workflow
Step
Make module
Purpose
1. Trigger
Watch Google Sheet rows (or webhook)
Detect new emails to enrich
2. Iterate
Iterator module
Process one email at a time
3. HTTP request
HTTP module to enrichment API
Call enrichment service
4. Parse
JSON parse module
Extract fields from API response
5. Route
Router module
Different paths for enriched vs not-found
6. Store
Google Sheet or CRM module
Save enriched data
n8n workflow
Step
n8n node
Purpose
1. Trigger
Webhook or Schedule trigger
Start enrichment process
2. Read
Spreadsheet or database node
Load emails to enrich
3. Enrich
HTTP Request node to enrichment API
Look up each email
4. Transform
Function node
Parse and normalise results
5. Filter
IF node
Route based on enrichment success
6. Store
CRM or database node
Save enriched records
Enrichment Data Sources
Enrichment API providers
Provider
Strengths
Typical pricing model
Clearbit (now part of HubSpot)
Strong company data, good coverage of tech companies
Per-lookup or monthly plan
Apollo.io
Combined database and enrichment; large B2B database