Turn LinkedIn post engagers into scored leads with n8n
Find LinkedIn posts by topic, pull every reactor and commenter, score them against your ICP with AI, and save hot leads with a ready connection note to Google Sheets.
Find LinkedIn posts on any topic, pull everyone who reacted or commented, score each person against your ICP with AI, and save qualified leads with a ready connection note to Google Sheets. No post URLs needed: you give the workflow a topic, and it finds the posts itself.
Why post engagers convert better than cold lists, and how to run the same pipeline from MCP or REST: see the playbook Mine LinkedIn post engagement for intent signals.
Import the template: Score LinkedIn post engagers as leads with Periodix Actions, Claude, and Google Sheets
What you need
- A Periodix Actions account with a connected LinkedIn profile (3-day free trial)
- The Periodix Actions node installed (listed in n8n as Periodix LinkedIn), see Installation
- An AI provider API key: Claude by default, OpenAI or Gemini also work
- A Google Sheet with two tabs: Hot and Cold
Workflow at a glance
Run Daily → Campaign Config → Find Topic Posts (Periodix Actions) → Extract Posts → Loop Posts → Get Post Reactions + Get Post Comments (Periodix Actions) → Normalize → Merge → Dedupe and Pre-filter by ICP → Score and Draft with AI → Parse AI Output → Hot Lead? → Save Hot Lead / Save Cold Lead
Step by step
1. Run Daily (Schedule Trigger)
Runs once a day at 9:00. Change the hour to fit your timezone.
2. Campaign Config (Set node)
All settings live in one place:
| Field | Example | What it controls |
|---|---|---|
| topic_keywords | AI agents in sales | The topic used to find posts |
| icp_keywords | founder, head of, growth, marketing, sales | Cheap pre-filter on headline and company, before any AI call |
| icp_description | Role, company type, size | Passed to AI for scoring |
| offer | One sentence on what you offer | Passed to AI for the connection note |
| score_threshold | 7 | Minimum score to count as a hot lead |
| posts_limit | 20 | How many posts to pull per run |
| reactions_limit | 100 | Max reactions per post |
| comments_limit | 100 | Max comments per post |
3. Find Topic Posts (Periodix Actions: Search)
- Resource: Search
- Profile: your connected LinkedIn profile
- Search URL:
{{ "https://www.linkedin.com/search/results/content/?keywords=" + encodeURIComponent($("Campaign Config").first().json.topic_keywords) }}
- Limit:
{{ $("Campaign Config").first().json.posts_limit }}
The search runs asynchronously and can take a few minutes. Each matching post becomes one item.
4. Extract Posts (Code node)
Dedupes posts and keeps three fields: post_id, post_url, and post_text (first 500 characters). The post ID is taken from social_id when present. This is the identifier that the reactions and comments operations expect.
5. Loop Posts (Loop Over Items)
Processes one post at a time, so reactions and comments are always matched to the right post.
6. Get Post Reactions and Get Post Comments (Periodix Actions: Post)
Both run in parallel for the current post:
- Resource: Post
- Operation: Get Reactions / Get Comments
- Post ID:
{{ $json.post_id }} - Limit:
reactions_limit/comments_limitfrom Campaign Config - Settings → On Error: Continue, so a post with no engagement does not stop the run
7. Normalize Reactions and Normalize Comments (Code nodes)
Both branches are mapped to the same shape:
| Field | Source |
|---|---|
| source | reaction or comment |
| name, headline, company | Engager's profile |
| provider_id | LinkedIn ID, used later to send a connection request |
| profile_url | Public profile URL |
| matched_post, post_url | The post they engaged with |
8. Merge, Collect, Dedupe and Pre-filter by ICP (Merge + Code nodes)
Engagers from all posts are merged and deduped by provider_id. Anyone whose headline or company contains none of your icp_keywords is dropped here, before any AI call. This is the main cost saver: you never pay to score someone who was never going to qualify. Leave icp_keywords empty to skip the pre-filter.
9. Score and Draft with AI (HTTP Request)
One AI call per engager does two jobs: it scores ICP fit from 1 to 10 with a short reason, and, for scores of 5 or higher, it writes a connection note under 300 characters that references the post the person engaged with. The default is Claude Haiku via the Anthropic API, one request every 1.5 seconds, with retry on failure. Swap the URL and body to use OpenAI or Gemini.
10. Parse AI Output (Code node)
Strips code fences and parses the JSON reply into score, reason, and connection_note. If parsing fails, the engager gets a score of 0 and the reason parse error, so nothing is lost silently.
11. Hot Lead? (If node) and Save to Google Sheets
Engagers with score >= score_threshold go to the Hot tab with the connection note. Everyone else goes to the Cold tab with the score and reason, which you can use to refine your ICP.
Example output (Hot tab row)
{
"source": "comment",
"name": "Jane Doe",
"headline": "Head of Growth at Example SaaS",
"company": "Example SaaS",
"provider_id": "ACoAAExample123",
"profile_url": "https://www.linkedin.com/in/janedoe",
"matched_post": "We replaced our SDR research step with an AI agent...",
"post_url": "https://www.linkedin.com/feed/update/urn:li:activity:0000000000000000000",
"score": 8,
"reason": "Growth leader at a B2B SaaS company actively exploring AI in outbound.",
"connection_note": "Hi Jane, your comment on using AI agents for SDR research stood out. We work on the same problem from the LinkedIn data side, would be great to connect."
}Next step: send the connection requests
Add a Periodix Actions node after Save Hot Lead:
- Resource: Connection
- Operation: Send Request
- Recipient:
{{ $json.provider_id }} - Note:
{{ $json.connection_note }}
Add a Wait node with a randomized delay between sends, and start with low daily volumes on new or recently inactive accounts.
Troubleshooting
- No posts found: try broader topic keywords, and check that the selected profile is connected on the Profiles page.
- Some posts return no engagers: normal for posts with little engagement. On Error: Continue keeps the run going.
- Almost everyone is filtered out: your
icp_keywordsare too narrow. Add more terms or leave the field empty. - Scores of 0 with reason "parse error": the AI reply was not valid JSON. Check the model name and the API key, and keep the "Respond in raw JSON only" instruction in the prompt.
- The same person appears on different days: the workflow dedupes within one run only. To skip people already in the sheet, read the Hot and Cold tabs first and filter by
provider_id, or use the Google Sheets Append or Update operation matched onprovider_id. - The run takes a long time: each post adds two Periodix calls and one AI call per engager. Lower
posts_limit,reactions_limit, orcomments_limit.
Related
Updated 5 days ago