This workflow corresponds to n8n.io template #4879 — we link there as the canonical source.
This workflow follows the Agent → Google Sheets recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "3gnnZ2YIkY7KtWGV",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Linkedin Leads Automation",
"tags": [
{
"id": "3wP6uU6SFbrRYs5q",
"name": "youtube",
"createdAt": "2025-05-17T22:21:11.653Z",
"updatedAt": "2025-05-17T22:21:11.653Z"
}
],
"nodes": [
{
"id": "62e62e1f-e71d-4869-bceb-370e4ab853e2",
"name": "Set Fields",
"type": "n8n-nodes-base.set",
"position": [
-1280,
80
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "cc27b2d9-8de7-43ca-a741-2d150084f78e",
"name": "currentStartIndex",
"type": "number",
"value": 1
}
]
}
},
"typeVersion": 3.4
},
{
"id": "c762fb3b-5574-4a25-ac2a-aa6f007bf79e",
"name": "Add to Google",
"type": "n8n-nodes-base.googleSheets",
"position": [
0,
0
],
"parameters": {
"columns": {
"value": {
"Name": "={{ $json.name }}",
"title": "={{ $json.position }}",
"profile_url": "={{ $json.link }}"
},
"schema": [
{
"id": "Name",
"type": "string",
"display": true,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "title",
"type": "string",
"display": true,
"required": false,
"displayName": "title",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "profile_url",
"type": "string",
"display": true,
"required": false,
"displayName": "profile_url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "about",
"type": "string",
"display": true,
"required": false,
"displayName": "about",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "outreach message 1",
"type": "string",
"display": true,
"required": false,
"displayName": "outreach message 1",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1jajDVL6_sMlrK6cQNkKPqPpUVOPUst_A7hyMg0cuyrM/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1jajDVL6_sMlrK6cQNkKPqPpUVOPUst_A7hyMg0cuyrM",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1jajDVL6_sMlrK6cQNkKPqPpUVOPUst_A7hyMg0cuyrM/edit?usp=drivesdk",
"cachedResultName": "linkedin"
}
},
"credentials": {},
"typeVersion": 4.5
},
{
"id": "b9ce466d-8080-40ec-8f3d-99e446ddee54",
"name": "OpenRouter Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"position": [
260,
180
],
"parameters": {
"model": "perplexity/sonar-pro",
"options": {}
},
"credentials": {},
"typeVersion": 1
},
{
"id": "9451edb8-a7a6-4840-9eea-e799f4bf0721",
"name": "Research Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
280,
0
],
"parameters": {
"text": "=Name: {{ $json.name }}\nTitle: {{ $json.title }}\nAbout: {{ $json.about }}",
"options": {
"systemMessage": "Your job is to research this lawyer or law firm founder as much as possible. The goal is to find relevant public information to help generate personalized outreach. This workflow is targeting solo practice lawyers and small law firms \u2014 not large firms or government attorneys. Avoid irrelevant sources. Focus on anything that reflects their legal focus (e.g., family law, criminal defense, small business law), local community involvement, or their firm\u2019s branding. Include source references (e.g., LinkedIn posts, website articles, etc.). No intros or conclusions."
},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "b5855a64-d62c-401e-8596-99888ff3a8b6",
"name": "Google Search",
"type": "n8n-nodes-base.httpRequest",
"position": [
-780,
80
],
"parameters": {
"url": "https://www.googleapis.com/customsearch/v1",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "key",
"value": "YOUR_API_KEY_OR_CX_ID"
},
{
"name": "cx",
"value": "YOUR_API_KEY_OR_CX_ID"
},
{
"name": "q",
"value": "(\"solo practitioner\" OR \"founder\" OR \"managing partner\") lawyer \"law firm\" site:linkedin.com/in -government -gov -biglaw"
},
{
"name": "start",
"value": "={{ $json.startIndex || 1 }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "f36fb9ae-dcd3-44dd-8096-5ae6efd0f83b",
"name": "Results ",
"type": "n8n-nodes-base.code",
"position": [
-440,
80
],
"parameters": {
"jsCode": "// Get the response data\nconst response = $input.first().json;\nconst items = response.items || [];\n\n// Track pagination info\nlet nextStartIndex = 1;\nif (response.queries && response.queries.nextPage && response.queries.nextPage[0]) {\n nextStartIndex = response.queries.nextPage[0].startIndex;\n}\n\n// Calculate if we should continue (Google only allows up to 100 results)\nconst hasMoreResults = nextStartIndex <= 100;\n\n// Process the items and include pagination info in each item\nconst results = items.map(item => {\n const titleParts = item.title.split(\" - \");\n return {\n name: titleParts[0] || null,\n position: titleParts.slice(1).join(\" - \") || null,\n link: item.link || null,\n about: item.snippet || null,\n image: item.pagemap?.cse_thumbnail?.[0]?.src || null,\n // Add pagination info to each item\n startIndex: nextStartIndex,\n hasMoreResults: hasMoreResults\n };\n});\n\n// If there are no results, return at least one item with pagination info\nif (results.length === 0) {\n return [{ \n json: {\n name: null,\n position: null,\n link: null,\n about: null,\n image: null,\n startIndex: nextStartIndex,\n hasMoreResults: false\n }\n }];\n}\n\n// Return the processed results\nreturn results.map(r => ({ json: r }));\n"
},
"typeVersion": 2
},
{
"id": "e3cbad5a-2022-4c67-bde1-87ac77687539",
"name": "Pages",
"type": "n8n-nodes-base.code",
"position": [
0,
200
],
"parameters": {
"jsCode": "// Get all input items\nconst inputItems = $input.all();\nconsole.log(\"Input items count:\", inputItems.length);\n\n// Extract pagination values with correct field names\nlet nextStartIndex = 1;\nlet hasMoreResults = false;\n\nif (inputItems && inputItems.length > 0) {\n const firstItem = inputItems[0];\n\n if (firstItem.json) {\n console.log(\"First item JSON:\", JSON.stringify(firstItem.json));\n\n // Look for \"startIndex\" instead of \"index\"\n if (firstItem.json.startIndex !== undefined) {\n nextStartIndex = firstItem.json.startIndex;\n console.log(\"Found startIndex:\", nextStartIndex);\n }\n\n // Look for \"hasMoreResults\" instead of \"results\"\n if (firstItem.json.hasMoreResults !== undefined) {\n hasMoreResults = firstItem.json.hasMoreResults;\n console.log(\"Found hasMoreResults:\", hasMoreResults);\n }\n }\n}\n\n// Return pagination control info\nreturn {\n json: {\n continueLoop: hasMoreResults,\n startIndex: nextStartIndex\n }\n};\n"
},
"typeVersion": 2
},
{
"id": "94b87b0b-0bff-4e13-a710-b2f2b9702cd9",
"name": "Pages Check",
"type": "n8n-nodes-base.if",
"position": [
-1040,
200
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "faef2862-80a4-465b-9e0b-be5b9753dcbd",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $('Pages').item.json.continueLoop }}",
"rightValue": "true"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "e41547c3-ed14-4882-906a-d0005f85ca4b",
"name": "Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
1340,
0
],
"parameters": {
"columns": {
"value": {
"name": "={{ $('Results ').all()[ $itemIndex ].json.name }}",
"outreach message 1": "={{ $json.message.content }}"
},
"schema": [
{
"id": "name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "title",
"type": "string",
"display": true,
"required": false,
"displayName": "title",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "profile_url",
"type": "string",
"display": true,
"required": false,
"displayName": "profile_url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "about",
"type": "string",
"display": true,
"required": false,
"displayName": "about",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "outreach message 1",
"type": "string",
"display": true,
"required": false,
"displayName": "outreach message 1",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"name"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1smDBk1Eh50sRyTEzEhzWkDnaWaexZHiHTxYlp2M6_J0/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1smDBk1Eh50sRyTEzEhzWkDnaWaexZHiHTxYlp2M6_J0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1smDBk1Eh50sRyTEzEhzWkDnaWaexZHiHTxYlp2M6_J0/edit?usp=drivesdk",
"cachedResultName": "linkedin"
}
},
"credentials": {},
"typeVersion": 4.5
},
{
"id": "5dccf520-fe74-458a-8e9d-34bc69cd5f54",
"name": "Outreach Agent",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
700,
0
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o",
"cachedResultName": "GPT-4O"
},
"options": {},
"messages": {
"values": [
{
"role": "system",
"content": "Your job is to create a short, personalized outreach icebreaker for solo lawyers or small law firm owners. Keep it genuine, professional, and brief \u2014 one line max. You may refer to their practice area, years in practice, recent content, community involvement, or anything that reflects their personal brand. Avoid generic statements. Do not ask about location. Do not mention large law firms or government service. Use a business-casual tone, and start with: \"Hey [name] ...\""
},
{
"content": "=Name: {{ $('Results ').all()[ $itemIndex ].json.name }}\nPosition: {{ $('Results ').all()[ $itemIndex ].json.position }}\nAbout: {{ $('Results ').all()[ $itemIndex ].json.about }}\n"
}
]
}
},
"credentials": {},
"typeVersion": 1.8
},
{
"id": "8340fc87-c844-4861-a4ff-75f7da7274a3",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1480,
80
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.2
}
],
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "69a6fdbc-0653-4c7a-8258-17146dd20530",
"connections": {
"Pages": {
"main": [
[
{
"node": "Pages Check",
"type": "main",
"index": 0
}
]
]
},
"Results ": {
"main": [
[
{
"node": "Add to Google",
"type": "main",
"index": 0
},
{
"node": "Pages",
"type": "main",
"index": 0
}
]
]
},
"Set Fields": {
"main": [
[
{
"node": "Google Search",
"type": "main",
"index": 0
}
]
]
},
"Pages Check": {
"main": [
[
{
"node": "Google Search",
"type": "main",
"index": 0
}
]
]
},
"Add to Google": {
"main": [
[
{
"node": "Research Agent",
"type": "main",
"index": 0
}
]
]
},
"Google Search": {
"main": [
[
{
"node": "Results ",
"type": "main",
"index": 0
}
]
]
},
"Outreach Agent": {
"main": [
[
{
"node": "Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Research Agent": {
"main": [
[
{
"node": "Outreach Agent",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Set Fields",
"type": "main",
"index": 0
}
]
]
},
"OpenRouter Chat Model": {
"ai_languageModel": [
[
{
"node": "Research Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
⚠️ This template uses only official n8n nodes. No community nodes required.
Source: https://n8n.io/workflows/4879/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This n8n workflow turns a script and character/setting description from Google Sheets into a complete stitched UGC-style video ad, fully automated from intake to final delivery.
This workflow automates the creation, rendering, approval, and posting of TikTok-style POV (Point of View) videos to Instagram, with cross-posting to Facebook and YouTube. It eliminates manual video p
Complete PostgreSQL-backed system: Keyword scoring → AI research → Multi-part content generation → fal.ai Nano Banana image generation → WordPress publishing
This workflow is designed for: Content creators and marketers E-commerce and product-based businesses Agencies producing social media visuals and videos Automation builders looking for AI-powered crea
Generate product images with NanoBanana Pro to Veo videos and Blotato - vide 2 ok. Uses httpRequest, editImage, googleDrive, googleSheets. Scheduled trigger; 76 nodes.