8
n8n 中文网amn8n.com

使用GPT-4o和Google Search Console检测关键词蚕食

高级

这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 27 个节点。主要使用 If, Code, Merge, HttpRequest, GoogleSheets 等节点。 使用GPT-4o和Google Search Console检测关键词蚕食

前置要求
  • 可能需要目标 API 的认证凭证
  • Google Sheets API 凭证
  • OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "meta": {
    "instanceId": "bc8ca75c203589705ae2e446cad7181d6f2a7cc1766f958ef9f34810e53b8cb2"
  },
  "nodes": [
    {
      "id": "90168f30-8e88-4b5a-9a80-586ad28f5a8f",
      "name": "按关键词分组 GSC 数据(客户2)",
      "type": "n8n-nodes-base.code",
      "notes": "Groups Google Search Console data by keyword for Client 2. Takes raw GSC response and organizes it by keyword, with each keyword containing an array of URLs that rank for it, including position, clicks, impressions, and CTR data.",
      "position": [
        336,
        464
      ],
      "parameters": {
        "jsCode": "const grouped = {};\n\nfor (const row of items[0].json.rows) {\n  const query = row.keys[0]; // keyword\n  const url = row.keys[1];   // page\n  \n  if (!grouped[query]) grouped[query] = [];\n  \n  grouped[query].push({\n    url,\n    position: row.position,\n    clicks: row.clicks,\n    impressions: row.impressions,\n    ctr: row.ctr  // CTR added here\n  });\n}\n\n// Convert grouped object into array of items for next node\nreturn Object.entries(grouped).map(([keyword, urls]) => ({\n  json: { keyword, urls }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "866dd165-dd86-43b9-b24e-e54ade95c42c",
      "name": "按关键词分组 GSC 数据(客户3)",
      "type": "n8n-nodes-base.code",
      "notes": "Groups Google Search Console data by keyword for Client 3. Transforms the GSC API response into a keyword-centric structure where each keyword has associated URLs with their ranking metrics.",
      "position": [
        336,
        848
      ],
      "parameters": {
        "jsCode": "const grouped = {};\n\nfor (const row of items[0].json.rows) {\n  const query = row.keys[0]; // keyword\n  const url = row.keys[1];   // page\n  \n  if (!grouped[query]) grouped[query] = [];\n  \n  grouped[query].push({\n    url,\n    position: row.position,\n    clicks: row.clicks,\n    impressions: row.impressions,\n    ctr: row.ctr  // CTR added here\n  });\n}\n\n// Convert grouped object into array of items for next node\nreturn Object.entries(grouped).map(([keyword, urls]) => ({\n  json: { keyword, urls }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "e679fffe-fb2b-4cff-b5a0-104179212ac0",
      "name": "按关键词分组 GSC 数据(客户4)",
      "type": "n8n-nodes-base.code",
      "notes": "Groups Google Search Console data by keyword for Client 4. Processes raw GSC data and restructures it to group all URLs ranking for each keyword together with their performance metrics.",
      "position": [
        336,
        1040
      ],
      "parameters": {
        "jsCode": "const grouped = {};\n\nfor (const row of items[0].json.rows) {\n  const query = row.keys[0]; // keyword\n  const url = row.keys[1];   // page\n  \n  if (!grouped[query]) grouped[query] = [];\n  \n  grouped[query].push({\n    url,\n    position: row.position,\n    clicks: row.clicks,\n    impressions: row.impressions,\n    ctr: row.ctr  // CTR added here\n  });\n}\n\n// Convert grouped object into array of items for next node\nreturn Object.entries(grouped).map(([keyword, urls]) => ({\n  json: { keyword, urls }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "7f125793-0b03-4466-b25b-1ef3bb4a76d4",
      "name": "按关键词分组 GSC 数据(客户1)",
      "type": "n8n-nodes-base.code",
      "notes": "Groups Google Search Console data by keyword for Client 1. Converts the flat GSC response into a grouped structure where each keyword contains all its ranking URLs with position, clicks, impressions, and CTR.",
      "position": [
        336,
        272
      ],
      "parameters": {
        "jsCode": "const grouped = {};\n\nfor (const row of items[0].json.rows) {\n  const query = row.keys[0]; // keyword\n  const url = row.keys[1];   // page\n  \n  if (!grouped[query]) grouped[query] = [];\n  \n  grouped[query].push({\n    url,\n    position: row.position,\n    clicks: row.clicks,\n    impressions: row.impressions,\n    ctr: row.ctr  // CTR added here\n  });\n}\n\n// Convert grouped object into array of items for next node\nreturn Object.entries(grouped).map(([keyword, urls]) => ({\n  json: { keyword, urls }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "94c42a7f-50aa-48c9-9643-58eeaddd8ff8",
      "name": "合并所有客户 GSC 数据",
      "type": "n8n-nodes-base.merge",
      "notes": "Combines GSC data from all 4 clients plus the target keywords from the Google Sheet. This creates a unified dataset containing both the keyword targets and actual GSC performance data.",
      "position": [
        800,
        608
      ],
      "parameters": {
        "numberInputs": 5
      },
      "typeVersion": 3.2
    },
    {
      "id": "d79e5c22-ac7a-43f9-af04-0997fc7af3ce",
      "name": "将表格关键词与 GSC 数据匹配",
      "type": "n8n-nodes-base.code",
      "notes": "Cross-references target keywords from the Google Sheet with actual GSC performance data. Identifies which target keywords are ranking in GSC and which are missing, adding status flags for tracking.",
      "position": [
        1056,
        656
      ],
      "parameters": {
        "jsCode": "const out = [];\n\n// Step 1: Collect all Google Sheet keywords\nconst sheetKeywords = items\n  .filter(i => i.json.Targetted_Keywords) // from Sheets\n  .map(i => (i.json.Targetted_Keywords || \"\").toLowerCase().trim());\n\n// Deduplicate\nconst uniqueSheetKeywords = [...new Set(sheetKeywords)];\n\n// Step 2: Collect all GSC keywords\nconst gscData = items.filter(i => i.json.keyword);\n\n// Step 3: Match - GSC keywords found in sheet\nconst foundKeywords = new Set();\n\nfor (const item of gscData) {\n  const gscKeyword = (item.json.keyword || \"\").toLowerCase().trim();\n  \n  if (uniqueSheetKeywords.includes(gscKeyword)) {\n    foundKeywords.add(gscKeyword); // Track found keywords\n    \n    // Make sure URLs array includes CTR for each URL\n    const urlsWithCtr = (item.json.urls || []).map(urlObj => ({\n      url: urlObj.url,\n      position: urlObj.position,\n      clicks: urlObj.clicks,\n      impressions: urlObj.impressions,\n      ctr: urlObj.ctr  // CTR included here\n    }));\n    \n    out.push({\n      json: {\n        keyword: item.json.keyword,\n        urls: urlsWithCtr,\n        status: 'found_in_gsc' // Optional: to identify matched keywords\n      }\n    });\n  }\n}\n\n// Step 4: Add sheet keywords that were NOT found in GSC\nfor (const sheetKeyword of uniqueSheetKeywords) {\n  if (!foundKeywords.has(sheetKeyword)) {\n    out.push({\n      json: {\n        keyword: sheetKeyword,\n        urls: [], // No URLs since not found in GSC\n        status: 'not_found_in_gsc' // Optional: to identify missing keywords\n      }\n    });\n  }\n}\n\nreturn out;"
      },
      "typeVersion": 2
    },
    {
      "id": "2f8ae342-1586-4f0f-8cd5-d650c4a62b30",
      "name": "分析关键词蚕食风险",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "notes": "Uses AI to analyze keyword cannibalization risk by examining how many pages from the same domain rank for each keyword. Categorizes risk as High, Moderate, Low, or No risk based on page count and performance distribution.",
      "position": [
        1744,
        352
      ],
      "parameters": {
        "text": "=You are a Keyword Cannibalization Risk Detector.\n\nYou will receive:\n\n{{ $json.keyword }}\n{{ JSON.stringify($json.urls) }}\n\n\n\n\nYour Tasks:\n\nExtract the domain from each URL and group the pages by domain.\n\nFor each domain, analyze whether multiple pages are competing for the same keyword.\n\nHigh → 5 or more pages from the same domain rank for the keyword.\n\nModerate → 3 pages from the same domain rank closely in the top 10.\n\nLow → 2 pages rank, but one clearly dominates in clicks/impressions.\n\nNo → Only 1 page from that domain ranks.\n\nIf the main domain's homepage is ranking at position 1 AND other URLs from the same domain are also ranking, still classify as appropriate risk level based on total page count (don't give them No Risk just because the homepage ranks #1).\n\nIf multiple different domains rank for the same keyword, highlight cross-domain competition separately.\n\nReturn your findings in structured and concise form, showing the keyword, domains, and their respective risk levels.",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "0957bb5f-6200-40a4-a61a-002c965b53ee",
      "name": "OpenAI GPT-4o 模型",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "notes": "Provides the AI language model (GPT-4o) for the cannibalization analysis agent. Handles the natural language processing to understand keyword competition patterns.",
      "position": [
        1728,
        544
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "gpt-4o"
        },
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "503e683a-53c1-4aed-a86d-49ccdecd8b84",
      "name": "将 AI 分析解析为结构化 JSON",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "notes": "Converts the AI agent's natural language response into a structured JSON format with specific fields for keyword, domain, URLs, risk level, reasoning, observations, summary, and remediation steps.",
      "position": [
        1904,
        544
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"Keyword\": \"\",\n  \"Domain\": \"\",\n  \"URLs for Keyword\": [\n    {\n      \"url\": \"\",\n      \"position\": \"\",\n      \"clicks\": \"\",\n      \"impressions\": \"\",\n      \"ctr\": \"\"\n    }\n  ],\n  \"Risk Level\": \"\",\n  \"Reasoning\": \"\",\n  \"Observation\": \"\",\n  \"Summary\": \"\",\n  \"Remediation steps\": \"\"\n}\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "7ab77205-1560-45ae-8a94-fb088dcfa62e",
      "name": "监控关键词表格变更",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "notes": "Monitors the Keywords Google Sheet for any changes and triggers the workflow when modifications are detected. Polls every minute to ensure real-time processing of keyword updates.",
      "maxTries": 5,
      "position": [
        -944,
        656
      ],
      "parameters": {
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1256649775,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UfQvam8UhT58LSBobnyFsd3fi1dk7ilzvbQ57rFTIIo/edit#gid=1256649775",
          "cachedResultName": "Keywords"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1UfQvam8UhT58LSBobnyFsd3fi1dk7ilzvbQ57rFTIIo/edit?gid=1256649775#gid=1256649775"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1
    },
    {
      "id": "6dbee777-42fc-4576-a27b-4650af47455e",
      "name": "保存蚕食分析结果",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "Writes the final cannibalization analysis results back to Google Sheets. Updates or appends rows with risk levels, reasoning, observations, remediation steps, and all associated keyword data.",
      "position": [
        2272,
        672
      ],
      "parameters": {
        "columns": {
          "value": {
            "Data": "={{ $json.output['URLs for Keyword'].map(i => `${i.url} | Position: ${i.position} | Clicks: ${i.clicks} | Impressions: ${i.impressions} | CTR: ${i.ctr}`).join('\n') }}",
            "Date": "={{ $now.format('yyyy-MM-dd') }}",
            "Domain": "={{ $json.output.Domain }}",
            "Status": "={{ $('Match Keywords from Sheet with GSC Data').item.json.status }}",
            "Summary": "={{ $json.output.Summary }}",
            "Reasoning": "={{ $json.output.Reasoning }}",
            "Risk Level": "={{ $json.output['Risk Level'] }}",
            "Observation": "={{ $json.output.Observation }}",
            "Target page": "={{ $json.output['URLs for Keyword'].map(u => u.url).join(', ') }}\n",
            "remediation steps": "={{ $json.output['remediation steps'] }}",
            "Targetted_Keywords": "={{ $json.output.Keyword }}\n{{ $json.keyword }}"
          },
          "schema": [
            {
              "id": "Targetted_Keywords",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Targetted_Keywords",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Domain",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Domain",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Target page",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Target page",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Data",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Data",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Risk Level",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Risk Level",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reasoning",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Reasoning",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Observation",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Observation",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "remediation steps",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "remediation steps",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Targetted_Keywords"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1761789723,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UfQvam8UhT58LSBobnyFsd3fi1dk7ilzvbQ57rFTIIo/edit#gid=1761789723",
          "cachedResultName": "data"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1UfQvam8UhT58LSBobnyFsd3fi1dk7ilzvbQ57rFTIIo/edit?gid=1256649775#gid=1256649775"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "f78e179c-dedd-4d79-9f96-ab40fbe40f3f",
      "name": "路由至客户1",
      "type": "n8n-nodes-base.if",
      "notes": "Routes workflow execution to Client 1's GSC data fetching if the client website matches the specified URL pattern. Acts as a conditional switch for multi-client processing.",
      "position": [
        -288,
        288
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "9e1de819-aebf-4242-8f79-7262e422eb57",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json['Client Website'].trimStart().trimEnd() }}",
              "rightValue": "https://theshroomgroove.com/"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "executeOnce": false,
      "typeVersion": 2.2
    },
    {
      "id": "f44239f6-1831-4546-a829-2abf27d4eb2e",
      "name": "路由至客户2",
      "type": "n8n-nodes-base.if",
      "notes": "Routes workflow execution to Client 2's GSC data fetching when the client website matches the specified domain. Enables parallel processing of multiple clients.",
      "position": [
        -288,
        480
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "9e1de819-aebf-4242-8f79-7262e422eb57",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json['Client Website'].trimStart().trimEnd() }}",
              "rightValue": "grooveguide.io"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "fc7efa81-5870-4bc7-bd21-2181214976ff",
      "name": "路由至客户3",
      "type": "n8n-nodes-base.if",
      "notes": "Directs the workflow to fetch GSC data for Client 3 when the website URL matches the condition. Part of the multi-client routing logic to handle different domains.",
      "position": [
        -288,
        864
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "9e1de819-aebf-4242-8f79-7262e422eb57",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json['Client Website'].trimStart().trimEnd() }}",
              "rightValue": "https://groovegrillwellness.com/"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c91f5ab4-29a1-4f83-b570-3fdf4b3e7c1a",
      "name": "路由至客户4",
      "type": "n8n-nodes-base.if",
      "notes": "Routes to Client 4's GSC data collection process when the website URL condition is met. Completes the multi-client routing system for parallel data processing.",
      "position": [
        -288,
        1056
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "9e1de819-aebf-4242-8f79-7262e422eb57",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json['Client Website'].trimStart().trimEnd() }}",
              "rightValue": "https://example.com/"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2c0ba70f-00df-4be9-98a2-7969653e10db",
      "name": "获取客户网站 URL",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "Retrieves the list of client website URLs from the Google Sheet. This data is used to determine which clients to process and route them to their respective GSC data collection paths.",
      "position": [
        -656,
        656
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 146956146,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UfQvam8UhT58LSBobnyFsd3fi1dk7ilzvbQ57rFTIIo/edit#gid=146956146",
          "cachedResultName": "URL"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1UfQvam8UhT58LSBobnyFsd3fi1dk7ilzvbQ57rFTIIo",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UfQvam8UhT58LSBobnyFsd3fi1dk7ilzvbQ57rFTIIo/edit?usp=drivesdk",
          "cachedResultName": "Client URLs"
        }
      },
      "executeOnce": false,
      "typeVersion": 4.7
    },
    {
      "id": "a6a60ba4-3b48-4750-af64-bf19c22f6b5c",
      "name": "从表格获取目标关键词",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "Reads the target keywords from the Google Sheet that need to be analyzed for cannibalization. These keywords serve as the reference list to match against actual GSC performance data.",
      "position": [
        -288,
        656
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1256649775,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UfQvam8UhT58LSBobnyFsd3fi1dk7ilzvbQ57rFTIIo/edit#gid=1256649775",
          "cachedResultName": "Keywords"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1UfQvam8UhT58LSBobnyFsd3fi1dk7ilzvbQ57rFTIIo",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UfQvam8UhT58LSBobnyFsd3fi1dk7ilzvbQ57rFTIIo/edit?usp=drivesdk",
          "cachedResultName": "Client URLs"
        }
      },
      "executeOnce": true,
      "typeVersion": 4.7
    },
    {
      "id": "5a72cf8f-cf73-4811-9b55-807f7966e826",
      "name": "获取 GSC 数据(客户1)",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Makes API call to Google Search Console for Client 1 to retrieve the last 30 days of search performance data. Gets keyword-page combinations with position, clicks, impressions, and CTR metrics.",
      "onError": "continueRegularOutput",
      "position": [
        48,
        272
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($json['Client Website']) }}/searchAnalytics/query",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"startDate\": \"{{ $now.minus(30, 'days').format('yyyy-MM-dd') }}\",\n  \"endDate\": \"{{ $now.format('yyyy-MM-dd') }}\",\n  \"dimensions\": [\"query\", \"page\"]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "03e271fe-0bfd-4f75-85af-cfdf0bcb8ac0",
      "name": "筛选在 GSC 中找到的关键词",
      "type": "n8n-nodes-base.if",
      "notes": "Filters out keywords that were not found in GSC data, only passing through keywords that actually have ranking performance data. Prevents AI analysis of keywords with no GSC presence.",
      "position": [
        1424,
        656
      ],
      "parameters": {
        "options": {
          "ignoreCase": true
        },
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ccec25a9-75f6-4c82-a93f-aafb28aa3633",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "not_found_in_gsc"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "df3c0be2-7000-4821-8eb2-bbd9fee541f6",
      "name": "获取 GSC 数据(客户2)",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Retrieves Google Search Console data for Client 2 using domain property format. Collects 30 days of search analytics data including keywords, pages, positions, and engagement metrics.",
      "onError": "continueRegularOutput",
      "position": [
        48,
        464
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/webmasters/v3/sites/sc-domain:{{ $json['Client Website'] }}/searchAnalytics/query",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"startDate\": \"{{ $now.minus(30, 'days').format('yyyy-MM-dd') }}\",\n  \"endDate\": \"{{ $now.format('yyyy-MM-dd') }}\",\n  \"dimensions\": [\"query\", \"page\"]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "88d5018c-546f-4299-9ad9-d77065450cb6",
      "name": "获取 GSC 数据(客户3)",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Connects to Google Search Console API for Client 3 to extract search performance data. Gathers keyword rankings, page URLs, positions, clicks, impressions, and CTR for the past 30 days.",
      "onError": "continueRegularOutput",
      "position": [
        48,
        848
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($json['Client Website']) }}/searchAnalytics/query",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"startDate\": \"{{ $now.minus(30, 'days').format('yyyy-MM-dd') }}\",\n  \"endDate\": \"{{ $now.format('yyyy-MM-dd') }}\",\n  \"dimensions\": [\"query\", \"page\"]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "a7f0a16a-ca27-4bb2-b5ba-5b74759f5f70",
      "name": "获取 GSC 数据(客户4)",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Pulls Google Search Console analytics data for Client 4 covering the last 30 days. Retrieves comprehensive search performance metrics including keyword-page relationships and ranking positions.",
      "onError": "continueRegularOutput",
      "position": [
        48,
        1040
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($json['Client Website']) }}/searchAnalytics/query",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"startDate\": \"{{ $now.minus(30, 'days').format('yyyy-MM-dd') }}\",\n  \"endDate\": \"{{ $now.format('yyyy-MM-dd') }}\",\n  \"dimensions\": [\"query\", \"page\"]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "9d911368-b656-4519-8a24-36220cb9f4e0",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1008,
        416
      ],
      "parameters": {
        "width": 480,
        "height": 416,
        "content": "## 监控关键词表格变更"
      },
      "typeVersion": 1
    },
    {
      "id": "ddd27041-06de-475b-bb47-2d1a6032be6c",
      "name": "便签 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        -48
      ],
      "parameters": {
        "width": 656,
        "height": 1248,
        "content": "## 获取 GSC 数据(客户1-4)"
      },
      "typeVersion": 1
    },
    {
      "id": "581173a3-79e0-415d-99d2-a971bb5318d1",
      "name": "便签 4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        992,
        368
      ],
      "parameters": {
        "height": 448,
        "content": "## 将表格关键词与 GSC 数据匹配"
      },
      "typeVersion": 1
    },
    {
      "id": "f6343388-a09f-433d-94dc-a6c7d9195eec",
      "name": "便签 5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1360,
        64
      ],
      "parameters": {
        "width": 1104,
        "height": 816,
        "content": "## 筛选在 GSC 中找到的关键词"
      },
      "typeVersion": 1
    },
    {
      "id": "2e15b4f3-f8ac-41f6-a50f-beb2af6f384d",
      "name": "便签 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1664,
        64
      ],
      "parameters": {
        "width": 432,
        "height": 1040,
        "content": "## 关键词蚕食检测工作流摘要"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "Route to Client 1": {
      "main": [
        [
          {
            "node": "Fetch GSC Data (Client 1)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route to Client 2": {
      "main": [
        [
          {
            "node": "Fetch GSC Data (Client 2)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route to Client 3": {
      "main": [
        [
          {
            "node": "Fetch GSC Data (Client 3)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route to Client 4": {
      "main": [
        [
          {
            "node": "Fetch GSC Data (Client 4)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI GPT-4o Model": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze Keyword Cannibalization Risk",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Client Website URLs": {
      "main": [
        [
          {
            "node": "Route to Client 1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Route to Client 2",
            "type": "main",
            "index": 0
          },
          {
            "node": "Route to Client 3",
            "type": "main",
            "index": 0
          },
          {
            "node": "Route to Client 4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch GSC Data (Client 1)": {
      "main": [
        [
          {
            "node": "Group GSC Data by Keyword (Client 1)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch GSC Data (Client 2)": {
      "main": [
        [
          {
            "node": "Group GSC Data by Keyword (Client 2)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch GSC Data (Client 3)": {
      "main": [
        [
          {
            "node": "Group GSC Data by Keyword (Client 3)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch GSC Data (Client 4)": {
      "main": [
        [
          {
            "node": "Group GSC Data by Keyword (Client 4)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge All Client GSC Data": {
      "main": [
        [
          {
            "node": "Match Keywords from Sheet with GSC Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Keywords Found in GSC": {
      "main": [
        [
          {
            "node": "Analyze Keyword Cannibalization Risk",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Save Cannibalization Analysis Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Target Keywords from Sheet": {
      "main": [
        [
          {
            "node": "Merge All Client GSC Data",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Monitor Keywords Sheet for Changes": {
      "main": [
        [
          {
            "node": "Fetch Client Website URLs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Target Keywords from Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Keyword Cannibalization Risk": {
      "main": [
        [
          {
            "node": "Save Cannibalization Analysis Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Group GSC Data by Keyword (Client 1)": {
      "main": [
        [
          {
            "node": "Merge All Client GSC Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Group GSC Data by Keyword (Client 2)": {
      "main": [
        [
          {
            "node": "Merge All Client GSC Data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Group GSC Data by Keyword (Client 3)": {
      "main": [
        [
          {
            "node": "Merge All Client GSC Data",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "Group GSC Data by Keyword (Client 4)": {
      "main": [
        [
          {
            "node": "Merge All Client GSC Data",
            "type": "main",
            "index": 4
          }
        ]
      ]
    },
    "Parse AI Analysis to Structured JSON": {
      "ai_outputParser": [
        [
          {
            "node": "Analyze Keyword Cannibalization Risk",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Match Keywords from Sheet with GSC Data": {
      "main": [
        [
          {
            "node": "Filter Keywords Found in GSC",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

高级 - 内容创作, 多模态 AI

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量27
分类2
节点类型10
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

外部链接
在 n8n.io 查看

分享此工作流