Loading...
Loading...
When the user wants to build or improve a sales bot's ability to pull in firmographic or contact data mid-conversation. Also use when the user mentions "data enrichment," "lead enrichment," "pulling company data," "contact data lookup," or "real-time data."
npx skill4agent add louisblythe/salesskills data-enrichment-integration| Provider | Strengths | Best For |
|---|---|---|
| Clearbit | Firmographic, real-time | B2B SaaS |
| ZoomInfo | Contact data depth | Outbound prospecting |
| Apollo | Contact + enrichment | Volume outreach |
| Lusha | Direct dials | Phone outreach |
| 6sense | Intent data | ABM |
| Bombora | Intent signals | Enterprise |
| BuiltWith | Technographics | Tech targeting |
Trigger: Form submission or chat initiation
Timing: Immediate
Flow:
1. Lead submits email
2. Enrich on email (async)
3. Use data in conversation
4. Store for future useTrigger: Building prospect list
Timing: Before outreach
Flow:
1. Import contact list
2. Batch enrich
3. Score and segment
4. Personalize outreachTrigger: Learn new information in conversation
Timing: During conversation
Flow:
1. User mentions company name
2. Real-time lookup
3. Adjust conversation with context
4. Store enriched datafunction enrichLead(email) {
// Check cache first
cached = getFromCache(email)
if (cached && !isStale(cached)) {
return cached
}
// Call enrichment API
try {
enriched = enrichmentProvider.lookup(email)
// Validate and clean
validated = validateEnrichment(enriched)
// Store in cache and CRM
storeEnrichment(email, validated)
return validated
} catch (error) {
logError(error)
return null // Graceful fallback
}
}function enrichDuringConversation(message, context) {
// Extract signals from message
company_mentioned = extractCompany(message.content)
email_provided = extractEmail(message.content)
// Enrich asynchronously
if (company_mentioned && !context.company_data) {
enrichCompanyAsync(company_mentioned, context)
}
if (email_provided && !context.contact_enriched) {
enrichContactAsync(email_provided, context)
}
// Continue conversation (don't block)
return generateResponse(message, context)
}
async function enrichCompanyAsync(company, context) {
data = await enrichmentProvider.lookupCompany(company)
context.company_data = data
// Enriched data available for next turn
}function batchEnrich(leads, options) {
results = []
for (batch in chunk(leads, options.batch_size)) {
// Respect rate limits
await rateLimiter.waitForSlot()
// Parallel enrichment within batch
batch_results = await Promise.all(
batch.map(lead => enrichLead(lead.email))
)
results.push(...batch_results)
// Progress tracking
reportProgress(results.length, leads.length)
}
return results
}function qualifyWithEnrichment(lead) {
score = 0
// Employee count scoring
if (lead.enriched.employee_count >= 500) score += 3
else if (lead.enriched.employee_count >= 50) score += 2
else if (lead.enriched.employee_count >= 10) score += 1
// Industry fit
if (IDEAL_INDUSTRIES.includes(lead.enriched.industry)) score += 2
// Title/seniority
if (lead.enriched.seniority == "c_suite") score += 3
else if (lead.enriched.seniority == "director") score += 2
else if (lead.enriched.seniority == "manager") score += 1
// Technology fit
if (usesCompetitor(lead.enriched.technologies)) score += 2
if (usesComplementaryTech(lead.enriched.technologies)) score += 1
return score
}function routeLead(lead) {
// Enterprise routing
if (lead.enriched.employee_count > 1000) {
return assignToEnterpriseTeam(lead)
}
// Geographic routing
if (lead.enriched.country != "US") {
return assignToInternationalTeam(lead)
}
// Industry routing
if (lead.enriched.industry in SPECIALIZED_INDUSTRIES) {
return assignToIndustrySpecialist(lead)
}
// Standard routing
return standardRoundRobin(lead)
}function validateEnrichment(data) {
validated = {}
// Company name - clean and standardize
if (data.company_name) {
validated.company_name = cleanCompanyName(data.company_name)
}
// Employee count - range validation
if (data.employee_count && data.employee_count > 0) {
validated.employee_count = data.employee_count
}
// Email - format validation
if (data.email && isValidEmail(data.email)) {
validated.email = data.email.toLowerCase()
}
// Phone - format and validate
if (data.phone && isValidPhone(data.phone)) {
validated.phone = formatPhone(data.phone)
}
return validated
}function isStale(enrichment_record) {
days_old = daysSince(enrichment_record.enriched_at)
// Different freshness rules by data type
if (enrichment_record.type == "contact") {
return days_old > 30 // Contact data stales faster
}
if (enrichment_record.type == "company") {
return days_old > 90 // Company data more stable
}
if (enrichment_record.type == "intent") {
return days_old > 7 // Intent data very time-sensitive
}
return days_old > 60 // Default
}function getCompanySize(lead) {
if (lead.enriched.employee_count) {
return lead.enriched.employee_count
}
// Fallback: ask in conversation
return askInConversation("company_size")
}
function personalizeMessage(template, lead) {
// Use enriched data where available
company = lead.enriched.company_name || lead.stated_company || "your company"
industry = lead.enriched.industry || null
message = template.replace("{company}", company)
// Only include industry reference if we have it
if (industry) {
message = message.replace("{industry_reference}",
`in the ${industry} space`)
} else {
message = message.replace("{industry_reference}", "")
}
return message
}function enrichByValue(lead) {
lead_score = quickScore(lead)
if (lead_score >= 80) {
// High potential: full enrichment
return fullEnrichment(lead)
}
if (lead_score >= 50) {
// Medium potential: basic enrichment
return basicEnrichment(lead)
}
// Low potential: minimal enrichment
return minimalEnrichment(lead)
}
function fullEnrichment(lead) {
// Firmographic + contact + technographic + intent
return multiProviderEnrich(lead, ["clearbit", "zoominfo", "bombora"])
}
function basicEnrichment(lead) {
// Firmographic + contact only
return singleProviderEnrich(lead, "clearbit")
}
function minimalEnrichment(lead) {
// Just verify email
return emailVerify(lead.email)
}