SEO关键词排名监控与团队下降警报
这是一个Market Research领域的自动化工作流,包含 12 个节点。主要使用 Code, Cron, Wait, Slack, Filter 等节点。 使用SERP API监控SEO关键词排名并通过Slack发送下降警报
- •Slack Bot Token 或 Webhook URL
- •可能需要目标 API 的认证凭证
- •Google Sheets API 凭证
分类
{
"id": "8Pj6PSyWQCOFASKY",
"meta": {
"instanceId": "dd69efaf8212c74ad206700d104739d3329588a6f3f8381a46a481f34c9cc281",
"templateCredsSetupCompleted": true
},
"name": "SEO 关键词排名监控与团队下降警报",
"tags": [],
"nodes": [
{
"id": "85f989d7-89a1-4f71-9156-fbedc02f3b1a",
"name": "每日 SEO 检查触发器",
"type": "n8n-nodes-base.cron",
"notes": "🕐 DAILY SCHEDULER\n\nWhy this node?\n• Automatically runs SEO checks every day at 8 AM\n• Ensures consistent daily monitoring without manual intervention\n• Uses cron expression '0 8 * * *' for daily 8 AM execution\n• Essential for tracking keyword ranking changes over time\n\nWhat it does:\n• Triggers the entire SEO monitoring workflow\n• Runs Monday through Sunday automatically\n• Can be modified to run multiple times per day if needed",
"position": [
-1860,
-140
],
"parameters": {},
"typeVersion": 1
},
{
"id": "7146f49a-fc4c-4d65-8d10-3f43c9d8f6b6",
"name": "获取关键词数据库",
"type": "n8n-nodes-base.googleSheets",
"notes": "📊 KEYWORD DATABASE\n\nWhy this node?\n• Stores all keywords to monitor in one central location\n• Easy to add/remove keywords without changing workflow\n• Maintains historical ranking data for comparison\n• Allows team collaboration on keyword list management\n\nWhat it does:\n• Reads keywords, target URLs, and previous rankings\n• Provides data structure: keyword, url, previous_rank, current_rank\n• Acts as the source of truth for all SEO monitoring\n• Enables bulk processing of multiple keywords",
"position": [
-1640,
-140
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "id",
"value": "=54refghuy654e3w"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "23456yujhyt543erfgb"
},
"authentication": "serviceAccount",
"combineFilters": "AND"
},
"credentials": {
"googleApi": {
"id": "ScSS2KxGQULuPtdy",
"name": "Google Sheets- test"
}
},
"typeVersion": 4
},
{
"id": "823ab7be-aa9f-45c8-884e-cb3e54a0764c",
"name": "仅筛选活跃关键词",
"type": "n8n-nodes-base.filter",
"notes": "🔍 KEYWORD FILTER\n\nWhy this node?\n• Saves API costs by only checking active keywords\n• Prevents processing empty or disabled keyword entries\n• Allows temporary disabling of specific keyword monitoring\n• Improves workflow efficiency and performance\n\nWhat it does:\n• Filters out empty keyword fields\n• Only processes keywords marked as 'monitor_active = true'\n• Reduces unnecessary API calls to SERP services\n• Ensures clean data flow to ranking APIs",
"position": [
-1420,
-140
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "condition-1",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"leftValue": "={{ $json.keyword }}",
"rightValue": ""
},
{
"id": "condition-2",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.monitor_active }}",
"rightValue": "true"
}
]
}
},
"typeVersion": 2
},
{
"id": "c3157af6-3541-44f3-bde6-f05788aede5a",
"name": "通过 SERP API 获取 Google 排名",
"type": "n8n-nodes-base.httpRequest",
"notes": "🌐 GOOGLE RANKING FETCHER\n\nWhy this node?\n• Gets real-time Google search rankings for keywords\n• Uses SERP API to avoid Google blocking/rate limiting\n• Fetches top 100 results to catch ranking changes\n• Provides accurate, location-specific ranking data\n\nWhat it does:\n• Searches Google for each keyword\n• Returns organic search results with positions\n• Captures ranking data for specified location (US)\n• Handles Google's anti-bot measures automatically\n• Costs ~$0.001 per search (check SERP API pricing)",
"position": [
-1200,
-140
],
"parameters": {
"url": "https://serpapi.com/search",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $json.keyword }}"
},
{
"name": "location",
"value": "United States"
},
{
"name": "hl",
"value": "en"
},
{
"name": "gl",
"value": "us"
},
{
"name": "google_domain",
"value": "google.com"
},
{
"name": "api_key",
"value": "YOUR_SERPAPI_KEY"
},
{
"name": "num",
"value": "100"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"id": "KCqBydsOZHvzNKAI",
"name": "Header Auth account"
}
},
"typeVersion": 4.2
},
{
"id": "ca3e0cb8-9772-416b-8dd0-4f4beb80b87a",
"name": "解析排名并检测变化",
"type": "n8n-nodes-base.code",
"notes": "⚙️ RANKING ANALYZER\n\nWhy this node?\n• Processes complex SERP API responses into usable data\n• Finds your website's position in search results\n• Calculates ranking changes compared to previous data\n• Determines which keywords need attention/alerts\n\nWhat it does:\n• Searches through 100 organic results for your URL\n• Matches domain/subdomain to find exact ranking\n• Calculates ranking improvement/drop numbers\n• Sets alert flags for drops > 2 positions\n• Handles cases where website is not found in top 100",
"position": [
-760,
-140
],
"parameters": {
"jsCode": "// Parse SERP API response and find our website rankings\nconst items = [];\n\nfor (const item of $input.all()) {\n const serpData = item.json;\n const keyword = item.json.keyword || 'Unknown';\n const targetUrl = item.json.url || '';\n const previousRank = parseInt(item.json.previous_rank) || 0;\n \n let currentRank = null;\n let foundUrl = '';\n \n // Search through organic results\n if (serpData.organic_results && Array.isArray(serpData.organic_results)) {\n for (let i = 0; i < serpData.organic_results.length; i++) {\n const result = serpData.organic_results[i];\n const resultUrl = result.link || '';\n \n // Check if this result matches our target URL (domain matching)\n if (targetUrl && resultUrl.includes(targetUrl.replace('https://', '').replace('http://', '').split('/')[0])) {\n currentRank = result.position || (i + 1);\n foundUrl = resultUrl;\n break;\n }\n }\n }\n \n // Calculate ranking change\n const rankingChange = previousRank && currentRank ? (previousRank - currentRank) : 0;\n const rankingDrop = currentRank && previousRank ? (currentRank - previousRank) : 0;\n \n // Determine status\n let status = 'not_found';\n if (currentRank) {\n if (rankingChange > 0) status = 'improved';\n else if (rankingChange < 0) status = 'dropped';\n else status = 'stable';\n }\n \n items.push({\n json: {\n keyword: keyword,\n target_url: targetUrl,\n current_rank: currentRank,\n previous_rank: previousRank,\n ranking_change: rankingChange,\n ranking_drop: rankingDrop,\n status: status,\n found_url: foundUrl,\n check_date: new Date().toISOString().split('T')[0],\n needs_alert: rankingDrop > 2 || currentRank === null\n }\n });\n}\n\nreturn items;"
},
"typeVersion": 2
},
{
"id": "7615956e-9f02-4e10-b4f0-986439f18c10",
"name": "筛选显著排名下降",
"type": "n8n-nodes-base.filter",
"notes": "🚨 ALERT FILTER\n\nWhy this node?\n• Only sends alerts for significant ranking changes\n• Prevents spam from minor 1-2 position fluctuations\n• Focuses attention on keywords that truly need action\n• Saves notification costs and reduces alert fatigue\n\nWhat it does:\n• Filters keywords with drops > 2 positions\n• Includes keywords that disappeared from top 100\n• Passes only actionable ranking issues\n• Reduces noise in alerting system",
"position": [
-540,
-240
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "condition-1",
"operator": {
"type": "boolean",
"operation": "equals"
},
"leftValue": "={{ $json.needs_alert }}",
"rightValue": true
}
]
}
},
"typeVersion": 2
},
{
"id": "18daa200-2105-48e7-b624-571afb9e8b56",
"name": "在 Google Sheet 中更新排名",
"type": "n8n-nodes-base.googleSheets",
"notes": "📈 RANKING HISTORY TRACKER\n\nWhy this node?\n• Maintains historical ranking data for trend analysis\n• Updates previous_rank for next day's comparison\n• Creates audit trail of all ranking changes\n• Enables manual review and reporting\n\nWhat it does:\n• Updates current rankings in Google Sheet\n• Records ranking changes and status\n• Timestamps each check for historical tracking\n• Stores found URLs for verification\n• Prepares data for next day's comparison",
"position": [
-320,
60
],
"parameters": {
"columns": {
"value": {},
"schema": [],
"mappingMode": "autoMapInputData",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "=234567uijhgfds"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "234y"
},
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"id": "ScSS2KxGQULuPtdy",
"name": "Google Sheets- test"
}
},
"typeVersion": 4
},
{
"id": "317313f3-5cc6-472b-b1c4-4b020ae1a1ed",
"name": "发送 Slack 排名警报",
"type": "n8n-nodes-base.slack",
"notes": "💬 SLACK NOTIFICATION\n\nWhy this node?\n• Provides instant alerts to SEO team\n• Rich formatting shows ranking details clearly\n• Integrates with existing team communication\n• Allows immediate team discussion and action\n\nWhat it does:\n• Sends formatted alert to designated Slack channel\n• Includes keyword, ranking change, and URLs\n• Shows current vs previous ranking comparison\n• Provides actionable information for quick response\n• Can mention specific team members if needed",
"position": [
-320,
-340
],
"webhookId": "0a59f221-d7ae-44b1-acf5-a8e981ac052a",
"parameters": {
"text": "🚨 *SEO RANKING ALERT* 🚨\n\n*Keyword*: {{ $json.keyword }}\n*Current Rank*: {{ $json.current_rank || 'Not Found (>100)' }}\n*Previous Rank*: {{ $json.previous_rank }}\n*Change*: {{ $json.ranking_drop > 0 ? '📉 Dropped ' + $json.ranking_drop + ' positions' : '❓ Disappeared from top 100' }}\n*Target URL*: {{ $json.target_url }}\n*Date*: {{ $json.check_date }}\n\n{{ $json.current_rank ? '*Found URL*: ' + $json.found_url : '*Action Needed*: Check if page still exists or investigate technical issues' }}\n\n*Status*: {{ $json.status.toUpperCase() }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "id",
"value": "C1234567890"
},
"otherOptions": {}
},
"credentials": {
"slackApi": {
"id": "MQ0fgwuS8AzfwFvy",
"name": "Slack account - test "
}
},
"typeVersion": 2.1
},
{
"id": "16d01b26-bb28-4f81-ab7b-560e199b4a86",
"name": "发送邮件排名警报",
"type": "n8n-nodes-base.emailSend",
"notes": "📧 EMAIL NOTIFICATION\n\nWhy this node?\n• Provides detailed alert for serious ranking drops\n• Creates email trail for management reporting\n• Reaches team members who may not use Slack\n• Professional format suitable for stakeholder updates\n\nWhat it does:\n• Sends HTML-formatted email with ranking details\n• Includes actionable recommendations\n• Shows before/after ranking comparison\n• Provides links for immediate investigation\n• Can be forwarded to management or clients",
"position": [
-320,
-140
],
"webhookId": "8ed71888-a920-48c8-a43e-c2e0bc1165d0",
"parameters": {
"options": {},
"subject": "🚨 SEO Alert: {{ $json.keyword }} ranking dropped",
"toEmail": "seo-team@yourcompany.com",
"fromEmail": "seo-alerts@yourcompany.com"
},
"credentials": {
"smtp": {
"id": "G1kyF8cSWTZ4vouN",
"name": "SMTP -test"
}
},
"typeVersion": 2
},
{
"id": "f341f2b0-3aa7-4e32-b166-13d503f24c33",
"name": "生成 SEO 监控摘要",
"type": "n8n-nodes-base.code",
"notes": "📊 EXECUTION SUMMARY\n\nWhy this node?\n• Provides overview of daily SEO monitoring results\n• Tracks workflow performance and success metrics\n• Helps identify trends in keyword performance\n• Useful for reporting and debugging\n\nWhat it does:\n• Counts total keywords processed\n• Summarizes alerts sent and ranking changes\n• Calculates average ranking across all keywords\n• Logs detailed execution summary to console\n• Creates data for dashboard reporting\n• Confirms workflow completed successfully",
"position": [
-100,
-140
],
"parameters": {
"jsCode": "// Generate comprehensive SEO monitoring summary\nconst allItems = $input.all();\nconst processedKeywords = allItems.length;\nconst alertsSent = allItems.filter(item => item.json.needs_alert).length;\nconst improvements = allItems.filter(item => item.json.status === 'improved').length;\nconst drops = allItems.filter(item => item.json.status === 'dropped').length;\nconst stable = allItems.filter(item => item.json.status === 'stable').length;\nconst notFound = allItems.filter(item => item.json.status === 'not_found').length;\n\n// Calculate average ranking\nconst rankedKeywords = allItems.filter(item => item.json.current_rank);\nconst avgRanking = rankedKeywords.length > 0 ? \n (rankedKeywords.reduce((sum, item) => sum + item.json.current_rank, 0) / rankedKeywords.length).toFixed(1) : 'N/A';\n\n// Log detailed summary\nconsole.log('=== SEO MONITORING SUMMARY ===');\nconsole.log(`Execution Date: ${new Date().toISOString()}`);\nconsole.log(`Total Keywords Processed: ${processedKeywords}`);\nconsole.log(`Alerts Triggered: ${alertsSent}`);\nconsole.log(`Ranking Status:`);\nconsole.log(` - Improved: ${improvements}`);\nconsole.log(` - Dropped: ${drops}`);\nconsole.log(` - Stable: ${stable}`);\nconsole.log(` - Not Found: ${notFound}`);\nconsole.log(`Average Ranking: ${avgRanking}`);\nconsole.log('================================');\n\nreturn [{\n json: {\n execution_summary: {\n date: new Date().toISOString(),\n keywords_processed: processedKeywords,\n alerts_sent: alertsSent,\n improvements: improvements,\n drops: drops,\n stable: stable,\n not_found: notFound,\n average_ranking: avgRanking,\n success: true\n }\n }\n}];"
},
"typeVersion": 2
},
{
"id": "bd06a584-1291-4918-a0bf-cd2e49c548d2",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1720,
-540
],
"parameters": {
"color": 6,
"width": 800,
"height": 320,
"content": "## 工作原理"
},
"typeVersion": 1
},
{
"id": "7610d5a4-f63c-4f21-9087-ca88bac58bb1",
"name": "等待响应",
"type": "n8n-nodes-base.wait",
"position": [
-980,
-140
],
"webhookId": "d37ab414-01c6-4e2c-a02d-4c20f0adfa10",
"parameters": {},
"typeVersion": 1.1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "a5af8f36-78aa-4f02-8c09-adf5f330b315",
"connections": {
"Wait For Response": {
"main": [
[
{
"node": "Parse Rankings & Detect Changes",
"type": "main",
"index": 0
}
]
]
},
"Get Keywords Database": {
"main": [
[
{
"node": "Filter Active Keywords Only",
"type": "main",
"index": 0
}
]
]
},
"Daily SEO Check Trigger": {
"main": [
[
{
"node": "Get Keywords Database",
"type": "main",
"index": 0
}
]
]
},
"Send Email Ranking Alert": {
"main": [
[
{
"node": "Generate SEO Monitoring Summary",
"type": "main",
"index": 0
}
]
]
},
"Send Slack Ranking Alert": {
"main": [
[
{
"node": "Generate SEO Monitoring Summary",
"type": "main",
"index": 0
}
]
]
},
"Filter Active Keywords Only": {
"main": [
[
{
"node": "Fetch Google Rankings via SERP API",
"type": "main",
"index": 0
}
]
]
},
"Parse Rankings & Detect Changes": {
"main": [
[
{
"node": "Filter Significant Ranking Drops",
"type": "main",
"index": 0
},
{
"node": "Update Rankings in Google Sheet",
"type": "main",
"index": 0
}
]
]
},
"Update Rankings in Google Sheet": {
"main": [
[
{
"node": "Generate SEO Monitoring Summary",
"type": "main",
"index": 0
}
]
]
},
"Filter Significant Ranking Drops": {
"main": [
[
{
"node": "Send Slack Ranking Alert",
"type": "main",
"index": 0
},
{
"node": "Send Email Ranking Alert",
"type": "main",
"index": 0
}
]
]
},
"Fetch Google Rankings via SERP API": {
"main": [
[
{
"node": "Wait For Response",
"type": "main",
"index": 0
}
]
]
}
}
}如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
中级 - 市场调研
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
Oneclick AI Squad
@oneclick-aiThe AI Squad Initiative is a pioneering effort to build, automate and scale AI-powered workflows using n8n.io. Our mission is to help individuals and businesses integrate AI agents seamlessly into their daily operations from automating tasks and enhancing productivity to creating innovative, intelligent solutions. We design modular, reusable AI workflow templates that empower creators, developers and teams to supercharge their automation with minimal effort and maximum impact.
分享此工作流