Repository navigation
Lead enrichment: names from addresses, LinkedIn profile and title by search, PDL behind a key - #125
Merged
Merged
Conversation
…reening
Append: POST /api/v1/autogtm/campaigns/{id}/leads takes up to 5,000 leads
(JSON or the CSV itself), skips people already in the campaign or its
project and anyone on a suppress list, and shares one code path with the
new-campaign import. UI on the product page, `og leads add`, MCP
add_leads_to_campaign.
Report: every row that did not simply become a lead is stored with what
happened (rejected, skipped, flagged) and the column or check behind it;
returned inline, readable at .../import/{task}/report, downloadable as CSV.
Screening: generated names (Borer853), relay mailboxes (passmail, aleeas,
simplelogin...), temp-mail domains (known, or one domain shared by 3+
unrelated leads), bot/agent/test accounts and role inboxes are flagged at
import and held back from cold outreach through the policy engine
(personScreenedOut), on every send path, until a human allows them.
Webmail is never taken as a company domain. Migration 0051.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…search, PDL behind a key
Fills only blanks, for leads in live campaigns: first/last from unambiguous
first.last@ addresses (free); People Data Labs by email when PDL_API_KEY is
set (licensed for storage, 3/day by default); then a Google search of
LinkedIn through the existing ValueSERP key, taking a profile only when the
result title carries every name part and the company (or, with no company,
one profile whose slug is the name), the title off "Name - Title - Company",
and the company's LinkedIn page as fallback. Ported from cli-tools
linkedin-lookup with its tests.
Every search is cached in serp_cache (reruns are free), capped per run and
per workspace per day (enrichment_usage), run at concurrency 10 with a 45 s
timeout, and a 402 pauses the provider until the next UTC day. A worker sweep
runs beside the tick; POST /autogtm/campaigns/{id}/enrich starts one on
demand and GET .../enrichment reports what is missing. UI on the product
page, `og leads enrich|enrichment`, MCP enrich_campaign_leads and
get_lead_enrichment. Migration 0052. PDL_API_KEY added to the deploy's
secret sync (unset until a key is assigned).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # apps/api/src/app.ts # apps/api/src/append-leads.test.ts # apps/api/src/autogtm-docs.ts # apps/api/src/autogtm.ts # apps/cli/src/commands.ts # apps/mcp/src/mcp.test.ts # apps/mcp/src/tools.ts # apps/web/app/(app)/products/[id]/page.tsx # packages/pipeline/src/index.ts
… mailbox Seen live on the first prod append: info@ came back as 'nobody reads that mailbox', the cleaner's text for noreply@. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Free enrichment for leads that arrived as a bare address, ported from cli-tools
linkedin-lookup/user-clean(logic and tests).What fills what (blanks only, live-campaign leads)
scott.perry@,gabriella_fiore@,ann-lee@(two alphabetic parts of 2+ letters, no role or bot words).jsmith@,john.s@,john.smith42@are left alone.PDL_API_KEY(PDL's license allows storing results; Apollo's does not and is never used). 3/day per workspace by default (PDL_LOOKUPS_PER_DAY).VALUESERP_API_KEY:site:linkedin.com/in "First Last" <company>. A profile is taken only when the result title carries every name part and the company is in the title or snippet; with no company, only a single profile whose slug is the name. The job title comes offName - Title - Company | LinkedIn. The company'slinkedin.com/company/...page is the fallback (companies.linkedin_url).Profiles are recorded as research (confidence 0.6 search / 0.8 PDL, below the outreach floor), with
field_provenancerows. Nothing fetches LinkedIn itself.Cost controls
serp_cachekeyed by query: reruns and rule changes cost nothing.max_searches, 40 for the background sweep, 100 on demand) and per workspace per day (LINKEDIN_SEARCHES_PER_DAY, default 300), counted inenrichment_usageso a restart cannot reset them.LEAD_ENRICH_CONCURRENCY), 45 s per-request timeout. A 402 throwsSearchOutOfCreditsand pauses that provider until the next UTC day; a person whose question went unanswered is not stamped and is retried.Surfaces
POST /autogtm/campaigns/{id}/enrich(202, background),GET /autogtm/campaigns/{id}/enrichment(missing name/title/LinkedIn, providers, searches today vs cap, last run). In llms.txt/openapi.og leads enrich <campaignId> [--max N],og leads enrichment <campaignId>.enrich_campaign_leads,get_lead_enrichment.Migration 0052: two nullable
ADD COLUMNs and two new empty tables; no index on an existing table.PDL_API_KEYjoins the deploy's secret sync; it is not set yet, so PDL stays off until a key is assigned.Tests
packages/providers/src/valueserp/linkedin.test.ts(matching rules, title parsing, 402 for ValueSERP and PDL),packages/pipeline/src/lead-enrichment.test.ts(names/title/profile/company page, cache makes the rerun free, cap and 402 stop cleanly, PDL first within its cap), API background run test, CLI/MCP tests.🤖 Generated with Claude Code