I built the data enrichment pipeline that feeds our account-based marketing program, pulling together firmographic, technographic, and intent signal data from multiple external providers and blending it with our own first-party engagement data to identify and prioritize target accounts. This project taught me that the actual difficulty in ABM data enrichment isn't acquiring data, providers are everywhere and reasonably affordable, it's reconciling data that different sources describe differently for what should be the same underlying account.
Every enrichment provider we use has their own internal identifier for a given company, and none of those identifiers match each other or our own CRM's account IDs out of the box. Matching accounts across sources by company name alone fails constantly, because the same company gets represented differently across different data providers, sometimes with a legal entity suffix, sometimes without, sometimes under a former name after an acquisition that one provider's data hasn't caught up with yet.
I built a matching pipeline that uses multiple signals together rather than relying on name matching alone, primary domain as the strongest signal since it's relatively stable and unambiguous, combined with fuzzy name matching and location data as supporting signals when domain matching alone doesn't resolve cleanly. Even with this layered approach, a meaningful percentage of accounts still require manual review to resolve correctly, particularly for larger enterprise accounts with multiple subsidiaries and regional entities that genuinely may or may not represent the same actual target account depending on how our sales team organizes their territory.
Different enrichment providers frequently disagree with each other on basic firmographic facts, employee count, revenue estimates, industry classification, sometimes by a meaningful margin, because each provider uses different underlying data sources and different estimation methodologies. Our early pipeline just used whichever provider we queried first for each field, which meant our firmographic data was essentially arbitrary depending on API response ordering rather than reflecting any genuine assessment of which source was more reliable for a given data point.
I rebuilt this with an explicit source-of-truth hierarchy per field type, based on actually testing each provider's accuracy against a sample of accounts where we had reliable ground truth, industry classification from provider A performed better against our validation sample than provider B, while employee count estimates from provider B were more reliable than provider A, and so on field by field. This meant building a genuinely more complex merge logic than simply picking one preferred provider globally, but it produced meaningfully more accurate blended data than either single provider alone or an arbitrary first-response merge strategy would have.
Third-party intent data, signals suggesting a company is actively researching topics related to what we sell, sounded like it would be immediately actionable when we first added it to the pipeline, and in practice raw intent scores without context led sales and marketing to chase a lot of noise. A spike in intent signal around a broad topic could mean genuine active buying research, or it could mean an employee at that company read one article for reasons entirely unrelated to any purchase intent, and the raw score alone doesn't distinguish between these very different situations.
We now combine intent signal with our own first-party engagement data before treating anything as a genuinely qualified priority signal, an intent spike on a topic combined with actual engagement with our own content or website within a similar window is treated very differently from an intent spike with zero corresponding first-party engagement. This combined approach produces a meaningfully smaller number of flagged accounts than raw intent data alone would generate, but the accounts it does flag have converted to genuine sales conversations at a noticeably higher rate, which is a much more useful outcome for both sales and marketing than a larger volume of low-confidence signals.
Not every piece of enrichment data needs the same refresh cadence, and treating all fields with a single, one-size-fits-all refresh schedule wastes API budget on fields that rarely change while leaving genuinely time-sensitive fields stale for longer than they should be. Employee count and revenue estimates don't meaningfully shift week to week, so refreshing those quarterly is more than sufficient. Intent signals and recent funding or leadership change events, by contrast, are only valuable when reasonably current, and refreshing those on a weekly cadence is worth the additional API cost given how quickly their relevance decays.
I built field-specific refresh schedules into the pipeline rather than a single global refresh cadence, which both reduced our overall provider API costs and improved the actual freshness of the specific fields where freshness genuinely matters most for the program's effectiveness.
Early in building this pipeline, a provider API outage caused a batch enrichment run to partially fail in a way that wasn't obviously visible, some accounts ended up with fields populated from a stale prior enrichment run while other fields for those same accounts reflected the new run, creating internally inconsistent records that looked complete but actually blended data from two different points in time. This kind of quiet partial failure is more dangerous than a full, obvious failure, because it doesn't trigger any alert and the resulting bad data just flows downstream into account scoring and campaign targeting without anyone noticing until the output looks wrong for reasons that take real investigation to trace back to the source.
I rebuilt the pipeline to treat each enrichment run per account as an atomic operation, either every field for that account updates successfully together or none of them do, with a clear failure log for any account that didn't fully process, rather than allowing partial updates to silently create internally inconsistent blended records.
Don't assume account matching across providers will be straightforward, invest real effort in a layered matching strategy using domain and other stable signals, not name alone. Build an explicit, tested source-of-truth hierarchy per field rather than an arbitrary merge order across providers. Combine intent data with your own first-party engagement signal before treating it as genuinely actionable, since raw intent alone produces too much noise to be reliably useful on its own. Match refresh cadence to how quickly each specific field actually changes rather than using one global schedule. And design for atomic updates per account so a partial pipeline failure fails visibly and loudly, rather than silently corrupting data with a blend of stale and current information that nobody notices until much further downstream.