---
name: lead-gen-agent
description: Activates when the user asks to find local business leads, scrape Google Maps for businesses, generate personalized cold outreach emails, or run a B2B lead generation workflow. Uses Serper Maps API to find businesses, Firecrawl to enrich them with website context, and Claude to write personalized outreach. Outputs a CSV ready to import into a CRM or send via cold email tool.
---

# Lead Gen Agent Skill

The Claude Code version of Pillar 7's Google Maps lead gen workflow. Replaces the n8n visual workflow with a single skill file for users already deep in Claude Code.

## Activation Rules

Activate when:
- The user asks to "find leads," "scrape Google Maps," "generate cold outreach," or anything similar
- The user runs the `/lead-gen-agent` slash command
- A scheduled cron job triggers a recurring lead pipeline run

## Prerequisites

1. **Serper MCP** installed and configured with API key (serper.dev, ~$0.20 per 1,000 results)
2. **Firecrawl MCP** installed for website enrichment
3. **brand-kit.md** with the user's service offering described
4. **A defined niche/vertical** to target (HVAC, plumbing, dentists, etc. — see Pillar 7 vertical guide)

If MCPs aren't connected, prompt the user to install them before continuing.

---

## Slash Commands

### `/lead-gen-agent business_type=[X] location=[Y] radius=[N] count=[N] service_offered=[S]`

The primary command. Runs the full workflow end-to-end.

**Usage:**
```
/lead-gen-agent business_type="HVAC contractor" location="Fort Wayne, Indiana" radius=30 count=50 service_offered="Google Ads management and SEO for local service businesses"
```

**Workflow:**

1. **Search Google Maps via Serper:**
   - Query: `[business_type] in [location]`
   - Radius: `[radius]` miles from city center
   - Limit: `[count]` results
   - Save raw response to `./data/leads-raw-[date].json`

2. **For each result, extract:**
   - Business name
   - Address
   - Phone number
   - Website URL (if present)
   - Google rating (stars)
   - Review count
   - Category
   - Hours (if available)

3. **For each lead with a website, enrich via Firecrawl:**
   - Scrape the homepage and "About" page
   - Extract main content as markdown
   - Identify: services offered, geographic coverage, owner/contact info if listed
   - Note any obvious gaps: no SSL, outdated design, missing services pages
   - Cache scraped content to `./data/website-cache/[domain].md` to avoid re-scraping on future runs

4. **For each lead, generate personalized outreach:**
   - Use Claude (this is the model running this skill) to write a 3-4 sentence cold email
   - Reference something specific from the website or Google listing
   - Identify one specific problem they likely have
   - Offer a low-commitment next step tied to `[service_offered]`
   - Output as `subject` + `body`

5. **Compile to CSV** at `./output/leads-[date].csv` with columns:
   ```
   business_name, address, phone, website, email_if_found, rating, 
   review_count, category, website_summary, outreach_subject, 
   outreach_body, status (default: "Not Contacted"), first_contact_date, 
   response_date, meeting_date, close_date, monthly_revenue, added_date
   ```

6. **Show summary:**
   ```
   Lead pipeline complete.
   Leads found: [N]
   With website: [N] (enriched)
   Without website: [N] (phone-only outreach)
   AI outreach emails generated: [N]
   
   File saved: ./output/leads-[date].csv
   
   Cost breakdown:
     Serper API: ~$[N * 0.0002]
     Firecrawl scrapes: free (under monthly limit) or ~$[N * 0.001]
     Claude calls: ~$[N * 0.005]
     Total: ~$[total]
   
   Next steps:
   1. Open the CSV in Google Sheets
   2. Review the AI-generated outreach (the AI is wrong on ~10% of leads)
   3. Delete leads that aren't a fit (too small, wrong category, already sophisticated)
   4. Send emails one-by-one or via cold email tool with proper warm-up
   ```

### `/lead-gen-batch [config-file]`

Run multiple lead gen searches in sequence, defined by a config file.

**Usage:**
```
/lead-gen-batch ./configs/lead-gen-batch.json
```

**Config file format:**
```json
{
  "service_offered": "Google Ads management for local service businesses",
  "searches": [
    { "business_type": "HVAC contractor", "location": "Fort Wayne, IN", "radius": 30, "count": 50 },
    { "business_type": "plumber", "location": "Fort Wayne, IN", "radius": 30, "count": 50 },
    { "business_type": "roofing company", "location": "Fort Wayne, IN", "radius": 30, "count": 50 },
    { "business_type": "HVAC contractor", "location": "Indianapolis, IN", "radius": 25, "count": 50 }
  ]
}
```

Outputs one CSV per search at `./output/leads-[business_type]-[location]-[date].csv` plus a combined `./output/leads-batch-[date].csv`.

### `/refresh-pipeline`

Re-run the most recent lead gen search to find new businesses that have appeared on Google Maps since last run.

**Workflow:**
1. Read the most recent `./data/leads-raw-[date].json`
2. Re-run the same search parameters
3. Compare current results vs. previous: new businesses, closed businesses, rating changes
4. Generate outreach only for NEW leads (don't waste API calls on businesses you've already contacted)
5. Append new leads to the existing pipeline CSV

Run monthly per vertical/city to keep your pipeline fresh.

### `/score-leads [csv-path]`

Score and rank an existing leads CSV by likelihood to convert.

**Workflow:**
1. Read the CSV
2. For each lead, calculate a composite score based on:
   - **Rating signal:** 4.0-4.7 stars score highest (room to improve, but established)
   - **Review count signal:** 20-200 reviews score highest (real business, not too sophisticated)
   - **Website quality signal:** Older/simpler sites score higher (more room for help)
   - **Category match:** Closer match to your ideal vertical scores higher
3. Add a `lead_score` column (0-100)
4. Sort the CSV by score descending
5. Save as `./output/leads-scored-[date].csv`

Focus your outreach on the top 30-40% by score for best conversion rates.

### `/dry-run [business_type] [location]`

Preview what a search would return without consuming API credits.

**Workflow:**
1. Show estimated cost
2. Show example businesses that would likely match (cached from past similar searches if available)
3. Show what fields would be populated
4. Ask user to confirm before running the real search

---

## Outreach Generation Rules

When generating cold outreach emails, ALWAYS:

- Maximum 4 sentences
- Reference something SPECIFIC from the website scrape or Google listing (their service area, a specific service they offer, their rating, a specific page)
- Identify ONE specific problem they likely have
- Offer a low-commitment next step (audit, free tool, single 15-min call)
- Sound like a human, not a template

NEVER use:
- "I hope this email finds you well"
- "amazing," "incredible," "game-changing"  
- "in today's fast-paced world"
- "let me know if you'd like to learn more" (vague, lazy)
- Mass-blast tone (must feel one-to-one)
- Long paragraphs (aim for 1-2 sentences each)

ALWAYS include in the body:
- The business owner's first name if available, otherwise the business name
- One specific reference to their business (proves you actually looked)
- A clear, specific CTA (not "let me know")
- A short, friendly sign-off

**Subject line rules:**
- 5-8 words maximum
- Include their business name OR a specific reference to their work
- Avoid spam triggers ("Free," all caps, exclamation points)
- Should feel like a human-written subject, not a marketing tool's template

---

## Vertical-Specific Personalization

The skill should adapt outreach tone and angle based on the vertical:

### HVAC Contractors
- Emphasize seasonal urgency (summer/winter spike)
- Reference their service area and common HVAC issues
- Lead with: "I noticed you don't show up when I search 'AC repair [city]'"

### Plumbers
- Emphasize emergency intent searches ("burst pipe near me")
- Lead with: "Most plumbing leads come from searches at 11pm — is your Google Business profile optimized for after-hours?"

### Roofing Companies
- Emphasize insurance-driven demand and storm season
- Lead with: "I noticed your site doesn't have a [specific service] page — here's why that matters for storm season"

### Dentists
- Emphasize patient lifetime value
- Lead with: "I put together a quick audit of your local Google presence vs. [competitor practice in same area]"

### Med Spas
- Emphasize visual-first marketing
- Lead with: "Your before/after gallery is great. Here's how to make it work harder in Google AI Overviews."

The skill should detect the vertical from the `business_type` parameter and apply the appropriate angle automatically.

---

## Cross-Skill Integration

**Calls into this skill:**
- The user (directly via slash commands)
- A scheduled cron job (for monthly pipeline refresh)

**This skill calls:**
- Serper MCP (for Google Maps search)
- Firecrawl MCP (for website enrichment)
- brand-kit.md (for service offering and tone)

**Output flows to:**
- The user's CRM or cold email tool (Instantly, Smartlead, lemlist, etc.)
- The user's outreach workflow (manual sending recommended)
- A future Pillar (in development): an automated outreach scheduler skill that handles the 4-touch cadence

---

## Common Issues

### "No websites are scraping successfully"

Most common cause: the businesses in your search are too small to have websites. Try:
- Adjusting `business_type` to a larger category (e.g., "HVAC" instead of "AC repair")
- Searching in a larger metro area
- Lowering the `count` to focus on the top results (which tend to have better web presence)

### "AI outreach mentions things that aren't in the website"

The Firecrawl scrape may have failed silently. Check `./data/website-cache/[domain].md` — if it's empty or shows an error, the scrape didn't work. Re-run with longer timeout in the Firecrawl call.

### "Outreach feels too templated across leads"

Add more specific persona context to brand-kit.md. The more specific your service offering description, the more specific the AI personalization. Also consider switching the AI model to a higher-quality option (Claude Sonnet 4.5 outperforms GPT-4o-mini for outreach personalization).

### "I'm getting flagged as spam"

This skill does NOT send emails. It generates them. Sending should always be done through:
- Manual sending from your real Gmail (best deliverability for first 50/day)
- A warmed-up cold email tool with proper SPF/DKIM/DMARC
- Never bulk-blast from a fresh domain — you'll torch your sender reputation

---

## Notes

- The 50-leads-for-under-$1 cost claim assumes the Firecrawl free tier (500 scrapes/month) covers your usage. If you exceed it, Firecrawl is ~$0.001/scrape, which adds ~$0.05 per 50-lead batch.
- Google fights scrapers actively. Serper is the most stable data source as of mid-2026 because it operates as a Google search proxy with proper rate limiting. Direct scraping (without Serper) breaks every few months.
- For agencies, run separate searches per client niche. Don't combine HVAC and dental leads in the same CSV — the outreach angles are completely different.
- The lead pipeline is the start of the work, not the end. Conversion rates depend more on outreach quality and follow-up cadence than on lead volume. 50 well-personalized emails outperform 500 templated ones.
