{
  "id": "1I7RKPlTB5dbxc71",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Pull new keywords ranked in Google\u2019s top-10 into Airtable with DataForSEO",
  "tags": [],
  "nodes": [
    {
      "id": "71b5d365-4f62-4903-b199-1a4ce9329bc3",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1248,
        64
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "6d88155f-060a-4fc9-81a6-00d3d9a69293",
      "name": "Get ranked keywords",
      "type": "n8n-nodes-dataforseo.dataForSeoLabsApi",
      "position": [
        640,
        368
      ],
      "parameters": {
        "limit": 1000,
        "offset": "={{ $runIndex * 1000 }}",
        "filters": "[\"ranked_serp_element.serp_item.rank_absolute\", \"<=\", 10]",
        "operation": "get-ranked-keywords",
        "target_any": "={{ $('Search Targets').item.json.Domain }}",
        "language_name": "={{ $('Search Targets').item.json.Language }}",
        "location_name": "={{ $('Search Targets').item.json.Location }}"
      },
      "credentials": {
        "dataForSeoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d9e9828f-c00e-44da-b0b9-bb0a533513dd",
      "name": "Find new keywords",
      "type": "n8n-nodes-base.code",
      "position": [
        768,
        832
      ],
      "parameters": {
        "jsCode": "let oldKeywords = new Set([]);\nif ($('Aggregate').first().json.data) {\n oldKeywords = new Set($('Aggregate').first().json.data\n  .filter(item => item.target == $('Search Targets').first().json.Domain)\n  .map(item => item.keyword));\n}\n\nlet newKeywords = [];\nif ($('Merge \"items\" with last response').first().json.items) {\n newKeywords = $('Merge \"items\" with last response').first().json.items\n  .map(item => item.keyword_data.keyword);\n}\n\nlet diff;\nif (oldKeywords.size > 0) {\n  diff = newKeywords.filter(x => !oldKeywords.has(x));\n} else {\n  diff = [];\n}\n\nreturn [\n  {\n    json: {\n      diff\n    }\n  }\n];"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "7304aa30-f78a-4c08-a221-ea3133cc6846",
      "name": "Run every Monday",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        64
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "80de1cbe-b149-4076-8ab0-48659916a1d7",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -624,
        80
      ],
      "parameters": {
        "width": 480,
        "height": 528,
        "content": "This workflow uses the DataForSEO Labs API to detect new search queries for which your domain(s) started ranking in Google\u2019s top 10 results. Newly discovered keywords are recorded in Airtable, and a short overview is sent to you in a Slack notification.\n\n## How it works\n1. Runs on a predefined schedule (default: weekly).\n2. Reads your keywords and target domains from Airtable.\n3. Fetches the latest Google rankings and keyword metrics via DataForSEO API.\n4. Compares the latest data with the previous run.\n5. Logs new top-10 ranked keywords to Airtable.\n6. Sends a Slack summary with key changes.\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).\n3. Create a Slack connection and choose who will receive the notification.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "558f72a0-2fa4-4af4-af7e-6c11ccba322f",
      "name": "Aggregate1",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        544,
        832
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "89a179f1-20e1-43b8-8789-fa3746618a16",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        848,
        64
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "717cbba9-ee71-4041-82ee-c4c01325a935",
      "name": "Search keywords",
      "type": "n8n-nodes-base.airtable",
      "position": [
        208,
        64
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appZWQrfNksZ6S36L",
          "cachedResultUrl": "https://airtable.com/appZWQrfNksZ6S36L",
          "cachedResultName": "Integrations"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblNstvG3A4NPvYSn",
          "cachedResultUrl": "https://airtable.com/appZWQrfNksZ6S36L/tblNstvG3A4NPvYSn",
          "cachedResultName": "Ranked Keywords"
        },
        "options": {},
        "operation": "search"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "notesInFlow": false,
      "typeVersion": 2.1,
      "alwaysOutputData": true
    },
    {
      "id": "9603f932-c8cc-46fa-99b7-9f704bea714d",
      "name": "Search Targets",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1488,
        64
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appZWQrfNksZ6S36L",
          "cachedResultUrl": "https://airtable.com/appZWQrfNksZ6S36L",
          "cachedResultName": "Integrations"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblW8RaNBF4vKrWV1",
          "cachedResultUrl": "https://airtable.com/appZWQrfNksZ6S36L/tblW8RaNBF4vKrWV1",
          "cachedResultName": "Targets (Ranked Keywords)"
        },
        "options": {},
        "operation": "search"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "34fc39a2-9fa9-471f-b7b3-aa6a28dc251d",
      "name": "Create a record (keyword)",
      "type": "n8n-nodes-base.airtable",
      "position": [
        336,
        832
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appZWQrfNksZ6S36L",
          "cachedResultUrl": "https://airtable.com/appZWQrfNksZ6S36L",
          "cachedResultName": "Integrations"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblNstvG3A4NPvYSn",
          "cachedResultUrl": "https://airtable.com/appZWQrfNksZ6S36L/tblNstvG3A4NPvYSn",
          "cachedResultName": "Ranked Keywords"
        },
        "columns": {
          "value": {
            "Url": "={{ $json.ranked_serp_element.serp_item.url }}",
            "Date": "={{ new Date().toLocaleDateString('ISO') }}",
            "Rank": "={{ $json.ranked_serp_element.serp_item.rank_absolute }}",
            "Intent": "={{ $json.keyword_data.search_intent_info.main_intent }}",
            "Target": "={{ $('Search Targets').item.json.Domain }}",
            "Keyword": "={{ $json.keyword_data.keyword }}",
            "Search Volume": "={{ $json.keyword_data.keyword_info.search_volume }}"
          },
          "schema": [
            {
              "id": "Keyword",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Keyword",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Target",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Target",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date",
              "type": "dateTime",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Url",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Search Volume",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Search Volume",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Intent",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Intent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Rank",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Rank",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "create"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "d759be6a-add6-4a82-9874-07625f720bae",
      "name": "Send a message",
      "type": "n8n-nodes-base.slack",
      "position": [
        1200,
        832
      ],
      "parameters": {
        "text": "=New keywords ranking in the top-10 Google's results for target {{ $('Search Targets').item.json.Domain }}:{{ $json.diff.join(', ') }} . See the full list in Airtable.",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "7b9567dd-6923-4443-bfb9-2a3599d6f766",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        -160
      ],
      "parameters": {
        "color": 6,
        "width": 1216,
        "height": 384,
        "content": "## Get previous keywords and clear the table\nSelect your table with Ranked Keywords. The table is expected to have these columns: Keyword, Target, Date, URL, Search Volume, Intent, Rank.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1c9d9a45-36a1-4564-b32d-b577beb4da6a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1392,
        -160
      ],
      "parameters": {
        "color": 6,
        "width": 224,
        "height": 384,
        "content": "## Get targets\nSelect your table with targets. The table is expected to have these columns: Domain, Location, and Language."
      },
      "typeVersion": 1
    },
    {
      "id": "66138377-9651-400c-b366-2560fb417655",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        288
      ],
      "parameters": {
        "color": 6,
        "width": 1328,
        "height": 320,
        "content": "## Getn new keywords ranked in Google\u2019s top 10 results with DataForSEO\nCreate a DataForSEO connection and set up additional parameters if needed."
      },
      "typeVersion": 1
    },
    {
      "id": "528f3be8-7a89-4689-94b8-5136d9a23acf",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        688
      ],
      "parameters": {
        "color": 6,
        "width": 1216,
        "height": 320,
        "content": "## Save keywords ranked in Google\u2019s top 10 results to Airtable and send new keywords to Slack\nSelect your table with Ranked Keywords. \nCreate a Slack connection and set a receiver. Add additional information to the message if needed."
      },
      "typeVersion": 1
    },
    {
      "id": "e1bbf7f7-a2cf-4204-b25a-e5e525444915",
      "name": "If (table is not empty)",
      "type": "n8n-nodes-base.if",
      "position": [
        416,
        64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b304537e-1c71-4ad0-a5c5-d06d803ec76e",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "8ff1ff0e-36b9-49c0-b7f3-70293b73f443",
      "name": "Set \"keyword\" and \"target\" fields",
      "type": "n8n-nodes-base.set",
      "position": [
        1056,
        64
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "77cf5114-b977-4f23-aa4d-4245158d6198",
              "name": "keyword",
              "type": "string",
              "value": "={{ $('Search keywords').item.json.Keyword }}"
            },
            {
              "id": "59472bbb-72fc-4c3b-ae25-6379286672e9",
              "name": "target",
              "type": "string",
              "value": "={{ $('Search keywords').item.json.Target }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6330ff02-0863-4f42-96dd-1434a6be4e77",
      "name": "Initialize \"items\" field",
      "type": "n8n-nodes-base.set",
      "position": [
        208,
        432
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0126c659-03a5-4fc8-bd76-62d2ecea1195",
              "name": "items",
              "type": "array",
              "value": "={{ [] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8d25a8cd-ecbc-4d64-b9eb-c7f391e1a4c7",
      "name": "Set \"items\" field",
      "type": "n8n-nodes-base.set",
      "position": [
        432,
        432
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4b3c95a2-4e38-4e37-8e2f-a7e4544808d6",
              "name": "items",
              "type": "array",
              "value": "={{ $json.items }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "77e866ef-b079-43c3-a10d-4756301b4c8f",
      "name": "Merge \"items\" with DFS response",
      "type": "n8n-nodes-base.set",
      "position": [
        880,
        368
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ddd82419-e43e-44d8-919c-2d6602704da5",
              "name": "items",
              "type": "array",
              "value": "={{ [ ...$('Set \"items\" field').item.json.items, ...$json.tasks[0].result[0].items] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "26c73414-e804-44e9-b086-514f33f06d5c",
      "name": "Has more pages?",
      "type": "n8n-nodes-base.if",
      "position": [
        1104,
        432
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cd5943f7-df0b-4329-8436-9a1af3ec7caf",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "leftValue": "={{ $runIndex }}",
              "rightValue": "={{ $('Get ranked keywords').item.json.tasks[0].result[0].total_count / 1000 - 1}}"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "27b6e975-0952-4a14-af56-1e9c4884d0cf",
      "name": "Merge \"items\" with last response",
      "type": "n8n-nodes-base.set",
      "position": [
        1344,
        448
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "1e2c8353-5628-4948-abe6-35f8d0f660a5",
              "name": "items",
              "type": "array",
              "value": "={{ [...$('Set \"items\" field').item.json.items, ... $('Get ranked keywords').item.json.tasks[0].result[0].items]}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e504f014-b4a1-40fb-ae18-a487fa02e02d",
      "name": "Split out (items)",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        112,
        832
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "items"
      },
      "typeVersion": 1
    },
    {
      "id": "f6dad49f-79c4-47e0-8893-c013777bc68f",
      "name": "Filter (has new keywords)",
      "type": "n8n-nodes-base.filter",
      "position": [
        976,
        832
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "db27673e-4291-4e64-b92e-bf5fac8fcc05",
              "operator": {
                "type": "array",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.diff }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "616e6cac-a903-4b78-8173-885605c0d487",
      "name": "Delete keyword",
      "type": "n8n-nodes-base.airtable",
      "position": [
        624,
        -48
      ],
      "parameters": {
        "id": "={{ $json.id }}",
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appZWQrfNksZ6S36L",
          "cachedResultUrl": "https://airtable.com/appZWQrfNksZ6S36L",
          "cachedResultName": "Integrations"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblNstvG3A4NPvYSn",
          "cachedResultUrl": "https://airtable.com/appZWQrfNksZ6S36L/tblNstvG3A4NPvYSn",
          "cachedResultName": "Ranked Keywords"
        },
        "operation": "deleteRecord"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "c2654833-b498-4c94-bdea-41bae7523be3",
      "name": "Loop over targets",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -16,
        416
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "f478af01-bdde-40fc-877a-39bff1c43b89",
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Set \"keyword\" and \"target\" fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Search Targets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate1": {
      "main": [
        [
          {
            "node": "Find new keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Delete keyword": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Targets": {
      "main": [
        [
          {
            "node": "Loop over targets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send a message": {
      "main": [
        [
          {
            "node": "Loop over targets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has more pages?": {
      "main": [
        [
          {
            "node": "Set \"items\" field",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge \"items\" with last response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search keywords": {
      "main": [
        [
          {
            "node": "If (table is not empty)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run every Monday": {
      "main": [
        [
          {
            "node": "Search keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find new keywords": {
      "main": [
        [
          {
            "node": "Filter (has new keywords)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop over targets": {
      "main": [
        [],
        [
          {
            "node": "Initialize \"items\" field",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set \"items\" field": {
      "main": [
        [
          {
            "node": "Get ranked keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split out (items)": {
      "main": [
        [
          {
            "node": "Create a record (keyword)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get ranked keywords": {
      "main": [
        [
          {
            "node": "Merge \"items\" with DFS response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If (table is not empty)": {
      "main": [
        [
          {
            "node": "Delete keyword",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Initialize \"items\" field": {
      "main": [
        [
          {
            "node": "Set \"items\" field",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create a record (keyword)": {
      "main": [
        [
          {
            "node": "Aggregate1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter (has new keywords)": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge \"items\" with DFS response": {
      "main": [
        [
          {
            "node": "Has more pages?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge \"items\" with last response": {
      "main": [
        [
          {
            "node": "Split out (items)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set \"keyword\" and \"target\" fields": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}