A finder returns 80 email rows from a file containing 100 input rows. Is that an 80% success rate? You cannot tell yet. Some input rows may describe the same person, one identity may have several candidates, and a returned address may still have an unresolved employer match or verification result.

Before comparing methods, build a small reconciliation ledger. Count identities and stage outcomes separately, then define which results qualify for your intended handoff. This is a proposed application-side design with fictional counts, not a provider benchmark or a new contact-research run.

Start with an identity ledger

Assign an input record ID before calling another service. Preserve it through every handoff so you can explain where each submitted row ended up. Do not rely on a person's name as the only join key: names can collide, and one person can appear under different spellings.

Review duplicates separately from uncertain identity matches. Two rows that appear to be duplicates may need human review rather than automatic merging. Keep the original input rows and the decision that links them to a canonical research identity.

A starting ledger might contain 100 input rows, including 10 duplicate rows linked to existing identities. That leaves 90 distinct identities under the chosen deduplication rule. Record the rule, because another team may define an observation or a contact differently.

Make every stage account for its inputs

Suppose 10 of those 90 identities have unresolved employer context. Retain them for review and send only the remaining 80 into the next stage. A skipped identity is not a provider's failed lookup; it never reached that provider.

For the submitted set, record an outcome even when no address returns. Otherwise the result file becomes a list of successes with no way to calculate its denominator. Keep transport failures separate from completed lookups with no match as well.

An illustrative aggregate ledger is:

{ "batch_id": "fictional-pilot-01", "input_rows": 100, "duplicate_rows": 10, "distinct_identities": 90, "identity_review_pending": 10, "submitted_identities": 80, "no_match": 15, "verification_unresolved": 20, "accepted_under_batch_rules": 45 } 

The counts reconcile: 100 input rows split into 10 duplicate rows and 90 distinct identities; 90 splits into 10 pending and 80 submitted; the 80 submitted identities split into 15, 20 and 45 outcomes. This example assumes one mutually exclusive final outcome per submitted identity. Candidate-level records need a separate table.

Preserve candidates instead of inflating identity counts

A person may have two returned addresses. Preserve both candidates with their source and status, but count that person once when reporting identity coverage. If you choose one candidate for delivery, record the selection decision and retain the rejected alternative for audit where appropriate.

Keep observed addresses distinguishable from enrichment results. A business address read from an approved page and an address returned by a finder have different provenance. Neither should inherit the other's verification state merely because they share an identity key.

The minimum handoff can use three related records:

Record Purpose Example fields
Input identity Explain the original request input_id, canonical_identity_id, review_status
Candidate Preserve each returned value candidate_id, identity_id, source, provider_status, checked_at
Decision Explain inclusion in the delivery identity_id, selected_candidate_id, acceptance_rule_version

If the provider cannot expose a source or a check date, store that limitation. An empty metadata field should not become a confident label supplied by your adapter.

Define acceptance before looking at the totals

Map provider statuses into your review process deliberately. Preserve the original label as well as your local decision. An unknown result should remain distinguishable from a clear accepted result, and identity review should remain separate from mailbox checking.

In the fictional ledger, 45 identities meet the batch's declared rules. That means 45 of 80 submitted identities, or 45 of 90 distinct input identities, depending on the question. Report the denominator beside the rate. Neither ratio establishes delivery success or authorizes contacting anyone.

Do not hide the 10 pending identities and 20 unresolved checks in a single “missing email” bucket. The next actions differ: review employer evidence, resolve a verification status, or accept that a completed lookup found no match.

Compare costs using the same acceptance rule

For a pilot, record lookup charges, verification charges and manual review time separately. Divide comparable spend by accepted distinct identities only after stating what is included. Keep setup work visible so a workflow does not appear cheaper because its preparation happened outside the ledger.

Use the same input scope, review rules and observation window when comparing methods. More candidate rows can mean more alternatives to review rather than more usable people. A small pilot supports a decision about that pilot; broader coverage and reliability require further evidence.

BrowserAct's email-method comparison supplies the research-versus-enrichment context. The ledger adds an operational check: every input gets an explainable outcome, every candidate keeps its provenance, and every reported rate names its denominator.