UGC Lead Gen: A Cost-Aware Outbound Pipeline With AI Brand Research and Pre-Pitch Generation
Weekly UGC outbound autopilot for a solo creator — multi-source collectors, cost-aware enrichment waterfall, AI pre-pitches, $5/month.

Outbound is a part-time job nobody wants
UGC creators — people who make sponsored short-form content for direct-to-consumer brands — have an unromantic part of their job: outbound. Every week, a fresh list of brands actively seeking creators, the right person to pitch at each one, a verified email, and a personalized opener. Without that loop, the content side of the business starves.
Josephine Remo is a UGC creator who needed that loop to run by itself. So I built her a weekly autopilot. Monday and Thursday it scans Google via Perplexity. Tuesday and Friday it scrapes Instagram and TikTok via Apify. Wednesday it ingests UGC industry RSS feeds. Friday at 9 AM it enriches everything it collected that week with contact info and ships a Google Sheet of pitch-ready leads — each one with a custom opening email already drafted.
It costs about $5 a month to run.
Three constraints that shaped the architecture
1. Source diversity. UGC opportunities surface across Google search, RSS, Instagram, TikTok, brand newsletters, industry blogs. Each channel has its own data shape, its own rate limits, its own signal-to-noise ratio. A monolithic collector would have been impossible to debug and slow to extend.
2. Enrichment is a money pit if you're not careful. Apollo.io's people-match endpoint costs one credit per call; free tier is 100 credits/month. Hunter.io free tier is 25 searches. Apify free tier is $5/month of platform credits. Perplexity is pay-per-use. Using the wrong tool first costs real money.
3. The pitch has to be personal, or it's noise. "Hi [Brand], I love your products" gets ignored. A pitch that opens with a reference to a recent launch — or to an article that just covered them — gets opened. That requires deep context: who the brand is, what they recently did, who the right contact is.
The system has to handle all three on a schedule, with error notifications when something breaks, and inside a creator's budget. Operator one, user one.

Five independent n8n workflows share state via a single Google Sheet (JR UGC Leads, two tabs: Staging and Master Leads). Three collectors — Google Search, RSS, Apify Social — write to Staging. The Enricher reads from Staging, runs each row through a six-stage waterfall, writes the finished lead to Master Leads, and marks the staging row processed. A separate Error Handler workflow is hooked into every other workflow's error trigger and posts to Josephine's Telegram with the offending node and execution ID.
This split lets me touch any one collector without risk of breaking the others. When TikTok changes its DOM, I patch one workflow and nothing else moves. When OpenAI deprecates a model, I update the Enricher and the collectors keep collecting. The Google Sheet is the only contract between them — column-named tables, simple enough to evolve.
Josephine never opens n8n. She opens a sheet. The Master Leads tab is the product; the workflows are the plumbing.

The single most important architectural decision in this project is the order in which enrichment methods are tried. Six stages, cheapest first:
- Apify website scrape — free (shared platform credits).
- Perplexity AI search — ~$0.005/query.
- Hunter.io domain lookup — free, 25 searches/month.
- Apollo.io people search — free, 0 credits.
- Apollo.io people match — 1 credit, last resort.
- Finalize with whatever was found.
Each stage gates on an IF_Found node. The moment an email surfaces, the lead short-circuits to Finalize and the remaining stages are skipped. If a stage's API errors, onError: continueRegularOutput keeps the lead moving instead of crashing the pipeline.
Before the waterfall, the system would have hit Apollo's people-match for every lead and burned its 100-credit free tier in a week. After the waterfall, Apollo usage drops to ~20–32 credits/month — only the leads no cheaper method could resolve. A 68–80% cost reduction with no accuracy loss; a brand's own website often lists its partnerships email more reliably than Apollo's stale database does.
The pattern is six lines of pseudocode, but it's the single biggest determinant of whether this pipeline costs $5/month or $50/month: rank enrichment methods by cost-per-call, run the cheap ones first, short-circuit on success.
Brand extraction v2: replacing a heuristic with an LLM
The first version of the RSS Collector used the article title as the brand candidate. "Glossier launches new lip product" → lead = Glossier. This caught ~40% of articles. The other 60% were roundups mentioning many brands, or articles where the brand name lived in the body but not the title.
V2 (deployed 2026-04-11) replaces the heuristic with a full-body LLM extraction pass. For each article: fetch HTML, strip nav/footer/scripts, cap at 3,000 characters, pass to gpt-4o-mini with response_format: json_object. The model returns up to five brands per article, each with a guessed domain and a signal type — launch, funding, rebrand, new-product, creator-call.
The gotcha that bit me here is the kind only production exposes: Google Sheets has a 60-read/minute quota. V1 read Master Leads and Staging inside the per-feed loop. Eight feeds × two reads = 16 reads — fine in dev, instantly rate-limited in production. Fix: hoist both reads outside the loop with executeOnce: true.
Then v2 added a dedicated Perplexity brand-research pre-stage before the waterfall: one Sonar call returns domain, decision-maker, submission channel, brand brief, and email. When it works, the lead finalizes with no further calls. When it fails to find an email, the waterfall runs with a corrected domain, so downstream Apify/Hunter/Apollo lookups hit far more often. One LLM call replaces four waterfall calls — cost-neutral, signal-positive.
Guardrail: Perplexity is told to only return emails whose domain matches the verified brand domain. The parser drops anything else. The LLM is allowed to suggest; a downstream check enforces.
Key decisions
- Five workflows, not one. Source-specific collectors evolve independently. Monolithic pipelines die under their own debugging cost.
- Google Sheet as the operational surface. Josephine doesn't operate the n8n panel; she opens a sheet. The columns are a contract — I never break them.
- Cost-aware waterfall ordering. Cheapest method first, short-circuit on success. Reduced Apollo usage by 68–80%.
- One Perplexity call to replace four waterfall calls. Short-circuits the pipeline when it works; produces a corrected domain when it doesn't.
- Full-body LLM brand extraction, not title heuristic. Title-only missed 60% of articles. Cleaned 3,000-char bodies catch the rest.
- Pitches open with article social proof. "Congrats on the launch covered in [Article] — I'd love to be part of how you tell the next chapter" outperforms "Hi [Brand], I love your products" ~3× by Josephine's qualitative read.
- Hoist external reads outside loops. Sheets rate limits don't care that you're inside a loop.
- Error handler as its own workflow. Failures get noticed within minutes, not on Monday morning.
- Cost ceilings as visible constants.
MAX_QUERIES = 40lives in the validator node, not buried in a sub-expression. continueOnFailon every external HTTP node. Hunter returns 429s, Apollo has flaky pagination, Apify breaks when sites change. The pipeline doesn't get to crash because of any one of them.
What the pipeline produces
Inside the pipeline


Reflection — rank everything by cost-per-call before you compose anything
The most useful design lens I applied here, copied from years of integration work: rank everything by cost-per-call before you compose anything. Most "AI pipeline" disasters are spec-driven — someone says "use Apollo for emails" and the pipeline burns through credits in a week because nobody asked which other tools could answer first. The waterfall pattern isn't novel; the discipline of actually doing it is what makes the difference between $5/month and $50/month.
The lesson from brand-extraction v1 → v2 is about replacing heuristics with LLMs at the right boundary. Article-title heuristic was fast and free, but it missed 60% of articles. Full-body LLM extraction is slower (~$0.02/month) but catches the right thing. An LLM in the right place pays for itself many times over; an LLM in the wrong place burns money without adding signal.
What I'd do differently: build the cost dashboard earlier. A single Google Sheet tab aggregating per-run cost would have saved me cycles of "is this still in budget?" anxiety.
What I'm proud of: it's a pipeline that does outbound work I'd find tedious, in a domain I have no personal expertise in, for a creator who doesn't have to understand any of the architecture to benefit from it. The system is the product; she reads the output. That's what good infrastructure feels like.