keinsaasforever/gtm-pipeline-skills/gtm-contact-filter

Claude Code and agent skill by keinsaasforever/gtm-pipeline-skills

Trust tier 2
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Classify and filter contacts from people-search output BEFORE enrichment. Rejects non-ICP contacts and ranks the rest using job tier, industry tier, location tier, company size, and ICP keyword scoring. Saves enrichment credits by only passing qualified contacts downstream. Input: contacts_found.csv. Output: contacts_filtered.csv. Also triggers on "filter contacts", "ICP filter", "rank contacts".

Install

npx vskill@latest install keinsaasforever/gtm-pipeline-skills/gtm-contact-filter

SKILL.md

Contact Filter

Classify and rank contacts from people-search output using a three-tier ICP scoring system. Rejects non-ICP contacts before enrichment to save credits.

Read `~/.claude/skills/gtm-pipeline/_shared/conventions.md` before executing.

Filtering and ranking is agent work run on the `sonnet` model (see conventions "Model Routing" — contact filtering / ICP ranking). Classify in-context or via a Sonnet subagent; never shell out to a third-party LLM API.


When to Use

  • After people-search, before people-enrichment
  • Input: csv/intermediate/contacts_found.csv
  • Output: csv/intermediate/contacts_filtered.csv
  • Even small batches (10 contacts) benefit from ICP ranking

Prerequisites — Company Data

Contact-filter classifies on company-level fields (company_employee_count, company_hq_location, company_industry, company_specialities) alongside each contact. These come from upstream skills.

SourceFields ProvidedCost
PB LinkedIn Profile Scraper (enrichWithCompanyData: true)employee_count, hq, industry, specialitiesFree (PB plan + LinkedIn account)
PB Sales Navigator Account Scraperemployee_count, hq, industry, growth metricsFree (PB plan + SN account)
PB LinkedIn Company ScraperFull company page dataFree (PB plan + LinkedIn account)
FullEnrich Company Finderemployee_count, hq, industry0.25 credits/company
Pipe0 companies:profiles:amplemarket@2employee_count, hq, industry2.00 credits/page (100 results)
Pipe0 companies:profiles:crustdata@3employee_count, hq, industry0.15 credits per result (not per page)

Where company data typically comes from:

  • Company-First workflow: Already enriched in the company-enrichment step.
  • Persona workflow: Run PB Profile Scraper with enrichWithCompanyData: true during/after people-search.
  • Standalone: Run one of the API providers above before contact-filter.

If company data is missing: The filter falls back to job-title-only classification. It skips company-dependent dimensions (industry tier, location tier from HQ, size filter) and relies on job_tier and person location only.

See _shared/conventions.md for the canonical field name mapping (snake_case across all skills).


Step 1 — Load ICP Configuration

Read {client-slug}-gtm/context/icp.md for client-specific tier definitions, thresholds, and sort order.

If `icp.md` does not yet contain contact-filter configuration, ask the user:

  1. What are your target job titles / role keywords?
  2. What seniority levels are you targeting? (manager, director, VP, C-level?)
  3. What industries are highest priority? Lowest priority?
  4. What geographies are highest priority?
  5. What company size range? (min and max employee count)
  6. Any ICP keyword signals to look for in company specialities?
  7. Which dimensions matter most for ranking? (e.g. location first, then role, then industry)

Save the answers to context/icp.md under a ## Contact Filter section.


Classification System

A. Job Tier (1–6, lower = better)

Fully parameterized — client defines role keywords. Example structure:

TierDescriptionExample
1Primary target roles, mid-level seniorityRevOps Manager, Sales Ops Lead
2Primary target roles, other seniorityRevOps IC, Head of RevOps
3Leadership in target domainVP Sales, Director of Revenue
4General domain rolesAccount Executive, Sales Manager
5C-level (promote to tier 3 if company < threshold employees)CRO, CSO
6Reject (non-target roles, junior, students)Intern, Coordinator, Marketing Analyst

C-level promotion rule: If company_employee_count < {client_clevel_threshold} (e.g. 50), promote C-level from tier 5 → tier 3 (they're operational at small companies).

Assistant/support demotion (keyword-guard): Demote to the reject tier when the title contains an assistant/support token — even if it also contains a decision-maker keyword. "Persönlicher Assistent des CEO" contains "CEO" but is not a decision-maker. Check the demotion token list before crediting any decision-maker keyword. Multilingual demotion tokens: assistant, assistent, secretary, sekretär, sekretariat, referent, PA, EA, office manager.

Don't trust provider seniority tags alone: A provider may tag an IT/SAP VP as top seniority over the real ICP persona (e.g. an HR lead). Rank by local ICP-keyword / title-tier scoring, not the provider's seniority field. When multiple candidates exist per company, dump all of them to the review CSV rather than auto-picking one on the provider's tag.

Hard reject: job_tier >= hard_reject_threshold (default: 6).

Missing title: tier 6 (Unknown). Default threshold rejects tier 6. To allow missing-title contacts through, set hard_reject_threshold: 7 in your ICP config.

B. Industry Tier (0–5, lower = better)

Client defines 5 industry tiers ranked by fit for their offering.

  • Match logic: exact match first (full industry name), then keyword fallback
  • Tier 0 = Unknown (company_industry missing) — sorted between tier 1 and tier 2
  • Missing industry → tier 0, NOT rejected
C. Location Tier (A–D, A = best)

Client defines geographic priority tiers.

  • Primary: company HQ location (company_hq_location field — format: "City, CC", extract country code CC)
  • Fallback: person location field
  • Both missing: tier D (lowest)
  • Hard reject option: client can specify only tier A (or A+B) passes
D. Company Size Filter

Client defines min and max company_employee_count.

  • Outside range AND field is present → hard reject
  • Field missing/empty → skip size filter, set employee_count_missing: true, deprioritize in sort
E. ICP Keyword Scoring

Scan company_specialities for client-defined domain keywords. Count matches → icp_kw_score (0 = no match, no penalty). Missing specialities → icp_kw_score = 0.

F. Buying-Authority Locality (ICP refinement)

Deprioritize entities where the decision-maker for the offering likely doesn't sit locally. Express as scoring signals, not hardcoded names:

  • Captive / in-house unit of a larger parent — buying authority sits at the parent, not the unit.
  • Foreign-HQ subsidiary — decisions (and budget) originate at the foreign HQ; the local entity is an executor.
  • Minor side-function — the target activity is a small side-function of the business, not a core line, so no dedicated local owner.

Emit a buying_authority_local signal (or a small penalty added to the sort key) when one of these holds; use it to deprioritize, not to hard-reject.


Hard Filters (Rejection Rules)

Prefer not to reject solely on missing data — use the hard_reject_threshold to control strictness per client. The exception is missing job title (tier 6), which is rejected at the default threshold; raise the threshold to 7 to keep them.

FilterConditionAction
Job tier>= hard_reject_threshold (default: 6)Reject
Employee countoutside [min, max] AND field presentReject
Location tierworse than threshold AND field presentReject (optional)

Soft Sort (Ranking)

Sort order is configurable per client — stored in context/icp.md.

Default composite sort key (used if no preference stated):

job_tier → industry_tier → company_loc_tier → person_loc_tier → employee_count_missing (penalty last) → icp_kw_score (desc) → follower_count (desc)

Other valid orderings:

  • Geography-first: company_loc_tier → job_tier → industry_tier → ...
  • Company-fit-first: industry_tier → icp_kw_score → company_loc_tier → job_tier → ...

Ask the user at setup which ordering fits their priorities. Store it in context/icp.md.


Output Columns Added

The following columns are appended to all passed records:

ColumnDescription
job_tier1–6 (1 = best fit)
personaLabel for the role category
seniorityDetected seniority level
ind_tier0–5 (0 = unknown, 1 = best fit)
ind_labelMatched industry label
comp_loc_tierA–D based on company HQ
person_loc_tierA–D based on person location
effective_loc_tierBest of comp_loc_tier / person_loc_tier
employee_count_missingtrue/false
icp_kw_scoreCount of ICP keyword matches in specialities
priority_labelHuman-readable priority (e.g. "High", "Medium", "Low")
sort_keyComposite sort value used for ranking

Demo / Small-Batch Mode

For demo runs and any small batch, use this lightweight path instead of hand-rolling a one-off `finalize.py`. This mode owns dedup, best-N-per-company selection, and local title ranking so downstream skills receive a clean, standardized list.

Steps (in order):

  1. Dedup by LinkedIn URL — across the whole set, not per-company. The same person can appear under two companies (same linkedin_profile_url); collapse those to one row. Normalize the URL (lowercase, strip trailing slash and query params) before comparing. Keep the row with the better company match / lower job_tier.
  2. Local title ranking — score by ICP-keyword and job_tier locally (apply the assistant/support demotion and the "don't trust provider seniority" rules above). Do not defer to the provider's seniority tag.
  3. Best-N per company — after ranking, keep the top N per company (default 2–3). Configurable via best_n_per_company in context/icp.md.

Standardized output schema (write to csv/intermediate/contacts_filtered.csv; a demo/review CSV may use the same columns):

full_name, job_title, company_name, linkedin_profile_url,
job_tier, persona, icp_kw_score, priority_label, buying_authority_local

All original input columns are preserved alongside these; the columns above are the canonical, always-present set for a demo/small-batch pass.


Missing Data Handling

FieldMissing Behavior
job_titletier 6 (Unknown) — rejected at default threshold (6); raise to 7 to keep
company_industrytier 0 (Unknown) — sorted between tier 1 and tier 2
company_hq_locationFall back to person location; if both missing → tier D
company_employee_countSkip size filter, flag employee_count_missing: true, deprioritize in sort
company_specialitiesicp_kw_score = 0 (no penalty)
Follower count0 (lowest tiebreaker priority)

Default policy: Don't hard-reject on missing data unless the corresponding tier is explicitly above threshold. Adjust hard_reject_threshold per client.


Execution Protocol

1. Read ICP Configuration

Load from context/icp.md. If contact-filter section is missing, ask the setup questions above and save the answers.

2. Classify All Contacts

Run the classification logic over all rows in contacts_found.csv. Add the output columns listed above.

3. Apply Hard Filters

Reject rows that fail hard filter conditions. Log rejection reasons.

4. Sort Passed Records

Apply the client's configured sort order (or default) to rank passed contacts.

5. Print Run Summary
## Contact Filter Summary
- Input: {n_input} contacts
- Hard rejected (job tier): {n_job_rejected}
- Hard rejected (employee count): {n_size_rejected}
- Hard rejected (location): {n_loc_rejected}
- Passed: {n_passed} contacts
## Tier Distribution (passed contacts)
Job tiers: tier1={x}, tier2={y}, tier3={z}, tier4={w}
Industry tiers: tier1={x}, tier2={y}, tier3={z}, ...
Location tiers: A={x}, B={y}, C={z}, D={w}
## Top 10 by Priority
[name | company | job_title | job_tier | ind_tier | loc_tier | icp_kw_score]

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
61
Repository forks
6
7-day trend score
21

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 21 Oct 2026, 17 days ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/keinsaasforever/gtm-pipeline-skills/gtm-contact-filter/badge)](https://verified-skill.com/skills/keinsaasforever/gtm-pipeline-skills/gtm-contact-filter)

Something wrong with this skill or its page? Tell us.