How to Turn a Company List Into Verified B2B Contacts
A list of company names is an account hypothesis, not a prospect list. Before outreach, we need to confirm which company each row represents, define the buying roles we need, find current people, apply a verification policy and preserve every unresolved match as an exception. If we skip those controls, similarly named companies, duplicate domains and irrelevant titles can enter the campaign unnoticed.
This guide turns a company CSV into an auditable contact list. We will define the input and output contracts, normalize websites, map buying roles, search with supported Getlead filters, create an exception queue and measure coverage without pretending that every company will produce a verified result.
Define the completed job
Input:
- Company;
- ideally Website/domain;
- optional Industry, Country and Account ID.
Output:
- confirmed account identity;
- one or more relevant buying-role contacts;
- approved verification status;
- clear exception for unmatched/ambiguous rows;
- native export and workflow fields kept separate.
We do not call the work complete because a tool produced some people. We must be able to explain which account and role every contact represents.
The minimum input contract
| Field | Status | Purpose | |---|---|---| | Company | Required | Account identity and review | | Website | Strongly recommended | Disambiguation and domain key | | Industry | Optional | ICP review | | Country | Optional | Geographic review | | Account ID | Optional but recommended | CRM join and deduplication |
Company alone can begin research, but a common name without Website creates higher ambiguity. We do not invent a domain from the company name and treat it as confirmed.
Example:
Company,Website,Industry,Country,Account ID
Northstar Cloud,https://www.northstarcloud.example/pricing?ref=list,B2B SaaS,United States,ACC-001
Signal Harbor,signalharbor.example,Software,United States,ACC-002
Northstar Cloud,www.northstarcloud.example,B2B SaaS,United States,ACC-003
All examples are synthetic.
Preserve source and provenance
Before transforming:
Source name
Export date
Owner
Original row number
Source account ID
Filters/context
We preserve the raw CSV. Normalization creates comparison values; it does not destroy source values.
If several sources are merged, add Source and Source Record ID. When values conflict, “newest” is not automatically correct. We look for current, attributable evidence.
Normalize websites and domains
For comparison:
- lowercase;
- remove
http://orhttps://; - remove leading
www.; - remove path, query and fragment;
- remove trailing dot/slash;
- apply IDN handling consistently;
- preserve original Website separately.
Example:
https://www.northstarcloud.example/pricing?ref=list
→ northstarcloud.example
We do not automatically merge:
- different country domains;
- parent and subsidiary domains;
- redirecting/parked domains;
- similar spellings;
- social profile URLs.
Those become review states unless evidence establishes the relationship.
Deduplicate accounts
Primary account key:
normalized Website/domain
Fallback:
normalized Company + Country
Fallback matches require review. Two different companies can share a name.
When duplicates exist, we:
- choose a survivor;
- preserve all source Account IDs;
- merge only compatible fields;
- retain conflict notes;
- move the losing row to an audit file.
Example codes:
DUPLICATE_DOMAIN
DUPLICATE_NAME_COUNTRY
CONFLICTING_INDUSTRY
CONFLICTING_COUNTRY
Confirm ICP before finding people
Our approved example is US B2B SaaS companies with sales leaders.
We check:
- Industry supports B2B software/SaaS fit.
- Country is United States for this segment.
- Website represents the target company.
- Employee Count, after contact export, does not contradict the approved size hypothesis if one exists.
- Explicit exclusions do not apply.
If account fit is uncertain, finding an email does not fix it. Hold the account.
Use the Ideal Customer Profile Builder when the account rules are not yet explicit.
Define a role contract
Before search:
Solution:
Target function:
Target seniority:
Primary titles:
Accepted alternatives:
Excluded titles:
Required buying roles:
Per-account working cap:
Example:
Solution: Sales intelligence
Function: Sales / Revenue Operations
Seniority: C-Level, VP, Head, Director
Primary: CRO, VP Sales, Head of Sales
Alternatives: RevOps Director, Sales Operations Director
Exclude: Sales Assistant, Intern, unrelated regional roles
Working cap: 3 relevant contacts/account
The cap is a workflow guideline, not a Getlead limit.
For deeper role selection, use the decision-maker guide.
Search with supported Getlead criteria
Confirmed criteria:
- Job title;
- Industry;
- Country;
- Seniority;
- Function/department;
- Verified Emails Only;
- requested result count.
Example:
Industry: Software
Country: United States
Function: Sales
Seniority: C-Level, VP, Head, Director
Verified Emails Only: On
The company CSV is an operational comparison input. We do not claim that the current product natively bulk-uploads company CSVs unless engineering confirms that feature.
Match search results back to accounts
We compare:
- normalized Company/Website;
- current Job Title and function;
- LinkedIn URL for identity review;
- Industry;
- Employee Count for post-export qualification;
- Verification Status.
The confirmed native export columns are:
First Name
Last Name
Job Title
Email
Company
Website
LinkedIn URL
Industry
Employee Count
Verification Status
We keep source Account ID as a workflow join field, not a native export field.
Apply the verification policy
Verified Emails Only retains contacts that passed Getlead's real-time SMTP check at verification time and excludes catch-all and risky results. This reduces hard-bounce risk before outreach.
Future delivery is not guaranteed. We record status and, where available, timestamp/source.
Decisions:
| Result | Action | |---|---| | Verified under approved condition | Eligible after ICP/role/suppression | | Catch-all | Hold out | | Risky | Hold out | | Invalid | Exclude | | Unknown | Verify before standard campaign |
Verification does not override suppression, role fit or account identity.
Build the enrichment waterfall
1. Validate company row
2. Normalize website/domain
3. Separate duplicates and ambiguity
4. Confirm ICP
5. Define buying roles/title families
6. Search supported filters
7. Match Company + Website
8. Apply verification policy
9. Attach native export fields
10. Queue exceptions
11. Measure quality
Every stage changes a visible status.
Use an exception queue
| Code | Meaning | Next action |
|---|---|---|
| MISSING_WEBSITE | No website/domain | Research identity |
| AMBIGUOUS_COMPANY | Several plausible matches | Resolve with country/domain |
| DUPLICATE_ACCOUNT | Domain repeated | Merge with provenance |
| OUT_OF_ICP | Account fails rules | Preserve reason/exclude |
| NO_ROLE_MATCH | No planned title/function | Review title family |
| NO_VERIFIED_CONTACT | Relevant person but no approved verified email | Try another role/hold |
| IDENTITY_CONFLICT | Company/profile evidence disagrees | Manual review |
| ACTIVE_CAMPAIGN | Contact already active elsewhere | Cross-campaign suppression |
We do not silently delete exceptions. A zero-result account is useful operational evidence.
Add workflow fields
Account ID
Normalized Domain
Buying Role
Match Status
Exception Code
Evidence URL
Evidence Date
Verification Timestamp
Account Owner
Next Action
These follow the native export; they do not replace or masquerade as it.
Measure four quality metrics
Account match coverage
Accounts with confirmed company match /
Total processed accounts × 100
Verified contact coverage
Eligible accounts with at least one approved verified contact /
Total eligible accounts × 100
Buying-role coverage
Required roles with an eligible contact /
Required roles defined × 100
Exception rate
Accounts requiring manual review /
Total processed accounts × 100
These measure the operation. They do not predict reply, delivery or revenue.
A complete synthetic example
Input:
100 company rows
5 duplicate domains
8 missing websites
4 out-of-ICP accounts
83 unique candidate accounts
After identity review:
76 confirmed eligible accounts
7 ambiguous/unresolved
Contact search:
65 accounts with at least one relevant role
54 accounts with at least one approved verified contact
Metrics:
Account match coverage = 76 / 83 = 91.6%
Verified contact coverage = 54 / 76 = 71.1%
Buying-role coverage requires the sum of defined roles. If 76 accounts require 190 roles and 121 have eligible contacts:
121 / 190 = 63.7%
These numbers illustrate the formulas, not Getlead benchmarks.
Distinguish account, person and email status
One row can have:
Account Match = Confirmed
Role Match = Confirmed
Verification = Unknown
Campaign Eligibility = Hold
Another:
Account Match = Confirmed
Role Match = Out of scope
Verification = Verified
Campaign Eligibility = Exclude
A verified email does not rescue an irrelevant role. A relevant person without an approved verification status remains a research result, not standard-campaign eligible.
Resolve multiple matches
For common company names:
- compare Website;
- compare Country;
- compare LinkedIn company/current role;
- compare Industry;
- preserve alternatives;
- require human confirmation.
Do not choose the first search result.
For subsidiaries:
- record the operating company;
- record parent relationship separately;
- do not inherit parent ICP or suppression automatically without policy.
Control contact count
We select distinct buying roles before adding similar titles. A per-account cap prevents the output from becoming indiscriminate.
Possible policy:
- small founder-led account: 1–2 contacts;
- mid-sized account: 2–3 distinct roles;
- larger/complex account: 2–4 distinct roles.
This is an editable operating model, not a universal fact.
Transfer supported state to onboarding
/register?industry=software&role=sales&seniority=cxo,vp,head,director&country=united-states&verified=true&utm_source=seo&utm_medium=guide&utm_campaign=jtbd03_company_to_contacts
We do not label the CTA “Upload My List” while native bulk import is unconfirmed.
Event:
{
"event": "seo_get_started_click",
"content_id": "jtbd-03",
"content_cluster": "prospecting",
"cta_name": "enrich_my_company_list",
"cta_position": "inline",
"destination": "register",
"state_transfer": true,
"tool_completed": false
}
QA the output
Inspect:
- all duplicate/ambiguous accounts;
- all website mismatches;
- all accepted title variants;
- all accounts with no role match;
- all verification exceptions;
- all cross-campaign overlaps;
- a sample of confirmed matches;
- every source with a high exception rate.
Reviewer questions:
- Is the company identity confirmed?
- Does the role contract justify the person?
- Does the verification decision match policy?
- Can another operator reproduce the match?
- Is the account/contact already active?
- Is the next action explicit?
Process the list in controlled batches
For a large company file, we do not transform every account before testing the contract. We begin with a calibration batch that includes:
- short and long company names;
- records with and without Website;
- duplicate domains;
- more than one country or industry value if present;
- likely parent/subsidiary relationships;
- accounts near ICP boundaries.
We run identity, role and contact matching on that batch and review the exception mix. If NO_ROLE_MATCH is high, the title library may be too narrow or the buying-role hypothesis may be wrong. If AMBIGUOUS_COMPANY is high, Website coverage or source quality may be weak. If NO_VERIFIED_CONTACT is high, the account list can still be correct; the reachability layer needs a different next action.
Only after the rules work on the calibration set do we increase batch size. Each batch records:
Batch ID
Source version
Account count
Role contract version
Search version
Reviewer
Started/completed dates
Exception summary
Approved next batch size
This protects the entire list from a faulty mapping.
Create an account-state machine
Every source account moves through explicit states:
RAW
→ NORMALIZED
→ IDENTITY_CONFIRMED
→ ICP_ELIGIBLE
→ ROLE_SEARCHED
→ CONTACT_MATCHED
→ VERIFIED_CONTACT_AVAILABLE
→ CAMPAIGN_READY
Exception branches:
NEEDS_IDENTITY_REVIEW
OUT_OF_ICP
NO_ROLE_MATCH
NO_VERIFIED_CONTACT
DUPLICATE_ACCOUNT
ACTIVE_CAMPAIGN
A record can move back when evidence changes. For example, an ambiguous company becomes IDENTITY_CONFIRMED after Website review. A contact whose role changed returns to ROLE_SEARCHED. State history keeps the reason and reviewer.
This model avoids one overloaded Status column. Status could mean account identity, contact verification or campaign progress. Separate fields preserve the meaning.
Merge contact results without creating duplicates
When several search iterations return the same person, use:
- normalized Email when present;
- normalized LinkedIn URL;
- Account ID + First Name + Last Name + Job Title as a reviewed fallback.
We do not merge only on name. We also do not treat a different email as a different person without reviewing identity.
The survivor record should prefer:
- confirmed current Company/Website;
- current Job Title;
- approved verification status with timestamp;
- more complete provenance;
- most recent attributable evidence.
The losing record remains in an audit table with the survivor ID and reason. If two records disagree, we do not silently select the richer one; we resolve the conflict or place it in review.
Measure quality by source
Aggregate coverage can hide weak data sources. Report by source:
| Metric | What it diagnoses | |---|---| | Missing Website rate | Account identity readiness | | Duplicate-account rate | Overlap and source merging | | Confirmed ICP rate | Target-source quality | | Role-match coverage | Role contract + source relevance | | Verified-contact coverage | Reachability under policy | | Exception rate | Manual operational cost |
Suppose Source A has 80% verified-contact coverage with 5% exceptions, while Source B has 45% coverage with 35% exceptions. We do not conclude that Source A is universally better from one batch, but we investigate acquisition method, age, market coverage and fields.
We annotate source changes. If a new export filter improves coverage, the record shows what changed.
Separate enrichment from campaign eligibility
Enrichment adds information. Campaign eligibility is a decision:
Campaign Eligible =
Account identity confirmed
AND ICP eligible
AND role match confirmed
AND verification policy passed
AND suppression clear
AND no overlapping campaign
A richly enriched profile can still be ineligible. A minimally populated record can be eligible if it meets every required field for the specific segment and message.
This distinction prevents operations from rewarding column count instead of decision quality.
Design the downloadable QA workbook
The supporting asset has four tabs:
Input Companies
Raw and normalized identity fields, source and Account ID.
Matched Contacts
Ten native Getlead export fields plus Account ID, Buying Role, Match Status and evidence fields.
Exceptions
Original account row, exception code, explanation, owner and next action.
QA Summary
Batch counts, four core metrics, source breakdown and reviewer decision.
No real personal data is used in the public template. Formula cells are visible and editable. Controlled-value columns include a data dictionary.
Coordinate with CRM and campaign owners
If the result enters a CRM, define:
- unique account key;
- unique contact key;
- source-of-truth field for Company and Website;
- allowed verification values;
- buying-role values;
- who can overwrite data;
- campaign and suppression joins;
- refresh/expiry rules.
We do not claim automatic CRM write-back unless the current product implements it. The guide provides a data contract that engineering or operations can map safely.
Before handoff, account owner confirms contact selection. Campaign owner confirms segment and capacity. Suppression owner confirms cross-campaign state. This keeps a technically verified contact from entering an inappropriate sequence.
A weekly leadership view
Leadership needs:
- source accounts received;
- confirmed eligible accounts;
- unique accounts after deduplication;
- accounts with at least one relevant contact;
- accounts with at least one approved verified contact;
- buying-role coverage;
- exception count by reason;
- manual review time;
- campaign-ready accounts;
- top source-quality changes.
Raw contact count is secondary. Ten irrelevant contacts per account can inflate the number while reducing operational quality.
The most useful decision is where the constraint lives:
- Identity constraint: improve Website/domain input.
- ICP constraint: improve source targeting.
- Role constraint: revise title/buying-role contract.
- Reachability constraint: refresh contacts or change role.
- Operations constraint: increase review capacity or simplify rules.
Each constraint links to a specific hub page rather than another generic article.
Refresh and expiration policy
Accounts and roles change. We define review triggers:
- Company or Website conflict appears;
- contact changes employer/title;
- verification ages beyond policy;
- account enters an active campaign;
- ICP or offer changes;
- trigger evidence expires.
We preserve prior values with dates. “Latest” is only useful when the source and change are known.
Common mistakes
Treating Company as unique
Names collide. Website/domain is a stronger key.
Guessing domains
Generated domains remain hypotheses until confirmed.
Searching people before defining roles
We collect available titles rather than relevant contacts.
Claiming native bulk upload
We describe only current confirmed product behavior.
Mixing native and workflow fields
Later imports and teams cannot tell data source from decision metadata.
Deleting no-match accounts
We lose evidence about ICP, title and data gaps.
Treating verification as permanent
It is time-bound.
Company-to-contacts checklist
- [ ] Raw company CSV preserved.
- [ ] Source and Account ID retained.
- [ ] Website/domain normalized.
- [ ] Duplicates and conflicts separated.
- [ ] ICP applied before person search.
- [ ] Role contract complete.
- [ ] Supported Getlead filters only.
- [ ] Company/Website match confirmed.
- [ ] Native export columns preserved.
- [ ] Workflow fields separately labeled.
- [ ] Verification policy applied.
- [ ] Exceptions have codes and owners.
- [ ] Four quality metrics calculated.
- [ ] Contact count justified by distinct roles.
- [ ] CTA carries supported state without upload claim.
Continue through the hub
Use the decision-maker guide to refine buying roles. If the company list itself is weak, return to JTBD-01. Clean the contact output with JTBD-04, prioritize it with JTBD-08, then segment with JTBD-05.
Frequently asked questions
Is a company name enough?
It can start research, but Website/domain is strongly recommended for disambiguation.
Does this workflow upload a company CSV into Getlead?
The guide treats the CSV as an operational comparison input and does not claim unconfirmed native bulk-upload behavior.
How many contacts should we find per company?
Use the smallest set that covers required buying roles. The working cap depends on account complexity.
What if no verified contact exists?
Try another relevant role or hold the account. Do not relabel catch-all/risky/unknown results as verified.
Why preserve exception rows?
They show whether the gap is identity, ICP, role selection, verification or duplication and make the workflow auditable.
Are the quality metrics benchmarks?
No. They measure our own operation and should be tracked over time by source and segment.