LinkedIn Social Listening Workflow
Build an n8n workflow that monitors LinkedIn for keywords, scores relevance with AI, and sends draft replies to Telegram.
What We’re Building
A fully automated LinkedIn social listening system that:
- Scrapes LinkedIn for posts matching your target keywords (via Apify)
- Scores each post for relevance using an AI model (via OpenRouter)
- Drafts a personalized reply for high-scoring posts
- Sends alerts to Telegram with the post, score, and draft reply — ready for you to copy-paste
The end result: you wake up to a Telegram channel full of pre-written, context-aware replies to the most relevant LinkedIn conversations in your niche. No scrolling required.
Initial Prompt
“I want to monitor LinkedIn for posts about AI automation, score them for relevance to Happy Operators, and get draft replies sent to my Telegram. Use n8n, Apify for scraping, and OpenRouter for the AI scoring.”
Architecture Overview
| Component | Tool | Purpose |
|---|---|---|
| Scheduler | n8n Cron | Triggers the workflow daily at 7am |
| Scraper | Apify LinkedIn Actor | Searches LinkedIn for keyword matches |
| Filter | n8n Code Node | Deduplicates and cleans raw results |
| AI Scorer | OpenRouter (Claude/GPT) | Scores relevance 1-10 with reasoning |
| Reply Drafter | OpenRouter (Claude/GPT) | Writes personalized reply drafts |
| Notification | Telegram Bot API | Sends formatted alerts to your channel |
Flow:
Cron (7am) → Apify Search → Filter & Dedupe → AI Score → Draft Reply → Telegram
Step-by-Step Build
Step 1: Set Up Apify LinkedIn Scraper
First, you need an Apify account and a LinkedIn scraping actor.
- Sign up at apify.com (free tier works for low volume)
- Find the LinkedIn Posts Search actor in the Apify Store
- Configure it with your search keywords:
{
"searchKeywords": ["AI automation", "workflow automation", "n8n"],
"maxResults": 50,
"timeFilter": "past-24h",
"sortBy": "relevance"
}
- Run it once manually to verify results
- Copy your API token from Apify Settings — you’ll need this in n8n
Step 2: Create the n8n Workflow
Open your n8n instance and create a new workflow.
Trigger Node: Schedule
{
"rule": {
"interval": [{ "field": "cronExpression", "expression": "0 7 * * *" }]
}
}
This fires every day at 7:00 AM.
HTTP Request Node: Call Apify
Add an HTTP Request node to trigger the Apify actor:
Method: POST
URL: https://api.apify.com/v2/acts/YOUR_ACTOR_ID/runs
Headers:
Authorization: Bearer YOUR_APIFY_TOKEN
Content-Type: application/json
Body:
{
"searchKeywords": ["AI automation", "workflow automation"],
"maxResults": 50,
"timeFilter": "past-24h"
}
Wait Node
Apify runs are async. Add a Wait node (60-120 seconds) for the scrape to complete, then fetch results:
Method: GET
URL: https://api.apify.com/v2/actor-runs/{{ $json.data.id }}/dataset/items
Headers:
Authorization: Bearer YOUR_APIFY_TOKEN
Step 3: Filter & Deduplicate
Add a Code node to clean the results:
const items = $input.all();
const seen = new Set();
const filtered = [];
for (const item of items) {
const post = item.json;
// Skip if we've seen this post URL before
if (seen.has(post.url)) continue;
seen.add(post.url);
// Skip posts with very low engagement
if ((post.likes || 0) < 5) continue;
// Skip your own posts
if (post.authorName?.includes('Happy Operators')) continue;
filtered.push({
json: {
url: post.url,
author: post.authorName,
authorHeadline: post.authorHeadline,
content: post.text?.substring(0, 1000), // Truncate for AI
likes: post.likes || 0,
comments: post.comments || 0,
postedAt: post.postedAt,
}
});
}
return filtered;
Step 4: AI Relevance Scoring
Add an HTTP Request node to call OpenRouter:
Method: POST
URL: https://openrouter.ai/api/v1/chat/completions
Headers:
Authorization: Bearer YOUR_OPENROUTER_KEY
Content-Type: application/json
Request body:
{
"model": "anthropic/claude-sonnet-4-5-20250929",
"messages": [
{
"role": "system",
"content": "You are a social listening analyst for Happy Operators, an AI & automation training company. Score LinkedIn posts for engagement relevance on a scale of 1-10.\n\nScore HIGH (7-10) if the post:\n- Discusses AI/automation pain points we solve\n- Is from a founder, ops lead, or team manager\n- Has good engagement (likes/comments)\n- Offers a natural opening for our expertise\n\nScore LOW (1-3) if the post:\n- Is from a competitor selling similar services\n- Is purely self-promotional with no conversation\n- Is off-topic (just mentions AI tangentially)\n\nRespond in JSON: {\"score\": N, \"reason\": \"brief explanation\", \"angle\": \"suggested approach for reply\"}"
},
{
"role": "user",
"content": "Author: {{ $json.author }}\nHeadline: {{ $json.authorHeadline }}\nPost: {{ $json.content }}\nEngagement: {{ $json.likes }} likes, {{ $json.comments }} comments"
}
],
"temperature": 0.3
}
Parse the response with a Code node:
const response = JSON.parse($input.first().json.choices[0].message.content);
return [{
json: {
...$input.first().json,
score: response.score,
reason: response.reason,
angle: response.angle,
}
}];
Step 5: Filter High-Score Posts
Add an IF node:
Condition: {{ $json.score }} >= 7
Only posts scoring 7+ continue to the reply drafting step.
Step 6: Draft Replies
Another OpenRouter call to draft the actual reply:
{
"model": "anthropic/claude-sonnet-4-5-20250929",
"messages": [
{
"role": "system",
"content": "Write a LinkedIn comment reply for Happy Operators. Rules:\n- Be genuinely helpful, not salesy\n- Reference something specific from the post\n- Add a practical insight or tip\n- Keep it under 100 words\n- Sound human, not corporate\n- No emojis in the first line\n- End with a question or conversation opener when natural"
},
{
"role": "user",
"content": "Post by {{ $json.author }}:\n{{ $json.content }}\n\nSuggested angle: {{ $json.angle }}"
}
],
"temperature": 0.7
}
Step 7: Send to Telegram
Final node — send the formatted alert:
Method: POST
URL: https://api.telegram.org/bot{{ YOUR_BOT_TOKEN }}/sendMessage
Body:
{
"chat_id": "YOUR_CHAT_ID",
"parse_mode": "HTML",
"text": "🎯 <b>LinkedIn Match (Score: {{ $json.score }}/10)</b>\n\n<b>Author:</b> {{ $json.author }}\n<b>Why:</b> {{ $json.reason }}\n\n<b>Post preview:</b>\n<i>{{ $json.content.substring(0, 300) }}...</i>\n\n<b>Draft reply:</b>\n{{ $json.draftReply }}\n\n<a href=\"{{ $json.url }}\">Open on LinkedIn →</a>"
}
Setup Checklist
Before running this workflow, you need:
- Apify account with LinkedIn Posts Search actor — apify.com
- Apify API token — Settings → Integrations
- OpenRouter account with credits — openrouter.ai
- OpenRouter API key — Keys section in dashboard
- Telegram Bot — create via @BotFather
- Telegram Chat ID — send a message to your bot, then call
getUpdatesAPI - n8n instance — self-hosted or n8n.io cloud
- Keywords defined — what topics should trigger monitoring
How to Use
Once deployed, the workflow runs automatically every morning:
- Check Telegram — you’ll have a channel of scored, filtered LinkedIn posts with draft replies
- Review the drafts — adjust tone or add personal context if needed
- Copy-paste to LinkedIn — open the post link, paste the reply, send
- Track what works — note which scores/angles lead to actual conversations
Tips for best results:
- Start with 3-5 specific keywords, not broad terms
- Adjust the scoring prompt as you learn what “relevant” means for your business
- Review and skip posts scored 7 that aren’t actually useful — refine the prompt
- Aim to respond within 2-4 hours of the post going live for maximum visibility
Future Improvements
- LinkedIn comment posting — auto-post approved replies (requires LinkedIn API access or browser automation)
- CRM integration — auto-create leads in Notion when you engage with someone
- Engagement tracking — follow up on posts you replied to, track if they responded
- Multi-platform — extend to Twitter/X with similar scoring
- Sentiment analysis — detect frustration posts (higher conversion opportunity)
- Slack alternative — send to Slack instead of or alongside Telegram
Need help building this?
We build workflows like this for teams every week. Book a free discovery call and we'll scope it together.
Chat with us →