This workflow corresponds to n8n.io template #13508 — we link there as the canonical source.
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": "u5DTLhj1aXL96lC6",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Pull competitor\u2019s ranked keywords and run gap analysis in Notion with DataForSEO",
"tags": [],
"nodes": [
{
"id": "1cc0b04a-0a69-4992-acbe-ec02cb006cef",
"name": "When clicking \u2018Execute workflow\u2019",
"type": "n8n-nodes-base.manualTrigger",
"position": [
0,
-64
],
"parameters": {},
"typeVersion": 1
},
{
"id": "78e14978-f5fd-4e6c-9448-e9d29948d22c",
"name": "Create a database page",
"type": "n8n-nodes-base.notion",
"position": [
1552,
-64
],
"parameters": {
"options": {},
"resource": "databasePage",
"databaseId": {
"__rl": true,
"mode": "list",
"value": "2f6a8ae5-ccb4-8020-9cec-def2626d321a",
"cachedResultUrl": "https://www.notion.so/2f6a8ae5ccb480209cecdef2626d321a",
"cachedResultName": "Competitor"
},
"propertiesUi": {
"propertyValues": [
{
"key": "Competitor\u2019s Ranked Keyword|title",
"title": "={{ $('Split out (competitor keywords)').item.json.keyword_data.keyword }}"
},
{
"key": "Keyword\u2019s Search Volume|number",
"numberValue": "={{ $('Split out (competitor keywords)').item.json.keyword_data.keyword_info.search_volume }}"
},
{
"key": "Competitor\u2019s Position|number",
"numberValue": "={{ $('Split out (competitor keywords)').item.json.ranked_serp_element.serp_item.rank_group }}"
},
{
"key": "Competitor\u2019s URL|url",
"urlValue": "={{ $('Split out (competitor keywords)').item.json.ranked_serp_element.serp_item.url }}",
"ignoreIfEmpty": true
},
{
"key": "Keyword\u2019s Competition|number",
"numberValue": "={{ $('Split out (competitor keywords)').item.json.keyword_data.keyword_info.competition }}"
}
]
}
},
"credentials": {
"notionApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "4605a7bf-cef5-456e-8dd0-40761af6580d",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-432,
-400
],
"parameters": {
"width": 384,
"height": 768,
"content": "This workflow uses the DataForSEO APIs to perform a ranked keyword gap analysis between your website and a competitor. It pulls the top 100 organic keywords for both domains, identifies keywords your competitor ranks for but you don\u2019t, and saves your keyword opportunities into a Notion database. \n\nOnce the data is stored, you can use Notion AI to turn this keyword gap data into an actionable content plan. Recommended prompt: \u201cAnalyse the keywords present in this table - this is the keyword gap between my website\u2019s page {{my url}} and the competitor\u2019s URL listed in the table, and based on this data, build a content strategy for me.\u201d\n\n## How it works\n1. Triggers manually on demand.\n2. Fetches the top 100 ranked keywords for your site via DataForSEO Labs API.\n3. Fetches the competitor\u2019s top-ranked keywords from the same API.\n4. Compares both datasets to find keywords missing for your domain.\n5. Extracts key metrics, including SV, competition, rank, and ranking URL.\n6. Writes all keyword gap opportunities into a Notion database.\n\n## Setup steps\n1. Select your spreadsheets with keywords and target domains.\n2. Create or select your DataForSEO connection (use [your API login and password](https://app.dataforseo.com/api-access)).\n3. Indicate your and your competitor\u2019s websites or pages.\n4. Create a Notion connection, and select a page with your database.\n"
},
"typeVersion": 1
},
{
"id": "21c16fd0-04b5-4825-a90b-1bf49efc9ac2",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
144,
-288
],
"parameters": {
"color": 6,
"width": 416,
"height": 432,
"content": "## Get my ranked keywords\nCreate a DataForSEO connection and set up Your target website/page, location, language and additional parameters if needed."
},
"typeVersion": 1
},
{
"id": "56f2a704-d9ba-400e-a92e-08b71c12742f",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
576,
-288
],
"parameters": {
"color": 6,
"width": 288,
"height": 432,
"content": "## Get my competitor\u2019s ranked keywords\nSelect a DataForSEO connection, set up a Competitor website/page, and specify additional parameters if needed."
},
"typeVersion": 1
},
{
"id": "fc6a65a7-404a-48a5-a3e8-96ee3edb07f5",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
880,
-288
],
"parameters": {
"color": 6,
"width": 816,
"height": 432,
"content": "## Find keyword gaps and log the opportunities in Notion\nCreate a Notion connection. Create a Page with a database containing the following recommended fields: Competitor's Ranked Keyword, Keyword Search Volume, Keyword Competition, Competitor's Position, Competitor's URL.\n\nSet up values for your fields:\n{{ $('Split Out').item.json.keyword_data.keyword }} for Competitor's Ranked Keyword;\n{{ $('Split Out').item.json.keyword_data.keyword_info.search_volume }} for Keyword Search Volume;\n{{ $('Split Out').item.json.ranked_serp_element.serp_item.rank_group }} for Keyword Competition;\n{{ $('Split Out').item.json.ranked_serp_element.serp_item.url }} for Competitor's Position \n{{ $('Split Out').item.json.keyword_data.keyword_info.competition }} for Competitor's URL\n"
},
"typeVersion": 1
},
{
"id": "6288120d-ebf8-457f-9b13-4421c29027d7",
"name": "Split out (competitor keywords)",
"type": "n8n-nodes-base.splitOut",
"position": [
1008,
-64
],
"parameters": {
"options": {},
"fieldToSplitOut": "tasks[0].result[0].items"
},
"typeVersion": 1
},
{
"id": "3f47ad30-4a5a-4d40-bb48-df1223941a76",
"name": "Filter (My site doesn't have keyword)",
"type": "n8n-nodes-base.filter",
"position": [
1280,
-64
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "d3fd5e11-f97f-436a-93b8-ff8f1b04f488",
"operator": {
"type": "array",
"operation": "notContains",
"rightType": "any"
},
"leftValue": "={{ $('Edit fields (myKeywords)').item.json.myKeywords }}",
"rightValue": "={{ $json.keyword_data.keyword }}"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "b76520b3-08f5-450d-b439-09e034641352",
"name": "Get my ranked keywords",
"type": "n8n-nodes-dataforseo.dataForSeoLabsApi",
"position": [
224,
-64
],
"parameters": {
"offset": "=",
"operation": "get-ranked-keywords",
"target_any": "https://dataforseo.com/apis/serp-api",
"language_name": "english",
"location_name": "united states"
},
"credentials": {
"dataForSeoApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "8524e41c-2a7a-4be7-b212-c7b6504e1b98",
"name": "Get my competitor\u2019s ranked keywords",
"type": "n8n-nodes-dataforseo.dataForSeoLabsApi",
"position": [
672,
-64
],
"parameters": {
"offset": "=0",
"operation": "get-ranked-keywords",
"target_any": "=https://serpapi.com/",
"language_name": "={{ $('Get my ranked keywords').item.json.tasks[0].data.language_name }}",
"location_name": "={{ $('Get my ranked keywords').item.json.tasks[0].data.location_name }}"
},
"credentials": {
"dataForSeoApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "59b133fb-ed42-44c9-abc4-f2a9c8d5bd03",
"name": "Edit fields (myKeywords)",
"type": "n8n-nodes-base.set",
"position": [
416,
-64
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "c8e2361a-2e8d-4044-9114-703cd7d66192",
"name": "myKeywords",
"type": "array",
"value": "={{ $('Get my ranked keywords').item.json.tasks[0].result[0].items.map(item => item.keyword_data.keyword) }}"
}
]
}
},
"typeVersion": 3.4
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "e4e24dff-a95a-4d08-b990-d455aa2555ca",
"connections": {
"Get my ranked keywords": {
"main": [
[
{
"node": "Edit fields (myKeywords)",
"type": "main",
"index": 0
}
]
]
},
"Edit fields (myKeywords)": {
"main": [
[
{
"node": "Get my competitor\u2019s ranked keywords",
"type": "main",
"index": 0
}
]
]
},
"Split out (competitor keywords)": {
"main": [
[
{
"node": "Filter (My site doesn't have keyword)",
"type": "main",
"index": 0
}
]
]
},
"When clicking \u2018Execute workflow\u2019": {
"main": [
[
{
"node": "Get my ranked keywords",
"type": "main",
"index": 0
}
]
]
},
"Filter (My site doesn't have keyword)": {
"main": [
[
{
"node": "Create a database page",
"type": "main",
"index": 0
}
]
]
},
"Get my competitor\u2019s ranked keywords": {
"main": [
[
{
"node": "Split out (competitor keywords)",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
dataForSeoApinotionApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow helps you discover new SEO content opportunities by automatically identifying keyword gaps between your website and a competing domain.
Source: https://n8n.io/workflows/13508/ — 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.
Workflow 01.01. Uses notion, executeWorkflowTrigger, httpRequest. Event-driven trigger; 60 nodes.
Automate sales call analysis and store structured insights in Notion with AI-powered intelligence.
Inspired by Alex Kim's workflow, this version adds the ability to keep multiple versions of the same workflow on the destination instance. Each copied workflow’s name is prefixed with the date (), ena
Everyone organizing him/herself by using a notion database for tasks but losing track on some important tasks having a deadline. The weekly reminder helps you to not forget about your notion tasks. Th
WorkFlow 01.02. Uses notion, httpRequest, executeWorkflowTrigger. Event-driven trigger; 27 nodes.