Reddit is one of the highest-intent lead sources available for B2B SaaS, agencies, and service providers people openly describe their problems, compare tools, and ask for recommendations before making purchase decisions. The challenge is that relevant posts across dozens of subreddits appear constantly, and manual monitoring doesn't scale.
This post walks through a production-ready n8n workflow that monitors subreddits automatically, filters irrelevant posts, scores buying intent using Gemini AI, generates a contextual reply draft, and delivers everything to Slack without auto-posting anything to Reddit.
Free workflow JSON at the end.
Why Manual Reddit Monitoring Breaks
Manual Reddit lead gen fails at scale for three specific reasons:
- Timing: Reddit conversations move fast. A delayed reply by 2–3 hours often means the original poster has already engaged with a competitor's response
- Inconsistency: Intent judgment varies by person. Same post scored differently depending on who's scrolling
- Volume: Monitoring r/entrepreneur, r/SaaS, r/smallbusiness, r/nocode, r/webdev simultaneously is a full-time task
The workflow below solves all three consistent scoring, every 10 minutes, across all subreddits simultaneously.
Architecture
┌──────────────────────────────────────────────────────────────┐
│ n8n Reddit Lead Generation Workflow │
│ │
│ [Cron Trigger] → every 10 minutes │
│ ↓ │
│ [RSS Feed Read] → pull new posts from N subreddits │
│ ↓ │
│ [Filter Keywords] → remove non-intent posts │
│ ↓ │
│ [Dedup Posts] → skip already-processed posts │
│ ↓ │
│ [Score Intent: Gemini] → 0-10 score + reasoning │
│ ↓ │
│ [Structured Output Parser] → enforce JSON schema │
│ ↓ │
│ [Check Intent] → pass only score ≥ 6 │
│ ↓ │
│ [Generate Reply: Gemini] → draft helpful response │
│ ↓ │
│ [Slack] → deliver to #reddit-leads channel │
└──────────────────────────────────────────────────────────────┘
Stack
| Tool | Role |
|---|---|
| n8n (self-hosted or Cloud) | Orchestration |
| Reddit RSS feeds | Post ingestion (no API key needed) |
| Google Gemini | Intent scoring + reply generation |
| LangChain Structured Output Parser | Enforce consistent JSON response |
| Slack Bot | Lead delivery channel |
Node-by-Node Breakdown
1. Cron Trigger
Interval: Every 10 minutes
10 minutes balances real-time detection against Gemini API call volume. Shorter intervals catch posts faster but increase API costs. Longer intervals risk missing the early reply window when the original poster is most active.
If you're on Gemini's free tier, check current RPM limits before shortening the interval each run processes multiple posts and makes multiple API calls.
2. RSS Feed Read
Reddit exposes subreddit RSS feeds without authentication:
https://www.reddit.com/r/SaaS/new.json?sort=new&limit=25
https://www.reddit.com/r/entrepreneur/new.json?sort=new&limit=25
https://www.reddit.com/r/smallbusiness/new.json?sort=new&limit=25
https://www.reddit.com/r/nocode/new.json?sort=new&limit=25
https://www.reddit.com/r/webdev/new.json?sort=new&limit=25
Configure the RSS Feed Read node with multiple URLs — it fetches all and returns a merged array of posts. Each post object includes title, selftext (body), permalink, author, created_utc, and id.
Rate limit note: Reddit's RSS endpoints are rate-limited. Running across 10+ subreddits simultaneously can trigger 429 responses. Add a short delay between feed reads if you're monitoring many communities.
3. Filter Keywords — Remove Non-Intent Posts
This node runs before the AI scoring step to avoid burning Gemini API calls on obviously irrelevant posts.
// Filter node — keep only posts matching intent phrases
const intentPhrases = [
'recommend',
'looking for',
'best tool',
'anyone use',
'what do you use',
'alternative to',
'switch from',
'trying to find',
'suggestions',
'help me choose',
'which is better',
'need something that',
'does anyone know',
'has anyone tried'
];
const title = ($json.title || '').toLowerCase();
const body = ($json.selftext || '').toLowerCase();
const combined = title + ' ' + body;
const hasIntent = intentPhrases.some(phrase => combined.includes(phrase));
return hasIntent ? [$input.first()] : [];
Adjust intentPhrases to match your product category. For a DevOps tool, add phrases like "deploy", "CI/CD", "pipeline". For a CRM, add "manage leads", "sales tracking". The more specific the list, the fewer false positives reach the scoring step.
4. Dedup Posts — Prevent Repeat Alerts
Without deduplication, the same post triggers a new Slack alert on every 10-minute cron run until it ages out of the RSS feed. This is the fastest way to train your team to ignore the Slack channel.
// Code Node — Dedup using n8n workflow static data
const staticData = $getWorkflowStaticData('global');
const processed = staticData.processedPostIds || {};
const now = Date.now();
// Clean entries older than 24 hours
Object.keys(processed).forEach(id => {
if (now - processed[id] > 24 * 60 * 60 * 1000) {
delete processed[id];
}
});
const postId = $json.id;
const isDuplicate = !!processed[postId];
if (!isDuplicate) {
processed[postId] = now;
}
staticData.processedPostIds = processed;
return isDuplicate ? [] : [$input.first()];
Why 24-hour window? Reddit posts stay active for hours to days. A 24-hour suppression window prevents repeat alerts while still allowing genuinely new posts with similar topics to come through.
Limitation: n8n static data resets on workflow restart. For persistent cross-session dedup, replace this with a Google Sheets lookup or a simple database write.
5. Score Intent — Gemini Classification
This is the core intelligence layer. Gemini reads each post and assigns a 0–10 buying intent score.
Scoring Prompt
You are a lead qualification specialist for [Company/Product Name].
Your job is to score the buying intent of Reddit posts for a [product category] tool.
Intent scoring rubric:
- 9-10: Explicitly asking for tool recommendations with specific requirements, budget signals, or urgency
- 7-8: Clearly evaluating options, comparing tools, or expressing dissatisfaction with current solution
- 5-6: Discussing the problem space, may be open to recommendations
- 3-4: General question about the topic, low probability of purchase intent
- 1-2: Tangentially related, no buying signals
- 0: Not relevant
Post Title: {{ $json.title }}
Post Body: {{ $json.selftext }}
Subreddit: {{ $json.subreddit }}
Return ONLY valid JSON:
{
"score": 0-10,
"reasoning": "One or two sentences explaining the score based on specific signals in the post",
"key_signals": ["signal 1", "signal 2"],
"urgency": "low|medium|high"
}
Key settings:
- Temperature:
0.1— consistent scoring is more valuable than creative variation - Model:
gemini-1.5-flash(fast, cost-efficient for scoring) orgemini-1.5-pro(better reasoning on complex posts)
Structured Output Parser
The LangChain Structured Output Parser sub-node enforces the JSON schema. If Gemini returns markdown fences or malformed JSON, the parser catches it and routes to the error branch.
// If parser fails, fallback
{
score: 0,
reasoning: "Parse error — manual review required",
key_signals: [],
urgency: "low"
}
Route parser failures to a separate Slack alert so they're visible without stopping the whole pipeline.
6. Check Intent — Quality Gate
// IF node condition
{{ $json.score }} >= 6
// true → continue to reply generation
// false → stop (post is dropped silently)
Why 6? Posts scoring 5 or below are typically informational questions without clear purchase intent. A threshold of 6 captures posts where someone is genuinely evaluating options without letting through every tangential mention.
Tune this threshold after the first week of runs. If you're seeing too many false positives (low-quality posts making it through), raise to 7. If you're missing obvious opportunities, lower to 5.
7. Generate Reply — Gemini Draft
Posts that clear the intent gate get a reply drafted automatically.
You are writing a helpful, non-promotional reply to a Reddit post on behalf of someone from [Company Name].
Rules:
- Answer the person's actual question first
- Be genuinely helpful, not salesy
- Mention [Product Name] naturally only if directly relevant — do not force it
- Match the tone of the subreddit (r/{{ $json.subreddit }} is [tone descriptor])
- Keep the reply under 150 words
- Do not start with "Great question" or similar filler phrases
- Sound like a knowledgeable community member, not a sales rep
Original post title: {{ $json.title }}
Original post body: {{ $json.selftext }}
Intent score: {{ $json.score }}
Key signals identified: {{ $json.key_signals }}
Write a reply that would genuinely help this person.
Store the generated reply as {{ $json.suggested_reply }} for the Slack notification.
8. Slack Notification
// Build Slack Block Kit message
const { score, reasoning, urgency, suggested_reply } = scoringOutput;
const { title, permalink, author, subreddit } = postData;
const urgencyEmoji = { high: '🔴', medium: '🟡', low: '🟢' };
const scoreBar = score >= 8 ? '🔥 Hot' : score >= 6 ? '✅ Qualified' : '⚪ Low';
const blocks = [
{
type: 'header',
text: { type: 'plain_text', text: `${urgencyEmoji[urgency]} Reddit Lead — Score ${score}/10` }
},
{
type: 'section',
fields: [
{ type: 'mrkdwn', text: `*Subreddit:*\nr/${subreddit}` },
{ type: 'mrkdwn', text: `*Intent:*\n${scoreBar}` },
{ type: 'mrkdwn', text: `*Urgency:*\n${urgency.toUpperCase()}` },
{ type: 'mrkdwn', text: `*Author:*\nu/${author}` }
]
},
{
type: 'section',
text: { type: 'mrkdwn', text: `*Post:*\n${title}` }
},
{
type: 'section',
text: { type: 'mrkdwn', text: `*AI Reasoning:*\n${reasoning}` }
},
{
type: 'section',
text: { type: 'mrkdwn', text: `*Suggested Reply:*\n${suggested_reply}` }
},
{
type: 'actions',
elements: [
{
type: 'button',
text: { type: 'plain_text', text: '💬 Open Thread' },
url: `https://reddit.com${permalink}`,
style: 'primary'
}
]
}
];
Slack bot scoping: Token should be chat:write scoped to #reddit-leads only. Do not use workspace-wide permissions.
Customisation Options
Raise or Lower the Intent Threshold
// Check Intent node — adjust threshold
{{ $json.score }} >= 7 // Stricter — fewer, higher-quality leads
{{ $json.score }} >= 5 // Broader — more leads, more noise
Review the first 50 scored posts manually to calibrate. The right threshold depends on your product category and how broad the relevant subreddits are.
Add CRM Integration
After the Slack notification, add a node that creates a lead record in your CRM:
[Slack notification]
↓
[HubSpot / Pipedrive / Salesforce: Create Contact]
Fields: source=reddit, subreddit, post_title, intent_score, post_url
Add Google Sheets Logging
[Slack notification]
↓
[Google Sheets: Append Row]
Columns: timestamp | subreddit | post_title | score | urgency | post_url | suggested_reply | actioned_by
Gives a searchable lead history and lets you track which subreddits produce the most qualified leads over time.
Multi-Client Setup
For agencies running this for multiple clients, run separate workflow instances per client — each with its own:
- Subreddit list
- Keyword filter
- Scoring prompt (tuned to the client's product category)
- Intent threshold
- Slack channel
Avoid conditional branching inside one workflow for multi-client setups — separate instances are easier to debug and permission.
Swap Gemini for Another Model
Both the scoring and reply generation nodes can use Claude or GPT-4o instead of Gemini. The Structured Output Parser is model-agnostic — it enforces the JSON schema regardless of which model produced the response.
If you swap models, re-test scoring on 20–30 real posts first. Different models interpret buying intent differently, and the threshold that works for Gemini may need adjustment for another model.
Error Handling
// Error branch — log + alert
const errorLog = {
timestamp: new Date().toISOString(),
pipeline: "Reddit Lead Generation",
failed_node: $input.first().json.failedNode || "unknown",
error: $input.first().json.error?.message || "Unknown",
post_id: $('RSS Feed Read').first().json?.id || "unknown",
post_title: $('RSS Feed Read').first().json?.title || "unknown"
};
return [{ json: errorLog }];
Common Failure Points
| Failure | Cause | Handling |
|---|---|---|
| Gemini 429 (rate limit) | Too many posts per run | Add delay between scoring calls; reduce cron frequency |
| Gemini JSON parse error | Model added markdown fences | Strip with regex, retry once |
| Reddit RSS 429 | Too many subreddits polled simultaneously | Add delay between feed reads |
| Slack 400 | Malformed Block Kit JSON | Log raw blocks array, check field lengths |
| Static data reset | Workflow restarted | Acceptable for most cases; use Sheets for persistent dedup |
Limitations
Scoring depends on post quality. A post that vaguely mentions a problem without clear intent will score inconsistently. Better filtering upstream reduces this — tighter keyword phrases mean fewer ambiguous posts reach the scoring step.
No direct Reddit API. This workflow uses RSS feeds, which are public and don't require authentication. The tradeoff: RSS doesn't include comment data, so replies to a post aren't visible. The workflow sees new posts only, not evolving threads.
AI replies need human review before posting. Tone norms vary significantly between subreddits. r/entrepreneur and r/SaaS have different cultures, and a reply that lands well in one can feel off in another. Always review the suggested reply before sending.
No persistent dedup across restarts. The static data approach resets on workflow restart. For production setups with high uptime requirements, replace with Google Sheets or a database.
Get the Free Workflow JSON
IT Path Solutions published the complete n8n workflow — cron trigger, RSS feed reader, keyword filter, dedup node, Gemini intent scoring with structured output, quality gate, reply generation, and Slack Block Kit notification — all pre-connected.
Import into any n8n instance, add Gemini API key and Slack bot token, update subreddit list and keywords, activate.
👉 Download the free Reddit lead generation workflow JSON
Setup guide covers: Gemini credential config, Slack bot scoping, subreddit RSS URL format, keyword filter tuning, and how to calibrate the intent threshold in the first week.
Summary
The pipeline works because it applies a two-layer filter (keywords + AI scoring) before anything reaches your team, runs every 10 minutes so high-intent posts arrive while the conversation is still active, and delivers everything needed to respond in a single Slack message — without auto-posting anything publicly.
Tune the keyword list and intent threshold after the first week of real runs. The defaults are a starting point, not a fixed configuration.
Full guide and JSON: itpathsolutions.com/reddit-lead-generation-workflow-n8n
Top comments (0)