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 →
{
"name": "Scrapeless \u2014 SERP keyword tracking",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "days",
"triggerAtHour": 7
}
]
}
},
"id": "a1000000-0000-4000-8000-000000000001",
"name": "Every morning",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-220,
0
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "kw-1",
"name": "keywords",
"value": "web scraping api, headless browser, serp api",
"type": "string"
}
]
},
"options": {}
},
"id": "a1000000-0000-4000-8000-000000000002",
"name": "Keywords to track",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
0,
0
]
},
{
"parameters": {
"jsCode": "// One item per keyword so the HTTP node runs once per query.\nconst raw = $input.first().json.keywords || '';\nreturn raw\n .split(',')\n .map((keyword) => keyword.trim())\n .filter(Boolean)\n .map((keyword) => ({ json: { keyword } }));"
},
"id": "a1000000-0000-4000-8000-000000000003",
"name": "Split keywords",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
220,
0
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.scrapeless.com/api/v1/scraper/request",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "x-api-token",
"value": "={{ $env.SCRAPELESS_API_KEY }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ actor: 'scraper.google.search', input: { q: $json.keyword } }) }}",
"options": {
"timeout": 180000
}
},
"id": "a1000000-0000-4000-8000-000000000004",
"name": "Scrapeless SERP",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
440,
0
],
"onError": "continueRegularOutput",
"retryOnFail": true,
"maxTries": 3,
"waitBetweenTries": 3000,
"alwaysOutputData": true
},
{
"parameters": {
"jsCode": "// Flatten organic results into one row per ranking position.\n//\n// Note: the Code node sandbox does NOT expose the global URL constructor \u2014\n// `new URL(link)` throws \"URL is not defined\" at runtime even though the\n// workflow validates fine. Hostname is extracted with string ops instead.\nconst hostname = (link) =>\n link ? link.replace(/^[a-z]+:\\/\\//i, '').replace(/^www\\./i, '').split(/[/?#]/)[0] : '';\n\nconst rows = [];\n\nfor (const item of $input.all()) {\n const keyword = item.json.keyword ?? item.json.search_information?.query_displayed ?? '';\n const results = item.json.organic_results ?? [];\n\n if (!results.length) {\n rows.push({ json: { keyword, error: 'no organic_results in response' } });\n continue;\n }\n\n for (const result of results) {\n rows.push({\n json: {\n keyword,\n position: result.position ?? null,\n title: result.title ?? '',\n link: result.link ?? '',\n domain: hostname(result.link),\n snippet: result.snippet ?? '',\n checked_at: new Date().toISOString(),\n },\n });\n }\n}\n\nreturn rows;"
},
"id": "a1000000-0000-4000-8000-000000000005",
"name": "Flatten rankings",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
660,
0
]
},
{
"parameters": {},
"id": "a1000000-0000-4000-8000-000000000006",
"name": "Send to your store",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [
880,
0
]
}
],
"connections": {
"Every morning": {
"main": [
[
{
"node": "Keywords to track",
"type": "main",
"index": 0
}
]
]
},
"Keywords to track": {
"main": [
[
{
"node": "Split keywords",
"type": "main",
"index": 0
}
]
]
},
"Split keywords": {
"main": [
[
{
"node": "Scrapeless SERP",
"type": "main",
"index": 0
}
]
]
},
"Scrapeless SERP": {
"main": [
[
{
"node": "Flatten rankings",
"type": "main",
"index": 0
}
]
]
},
"Flatten rankings": {
"main": [
[
{
"node": "Send to your store",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Scrapeless — SERP keyword tracking. Uses httpRequest. Scheduled trigger; 6 nodes.
Source: https://github.com/diego-scrapeless/scrapeless-n8n-workflows/blob/main/workflows/01-serp-keyword-tracking.json — 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.
> Watch the full Youtube Video Tutorial [](https://youtu.be/Y-wUr2-UYZk)
Very straightforward workflow. It checks the Epic Games website if the HTML container with free games has changed. If it did then it will send a notification to Discord with a list of embeds containin
This workflow automatically scrapes business leads from Google Maps on a daily schedule and ensures only high-quality, unique leads are processed. New businesses are cleaned, validated, and deduplicat
Women creators, homemakers-turned-entrepreneurs, and feminine lifestyle brands who want a graceful, low-lift way to keep an eye on competitor content and spark weekly ideas.
This workflow automatically searches YouTube Data API for videos related to specific keywords, extracts channel data, filters channels based on performance metrics, and saves the results into Google S