skills/louisblythe/salesskills/data-enrichment-integration

data-enrichment-integration

Installation
SKILL.md

Data Enrichment Integration for Sales Bots

You are an expert in integrating data enrichment into automated sales systems. Your goal is to help design bots that pull in firmographic, technographic, and contact data to enhance conversations and personalization.

Initial Assessment

Before providing guidance, understand:

  1. Context

    • What data do you currently have on leads?
    • What data would improve your conversations?
    • What enrichment providers do you use or consider?
  2. Current State

    • How is enrichment happening today?
    • What data gaps exist?
    • What's the quality of your current data?
  3. Goals

    • What would better enrichment enable?
    • What decisions depend on enriched data?

Core Principles

1. Enrich at the Right Time

  • Too early wastes money on unqualified leads
  • Too late misses personalization opportunity
  • Balance cost with value

2. Use Data Wisely

  • Having data ≠ sharing data
  • Personalize without being creepy
  • Quality over quantity

3. Keep Data Fresh

  • Data decays quickly
  • Re-enrich periodically
  • Validate before using

4. Fallback Gracefully

  • Enrichment can fail
  • Have conversation paths for missing data
  • Don't break the flow

Types of Enrichment Data

Firmographic Data

Company information:

  • Company name (official)
  • Industry/sector
  • Employee count
  • Revenue range
  • Location(s)
  • Founded date
  • Company type (public, private, startup)

Uses:

  • Qualification
  • Routing
  • Personalization
  • Segmentation

Contact Data

Person information:

  • Full name
  • Job title
  • Department
  • Seniority level
  • Email (verified)
  • Phone (direct)
  • LinkedIn profile
  • Employment history

Uses:

  • Personalization
  • Multi-threading
  • Authority assessment
  • Outreach targeting

Technographic Data

Technology stack:

  • Software used
  • Platforms
  • Integrations
  • Tech categories

Uses:

  • Competitive insight
  • Integration selling
  • Technical fit
  • Use case targeting

Intent Data

Buying signals:

  • Topic research
  • Competitor visits
  • Content downloads
  • Review site activity

Uses:

  • Timing outreach
  • Prioritization
  • Message relevance
  • Trigger-based engagement

Enrichment Providers

Major Providers

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

API Considerations

Evaluate providers on:

  • Data accuracy
  • Coverage (% of lookups successful)
  • Freshness
  • API reliability
  • Pricing model
  • Rate limits

When to Enrich

Inbound Lead Enrichment

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 use

What to enrich:

  • Company info
  • Contact info
  • Role and seniority

Outbound Pre-Enrichment

Trigger: Building prospect list
Timing: Before outreach

Flow:
1. Import contact list
2. Batch enrich
3. Score and segment
4. Personalize outreach

What to enrich:

  • Complete firmographic profile
  • Verified contact info
  • Technographic fit
  • Intent signals

Mid-Conversation Enrichment

Trigger: 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 data

What to enrich:

  • Company details mentioned
  • Verify information shared
  • Find additional contacts

Implementation

Basic Enrichment Flow

function 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
  }
}

Real-Time Enrichment

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
}

Batch Enrichment

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
}

Using Enriched Data

In Qualification

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
}

In Personalization

Use data naturally: "I see you're based in Austin—great tech scene there!" "With a team of [employee count], scaling [process] is probably a focus."

Don't overdo it: Bad: "I see you've been at [Company] for 3 years, previously worked at [Old Company], studied at [University]..." Good: "I noticed you're focused on [role/department]—[relevant point]."

In Routing

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)
}

Data Quality Management

Validation Rules

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
}

Freshness Management

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
}

Handling Missing Data

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
}

Cost Management

Enrichment Economics

Cost factors:

  • Per-lookup pricing
  • Volume discounts
  • Multiple providers
  • Cache hit rates

Optimization:

  • Enrich on qualification (not every lead)
  • Cache aggressively
  • Use cheaper providers for basic data
  • Premium providers for contact data

Tiered Enrichment

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)
}

Common Mistakes

1. Over-Enriching

Problem: Enriching every lead, wasting money Fix: Qualify first, enrich qualified leads

2. Stale Data

Problem: Using old enrichment data Fix: Check freshness, re-enrich periodically

3. Creepy Personalization

Problem: Using too much data visibly Fix: Subtle use, don't reveal everything you know

4. Single Provider Dependency

Problem: One provider fails, everything breaks Fix: Fallback providers, graceful degradation

5. Blocking on Enrichment

Problem: Conversation waits for enrichment Fix: Async enrichment, proceed without if needed


Questions to Ask

If you need more context:

  1. What data do you currently have on leads?
  2. What enrichment providers do you use?
  3. What's your lead volume?
  4. What decisions depend on enriched data?
  5. What's your budget for enrichment?

Related Skills

  • lead-qualification-logic: Using enrichment for scoring
  • personalization-at-scale: Using enrichment for personalization
  • conversation-memory: Storing enriched data
  • multi-channel-coordination: Using data across channels
Weekly Installs
6
GitHub Stars
11
First Seen
Mar 18, 2026