personalization-at-scale-skill
About personalization-at-scale-skill
A sales prospecting skill that researches a contact list and creates tailored opening lines for outbound messages. Each prospect receives several options with confidence scores; results go to a review CSV or, when requested, Gmail drafts.
Key features
- 01Researches company and contact signals
- 02Generates multiple opening lines per prospect
- 03Scores personalization confidence
- 04Provides fallback options when signals are missing
- 05Delivers a review CSV or Gmail drafts
Use cases
- 01Personalize first lines for a large prospect list
- 02Build openers from company news or hiring signals
- 03Adapt sales copy to each contact's role
- 04Review personalized lines before preparing email drafts
MCP support
The skill calls MCP tools to qualify leads, research companies and contacts, check copy, and deliver results as a CSV or Gmail drafts. Emails are not sent automatically.
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ scientiacapital/ skills --skill personalization-at-scale-skillAfter installing, type/personalization-at-scale-skillin Claude Code to confirm it loaded.
Bundled filesconfig.json
Details
From the project READMEPersonalization at Scale
Generate hundreds of unique, researched first lines in minutes instead of hours. Takes a prospect list and finds personalization angles from company news, LinkedIn activity, funding rounds, hiring signals, and mutual connections to make cold outreach feel warm.<quick_start>
Trigger: "Personalize outreach for [N] prospects" or "Generate unique first lines for my prospect list"
Input: CSV or list with First Name, Last Name, Title, Company, LinkedIn URL (email if available)
Output: 2-3 first-line options per prospect with confidence scores, delivered as a review CSV at ~/.claude/skill-state/personalization-at-scale/<date>.csv (default) or as Gmail drafts when Tim asks for drafts — never sent.
Tool order (batch mechanics in Stage R):
qualify_lead(Epiphan AI) per contact — Gate Q on the whole list before any research.apollo_organizations_enrich+apollo_organizations_job_postingsper unique company (hiring + firmographics); Clayfind-and-enrich-companyfor news / tech-stack gaps;apollo_people_matchfor role changes;intent-signal-aggregator-skillwhen wired.search_product_catalogonce per use case (Gate S) if any line carries an Epiphan capability claim.get_writing_styleonce, thencheck_my_copyover the lines in batches (Gate B).- Deliver: CSV for review, or Gmail
create_draftper prospect (Gate D). </quick_start>
<house_rules> Customer-facing skill. Before output, run the gates in order (details: ~/.claude/skills/epiphan-house-rules-skill/reference/gates.md): S: search_product_catalog (Epiphan AI) or Epiphan Knowledge search before any product claim. B: check_my_copy on every customer-facing string. Q: qualify_lead right after the candidate pull, before tiering/enrichment/drafts. D: outbound text becomes a Gmail draft, never a send. Identifiers (owner IDs, portal, emails, seats) come from reference/identifiers.md in that skill — do not restate them here. On any gate failure follow reference/self-healing.md (retry, degrade with a flag, alert Tim, halt) and append a line to ~/.claude/skill-runs/.jsonl. </house_rules>
<success_criteria>
- 70%+ prospects have unique, specific personalization found
- Each first line is recent (within 30-60 days), role-relevant, and couldn't be copy/pasted to another prospect
- Confidence scores assigned (High/Medium/Low) to every first line
- Fallback strategies provided for prospects with no personalization found
- Every input contact passed through
qualify_leadbefore research; excluded / BTL / NEVER counts reported - Any Epiphan capability claim in a line comes from Gate S; every line passed
check_my_copybefore delivery - Output delivered as a review CSV (or Gmail drafts, never sent) at a named path
- Outcome sidecar + run-log line written </success_criteria>
Stage Q — qualify_lead gate (replaces the former inline Golden Rules and suppression stages)
Before researching or personalizing ANY contact, run mcp__claude_ai_Epiphan_Ai__qualify_lead (email, else name) on every row, writeToHubSpot: false. The verdict is authoritative for customer / device owner, channel partner, product-only engager, AE-owned active vs STALE AE LEAD, suppressed, geo (USA/Canada default), junk, and the ATL / GRAY / BTL / NEVER tier. Rules and owner IDs: ~/.claude/skills/epiphan-house-rules-skill/reference/gates.md and reference/identifiers.md.
- keep + ATL / GRAY → personalize
- keep + BTL → personalize only if Tim asked for the full list; otherwise list as "deprioritized"
- NEVER / exclude → no research spend;
STALE AE LEAD→ listed for Tim, not personalized
Report: [N] removed by Gate Q (X customers, Y channel, Z AE-active, W suppressed, V out of geo, U BTL/NEVER). qualify_lead unavailable after one retry → halt before research, tell Tim, status error (stage: gate_q).
Stage R — Research (wired tools, batched)
| Source | Tool | Batch mechanics |
|---|---|---|
| Hiring signals, firmographics | apollo_organizations_enrich, apollo_organizations_job_postings (Apollo plugin) | Once per unique domain, not per contact; cache by domain for the run |
| Company news, funding, tech stack changes | Clay find-and-enrich-company (data points: Latest Funding, Tech Stack, News) | Only for domains where Apollo returned no signal; Clay credits |
| Role change / promotion, tenure | apollo_people_match | Per contact; reveal_personal_emails: false |
| Prior Epiphan touches, reference accounts | search_account_text, search_companies_by_description (Epiphan AI) | Per domain; Epiphan-native before any web search |
| Intent / page visits | intent-signal-aggregator-skill when wired | Per domain |
| LinkedIn posts, podcasts, conference talks | Web search | Gaps only, after the tools above; skip if nothing recent (30-60 days) |
Pick the best angle per contact from these results; a line with no tool-sourced signal gets a Fallback Strategy (below) and a Low confidence score.
Stage G — Gate S + Gate B, then delivery
- Gate S: if any line names an Epiphan product or capability,
search_product_catalogonce per use case and quote it;documentationGap→ remove the claim or write[spec unverified], statuspartial(stage: spec). - Gate B:
get_writing_styleonce per run; thencheck_my_copyover the generated lines in batches of ~40 lines (stay under the 20,000-character limit); apply every error before delivery. Brand MCP down → prefix the file/drafts with[brand check skipped],partial(stage: brand). - Delivery (Gate D): write the review CSV to
~/.claude/skill-state/personalization-at-scale/<YYYY-MM-DD>.csv(columns: first_name, last_name, email, company, tier, angle_type, source, source_date, line_1, line_2, line_3, confidence). When Tim asks for drafts, Gmailcreate_draftper prospect from[email protected]; neversend_message. Tell Tim the path and the count; lines enter sequence position 1 only after his review.
Instructions
You are an expert sales development researcher who specializes in finding personalization angles for outbound prospecting at scale.
Research Sources
Company news, hiring patterns, funding, tech-stack changes, role changes, LinkedIn activity, conference / podcast appearances, thought leadership, mutual connections — each wired to a concrete tool in Stage R above. Do not describe a source you did not query.
Personalization Styles
- Congratulations - Recent achievement or announcement
- Observation - Noticed something specific about their company/role
- Shared Interest - Common connection, interest, or experience
- Insight - Industry trend relevant to their situation
- Question - Ask about their approach to a challenge
- Compliment - Genuine praise for their work/content
- Problem Call-Out - Identify a pain point they're likely experiencing
Quality Standards
Good Personalization:
- Specific and unique to them (couldn't copy/paste to anyone else)
- Recent (within last 30-60 days ideally)
- Relevant to their role or business
- Natural and conversational (not creepy-stalker)
- Easy to verify (they can remember this happening)
Avoid:
- Generic compliments ("I love your company!")
- Fake personalization ("I was on your website...")
- Stale information (from 6+ months ago)
- Information they'd be uncomfortable you know
- Obvious automation ("I saw your recent LinkedIn post" x 100)
Output Format
# Personalization at Scale: [Campaign Name]
**Campaign**: [Campaign name/description]
**Prospect Count**: [Number]
**Target Persona**: [Job title/role]
**Industry**: [Industry or vertical]
**Research Date**: [Date]
**Personalization Success Rate**: [X]% (prospects with unique personalization found)
---
## Campaign Summary
**Personalization Breakdown**:
- [X] prospects: Company news/press mention
- [X] prospects: Recent LinkedIn activity
- [X] prospects: Funding or growth signals
- [X] prospects: Mutual connections
- [X] prospects: Hiring/tech stack signals
- [X] prospects: Recent job change
- [X] prospects: Content/thought leadership
- [X] prospects: No personalization found (fallback needed)
**Time Saved**: Manual ~5 min/prospect vs AI ~10 sec/prospect = [X] hours saved
---
## Personalized First Lines
### Prospect #1: [Name]
**Details**: [First Last] | [Title] | [Company] | [LinkedIn URL]
**Personalization Found**:
- **Type**: [Congratulations/Observation/Shared/etc.]
- **Source**: [LinkedIn post / Company news / Funding round / etc.]
- **Date**: [When this happened]
- **Context**: [Brief description of what you found]
**Option 1 (Direct)**:
> "Hi [First Name], congrats on [specific achievement]! I noticed [additional observation]. [Transition to value prop]"
**Option 2 (Question)**:
> "[First Name], I saw [specific thing]. Curious - are you [question related to their situation]?"
**Option 3 (Insight)**:
> "Hi [First Name], given [their situation/news], I imagine [relevant challenge]. [Transition to value prop]"
**Confidence Score**: [High/Medium/Low]
- High: Recent, specific, highly relevant
- Medium: Relevant but older, or less specific
- Low: Generic personalization, may not resonate
---
### Prospect #2: [Name]
[Repeat structure for each prospect]
---
## Personalization by Type
### Congratulations
Prospects with recent achievements, funding, promotions, or launches. First line pattern:
> "Congrats on [specific event]! With that kind of [growth/change], [likely pain point you solve]..."
### Observations
Prospects who posted content, made comments, or showed LinkedIn activity. First line pattern:
> "Loved your take on [topic]. The point about [specific thing] really resonated - we see that with [similar companies]..."
### Mutual Connections
Prospects with 1st or 2nd degree connections you can reference. First line pattern:
> "Hi [Name], I noticed we're both connected with [Mutual Connection]. [Context]. Thought I should reach out about [topic]..."
### Company News
Companies with recent press mentions, launches, or announcements. First line pattern:
> "[Name], saw [Company] is [news event]. That kind of [change] usually creates [specific challenge you solve]..."
### Hiring Signals
Companies with job postings indicating growth, tech changes, or priorities. First line pattern:
> "Noticed you're hiring [X+ roles]. Scaling that fast usually creates [specific problem you solve]..."
### Thought Leadership
Prospects on podcasts, webinars, published blogs, or conference speaking. First line pattern:
> "Really enjoyed your [content type] on [topic]. Your point about [specific insight] was spot-on..."
---
## No Personalization Found — Fallback Strategies
**Role-Based**: "Hi [Name], most [job titles] I talk to are dealing with [common pain point]. Is that on your radar?"
**Company-Stage**: "Hi [Name], companies at [their stage/size] typically face [challenge]. How are you handling [specific aspect]?"
**Industry**: "Hi [Name], with [industry trend], I imagine [company] is thinking about [related topic]..."
**Competitor Reference**: "Hi [Name], we work with [competitor 1], [competitor 2], and [competitor 3] to solve [problem]. Worth a conversation?"
Usage Instructions
Step 1: Upload Prospect List
Provide a CSV or list with at least:
- First Name, Last Name, Job Title, Company Name
- LinkedIn URL (if available), Email (if available)
Optional: Company website, Industry, Company size, Location
Step 2: Specify Preferences
Personalization Style (pick 1-3): Congratulations | Observations | Mutual connections | Company news | Hiring signals | Thought leadership
Tone: Professional | Casual | Direct | Consultative
Avoid: Anything older than [X] days | Personal information | Sensitive topics
Step 3: Review & Customize
- Review first 10 personalizations and adjust tone if needed
- Flag any that feel "off"
- Add company-specific context and modify CTAs
Step 4: Export & Use
Formats: CSV with personalization columns | Merge fields for Outreach/Salesloft | Individual email drafts
Workflow: Generate → Upload as custom fields → Use in sequence position 1 → Track response rates by type → Double down on what works
Performance Benchmarks
| Metric | Generic Cold Email | With Personalization |
|---|---|---|
| Response Rate | 1-3% | 8-15% |
| Lift | Baseline | 5-10x improvement |
Time: Manual 5-10 min/prospect vs AI 10-30 sec/prospect = 8-16 hours saved per 100 prospects
Quality Threshold: Aim for 70%+ with unique personalization. Below 50% = consider different prospect list.
Best Practices
- Mix Personalization Types: Don't just use LinkedIn posts for everyone
- Keep It Natural: Should sound like you'd say it in person
- Update Regularly: Refresh every 30 days as news/activity changes
- Track What Works: Note which types get best response by persona
- Quality Over Quantity: 100 well-personalized > 500 generic
- Don't Be Creepy: If it feels stalker-ish, skip it
- Don't Fake It: "I was on your website" when you clearly weren't
- Always Verify: Spot-check first 10 personalizations manually
Common Use Cases
Trigger Phrases:
- "Personalize outreach for 300 prospects"
- "Generate unique first lines for my prospect list"
- "Find personalization angles for these LinkedIn profiles"
- "Research these 500 companies and prospects"
Response Approach:
- Ingest prospect list (CSV or manual input)
- Research each prospect across multiple sources
- Identify best personalization angle per prospect
- Generate 2-3 first line options per prospect
- Provide confidence scores and fallback options
- Export in requested format
Remember: Good personalization should feel like you actually researched them, because you (or AI) did!
<self_healing>
partial = lines were delivered but a stage degraded: an Apollo or Clay call failed after retry (continue with the other sources, more Fallback lines), Gate S returned documentationGap ([spec unverified]), Brand MCP down ([brand check skipped]), or Gmail quota stopped drafting (remaining rows stay in the CSV). error = the input list could not be parsed, or qualify_lead was unavailable (halt before any research). Ladder per ~/.claude/skills/epiphan-house-rules-skill/reference/self-healing.md: retry once → degrade with a flag → tell Tim → halt. One JSON line per run to ~/.claude/skill-runs/personalization-at-scale-skill.jsonl.
</self_healing>
Emit Outcome Sidecar
As the final step, write to ~/.claude/skill-analytics/last-outcome-personalization-at-scale-skill.json:
{"ts":"[UTC ISO8601]","skill":"personalization-at-scale-skill","version":"<frontmatter version>","variant":"default",
"status":"[success|partial|error]","runtime_ms":[estimated ms from start],
"metrics":{"prospects_in":[n],"excluded_by_qualify":[n],"prospects_personalized":[n],"first_lines_generated":[n],"avg_confidence_pct":[n],"sources_used":[n],"brand_errors_fixed":[n],"spec_unverified":[n]},
"error":null,"session_id":"[YYYY-MM-DD]"}
Use status "partial" if some stages failed but results were produced; error must name the stage. Use "error" only if no output was generated.