Skip to content

Contact lists: keep name, company, title and country for LinkedIn's people match - #49

Merged
stan-rym merged 1 commit into
mainfrom
contact-list-matchers
Oct 21, 2026
Merged

stan-rym merged 1 commit into
mainfrom
contact-list-matchers

Conversation

@stan-rym

@stan-rym stan-rym commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

What

Contact list uploads kept only the hashed email and dropped every other column. LinkedIn's list upload also accepts firstname, lastname, employeecompany, title and country as plain text next to the hashed email. These lift the match rate on work emails, and a row with a first and last name can match with no email at all ("People match" in the spec).

Changes

  • Cleaner (audienceCsv.ts)
    • Contact lists now keep those 5 columns, mapped from common aliases (First Name, Company, Job Title and so on).
    • Values are trimmed to LinkedIn's length caps: 35 characters for names, 50 for company and title.
    • Country keeps only two-letter ISO codes. Anything else is left blank, with a warning.
    • A row needs an email or a first and last name.
    • A list with first and last name columns but no email column is detected as a contact list.
    • name is not treated as the company on a contact list, since there it is usually the person's name.
    • Any name, company or title value shaped like an email address is blanked, with a warning. LinkedIn rejects the whole file otherwise ("Found raw email address on line N. This API doesn't accept email addresses in clear text."). A real list hit this when one lead's first name was their Gmail address.
  • Upload (audience.ts, new contactListCsv)
    • The email is SHA256-hashed as before, and the other columns go as text.
    • A row with an invalid email but both names stays in as a name match.
    • Rows are deduped on the email hash, or on name plus company.
    • New warnings report rows skipped and rows matching on name only.
  • Unchanged: email-only lists (CSV, Salesforce, HubSpot) produce the same email\n<hash> CSV as before.
  • Docs: the MCP tool description, docs/tools.md, docs/index.md, the README and the regenerated docs/tools.json.

LinkedIn API behavior relied on

DMP Segment List Uploads, Contact Lists (li-lms-2026-10):

  • Supported headers: email (SHA256), googleaid, googleuid, firstname, lastname, employeecompany, title and country (the rest as plain text).
  • The header row needs at least an email, a Google id, or first and last name.
  • Length caps are 35 characters for names and 50 for company and title. Country is an ISO two-letter code.

Tests

  • packages/core/test/contactList.test.mjs has 7 new tests:
    • column mapping, length caps and country checks
    • blanking email addresses in text columns
    • name-only detection
    • hashing, plain text columns and dedupe in the upload CSV
    • a full upload through a fake LinkedIn client
    • a check that email-only uploads are unchanged
  • pnpm -r typecheck is clean, and pnpm --filter @adwarp/core test passes all 35 tests.
  • Tried on real data: a 25,341-row contact list (email, first and last name, company and title) uploaded as a USER_LIST_UPLOAD segment, after the email-in-text fix above.

🤖 Generated with Claude Code

…eople match

Contact uploads used to keep only the hashed email and drop every other
column. LinkedIn's list upload also takes firstname, lastname,
employeecompany, title and country as plain text, which lifts the match
rate on work emails, and a row with a first and last name can match with
no email at all.

- The cleaner maps those columns (with common aliases) on contact lists,
  trims them to LinkedIn's length caps, and keeps only two-letter country
  codes. A list with first and last name columns but no email is a
  contact list.
- The upload hashes the email, sends the other columns as text, keeps a
  row with an invalid email as a name match when it has both names, and
  dedupes on the email hash or name + company.
- Email-only lists (CSV, Salesforce, HubSpot) upload exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
adwarp-mcp Ready Ready Preview Oct 21, 2026 8:35pm UTC

Request Review

@stan-rym
stan-rym merged commit 156c322 into main Oct 21, 2026
4 checks passed

This branch was successfully deployed

1 active deployment
Preview — a55c54e0 Deployed Oct 21, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant