{
  "id": "",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "name": "Research keywords for content ideas with SE Ranking",
  "tags": [],
  "nodes": [
    {
      "id": "142c3916-8a3b-42e6-9cff-d85e0ebe9678",
      "name": "When clicking 'Execute workflow'",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        4816,
        2256
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "66a11c08-8d6d-4a26-af10-c3c27569b88b",
      "name": "Get longtail keywords",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        5200,
        1776
      ],
      "parameters": {
        "keyword": "digital marketing",
        "resource": "keywordResearch",
        "operation": "getLongtail",
        "additionalFields": {
          "limit": 50
        }
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "ba8a180d-222e-4bfa-8877-6b101d4f3383",
      "name": "Get question keywords",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        5184,
        2064
      ],
      "parameters": {
        "keyword": "digital marketing",
        "resource": "keywordResearch",
        "operation": "getQuestions",
        "additionalFields": {
          "limit": 50,
          "volumeFrom": 500,
          "difficultyTo": 50,
          "historyTrend": true
        }
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8b6e5354-3fe8-4df4-a359-6ad65ce50570",
      "name": "Get similar keywords",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        5136,
        2336
      ],
      "parameters": {
        "keyword": "digital marketing",
        "resource": "keywordResearch",
        "operation": "getSimilar",
        "additionalFields": {
          "limit": 50,
          "volumeFrom": 500,
          "difficultyTo": 50,
          "historyTrend": true
        }
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f88dbe26-3126-45ab-8d7a-2dd0c0af607c",
      "name": "Get related keywords",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        5136,
        2624
      ],
      "parameters": {
        "keyword": "digital marketing",
        "resource": "keywordResearch",
        "operation": "getRelated",
        "additionalFields": {
          "limit": 50,
          "volumeFrom": 500,
          "difficultyTo": 50,
          "historyTrend": true
        }
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c3934474-713b-4cd0-83a3-3b3a279aa41d",
      "name": "Merge all keyword types",
      "type": "n8n-nodes-base.merge",
      "position": [
        5456,
        2256
      ],
      "parameters": {
        "numberInputs": 4
      },
      "typeVersion": 3
    },
    {
      "id": "9e937807-6e2e-43f2-a1d3-9952528518f4",
      "name": "Analyze & Score Keywords for Content",
      "type": "n8n-nodes-base.code",
      "position": [
        5680,
        2256
      ],
      "parameters": {
        "jsCode": "// Content Generation Keyword Analyzer\nconst allInput = $input.all();\nconst timestamp = new Date().toISOString().split('T')[0];\nlet allKeywords = [];\nconst seenKeywords = new Set();\n\n// Extract and deduplicate keywords from all sources\nallInput.forEach((item, sectionIndex) => {\n  const section = item.json;\n  \n  if (!section || !section.keywords || !Array.isArray(section.keywords)) {\n    return;\n  }\n  \n  section.keywords.forEach(kw => {\n    // Handle both string and object keyword formats\n    const keywordText = typeof kw === 'string' ? kw : kw.keyword;\n    const keywordLower = keywordText.toLowerCase().trim();\n    \n    // Skip duplicates\n    if (seenKeywords.has(keywordLower)) {\n      return;\n    }\n    seenKeywords.add(keywordLower);\n    \n    // For object keywords with full metrics\n    if (typeof kw === 'object' && kw.keyword) {\n      // Calculate opportunity score (0-100)\n      const volumeScore = Math.min((kw.volume || 0) / 10000, 1) * 40;\n      const difficultyScore = (100 - (kw.difficulty || 0)) / 100 * 40;\n      const cpcScore = Math.min((kw.cpc || 0) / 20, 1) * 20;\n      const opportunityScore = Math.round(volumeScore + difficultyScore + cpcScore);\n      \n      // Determine search intent\n      let intent = 'informational';\n      const kwText = keywordText.toLowerCase();\n      \n      if (kwText.match(/\\\\b(buy|purchase|price|cost|cheap|deal|discount|order)\\\\b/)) {\n        intent = 'transactional';\n      } else if (kwText.match(/\\\\b(best|top|review|vs|versus|compare|alternative)\\\\b/)) {\n        intent = 'commercial';\n      } else if (kwText.match(/\\\\b(how|what|why|when|where|guide|tutorial|tips|learn)\\\\b/)) {\n        intent = 'informational';\n      } else if (kwText.match(/\\\\b(login|sign up|download|free trial|official)\\\\b/)) {\n        intent = 'navigational';\n      }\n      \n      // Suggest content type\n      let contentType = 'blog post';\n      \n      if (kwText.startsWith('how to') || kwText.includes('step by step')) {\n        contentType = 'how-to guide';\n      } else if (kwText.startsWith('what is') || kwText.startsWith('why is')) {\n        contentType = 'explainer article';\n      } else if (kwText.match(/\\\\?$/)) {\n        contentType = 'FAQ / Q&A';\n      } else if (kwText.match(/\\\\b(best|top [0-9]|top ten)\\\\b/)) {\n        contentType = 'listicle';\n      } else if (kwText.match(/\\\\b(vs|versus|compare|comparison)\\\\b/)) {\n        contentType = 'comparison article';\n      } else if (kwText.includes('guide') || kwText.includes('complete')) {\n        contentType = 'comprehensive guide';\n      } else if (kwText.match(/\\\\b(review|reviews)\\\\b/)) {\n        contentType = 'review article';\n      } else if (kwText.match(/\\\\b(tips|strategies|tactics|ideas)\\\\b/)) {\n        contentType = 'tips & tactics';\n      }\n      \n      // Analyze trend\n      let trendStatus = 'stable';\n      let trendAvg = 0;\n      let trendDirection = 0;\n      \n      if (kw.history_trend && typeof kw.history_trend === 'object') {\n        const trendValues = Object.values(kw.history_trend);\n        if (trendValues.length >= 6) {\n          const recent3 = trendValues.slice(-3).reduce((a, b) => a + b, 0) / 3;\n          const older3 = trendValues.slice(0, 3).reduce((a, b) => a + b, 0) / 3;\n          trendAvg = Math.round(trendValues.reduce((a, b) => a + b, 0) / trendValues.length);\n          \n          if (recent3 > older3 * 1.3) {\n            trendStatus = 'trending up';\n            trendDirection = Math.round(((recent3 - older3) / older3) * 100);\n          } else if (recent3 < older3 * 0.7) {\n            trendStatus = 'trending down';\n            trendDirection = Math.round(((recent3 - older3) / older3) * 100);\n          }\n        }\n      }\n      \n      // Calculate estimated monthly traffic (CTR assumptions)\n      let estimatedTraffic = 0;\n      if (kw.volume) {\n        // Assume 30% CTR for position 1, 15% for 2-3, 10% for 4-5, 5% for 6-10\n        // For content generation, estimate top 5 ranking potential\n        estimatedTraffic = Math.round(kw.volume * 0.15);\n      }\n      \n      // Priority classification\n      let priority = 'LOW';\n      if (opportunityScore >= 70) {\n        priority = 'HIGH';\n      } else if (opportunityScore >= 50) {\n        priority = 'MEDIUM';\n      }\n      \n      // Extract SERP features and intents if available\n      const serpFeatures = kw.serp_features ? \n        (Array.isArray(kw.serp_features) ? kw.serp_features.join('; ') : kw.serp_features) : '';\n      const intents = kw.intents ? \n        (Array.isArray(kw.intents) ? kw.intents.join('; ') : kw.intents) : intent;\n      \n      allKeywords.push({\n        date: timestamp,\n        keyword: keywordText,\n        volume: kw.volume || 0,\n        cpc: kw.cpc || 0,\n        difficulty: kw.difficulty || 0,\n        competition: kw.competition || 0,\n        relevance: kw.relevance || null,\n        opportunity_score: opportunityScore,\n        priority: priority,\n        search_intent: intents || intent,\n        content_type: contentType,\n        trend_status: trendStatus,\n        trend_direction_pct: trendDirection,\n        trend_avg_volume: trendAvg,\n        estimated_monthly_traffic: estimatedTraffic,\n        serp_features: serpFeatures,\n        section_source: sectionIndex === 0 ? 'longtail' : \n                       sectionIndex === 1 ? 'questions' : \n                       sectionIndex === 2 ? 'similar' : 'related'\n      });\n    }\n    // For simple string keywords\n    else {\n      allKeywords.push({\n        date: timestamp,\n        keyword: keywordText,\n        volume: 0,\n        cpc: 0,\n        difficulty: 0,\n        competition: 0,\n        relevance: null,\n        opportunity_score: 0,\n        priority: 'UNKNOWN',\n        search_intent: 'unknown',\n        content_type: 'blog post',\n        trend_status: 'unknown',\n        trend_direction_pct: 0,\n        trend_avg_volume: 0,\n        estimated_monthly_traffic: 0,\n        serp_features: '',\n        section_source: sectionIndex === 0 ? 'longtail' : \n                       sectionIndex === 1 ? 'questions' : \n                       sectionIndex === 2 ? 'similar' : 'related'\n      });\n    }\n  });\n});\n\n// Sort by opportunity score descending\nallKeywords.sort((a, b) => b.opportunity_score - a.opportunity_score);\n\nreturn allKeywords.map(kw => ({ json: kw }));"
      },
      "typeVersion": 2
    },
    {
      "id": "203c0b4a-02ae-4f81-b55a-4ee80d894542",
      "name": "Export to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        5904,
        2256
      ],
      "parameters": {
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "92482d94-bb31-4b29-bc3e-9fee8a7d461b",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4208,
        1744
      ],
      "parameters": {
        "color": 5,
        "width": 504,
        "height": 768,
        "content": "## Research keywords for content ideas\n\n## Who is this for\n- Content creators planning articles\n- SEO professionals finding opportunities\n- Marketing teams building content calendars\n\n## What you'll get\n- Longtail, question, similar, and related keywords\n- Opportunity scores based on volume, difficulty, and CPC\n- Search intent classification\n- Content type suggestions\n- Trend analysis with historical data\n- Traffic estimates and priority rankings\n- All results exported to Google Sheets\n\n## How it works\n1. Fetches 4 keyword types from SE Ranking\n2. Merges and deduplicates results\n3. Analyzes with scoring algorithm\n4. Detects search intent and suggests content types\n5. Exports to Google Sheets\n\n## Setup steps\n1. Install SE Ranking community node\n2. Add SE Ranking API credentials\n3. Update seed keyword in all 4 nodes\n4. Connect Google Sheets credentials\n5. Select your spreadsheet\n\n## Customization\nAdjust volume and difficulty filters in nodes or modify scoring formula in Code node."
      },
      "typeVersion": 1
    },
    {
      "id": "24ca7591-012a-46a9-b926-aabe61d29b54",
      "name": "Longtail Keywords",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5120,
        1936
      ],
      "parameters": {
        "color": 4,
        "width": 280,
        "height": 80,
        "content": "### Longtail Keywords\nRetrieves up to 50 longtail variations. Update the keyword parameter with your target topic."
      },
      "typeVersion": 1
    },
    {
      "id": "1301ca6b-46e8-4dae-b3b1-58fd3e3176bd",
      "name": "Question Keywords",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5088,
        2224
      ],
      "parameters": {
        "color": 4,
        "width": 280,
        "height": 80,
        "content": "### Question Keywords\nFinds question-based keywords with min 500 volume and max 50 difficulty. Perfect for FAQ content."
      },
      "typeVersion": 1
    },
    {
      "id": "3f605bab-6964-4d8e-b843-dc65c7000407",
      "name": "Similar Keywords",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5056,
        2496
      ],
      "parameters": {
        "color": 4,
        "width": 280,
        "height": 80,
        "content": "### Similar Keywords\nGets semantically similar keywords with the same filters. Helps expand topic coverage."
      },
      "typeVersion": 1
    },
    {
      "id": "3f7bdb82-c609-414c-a707-3e27fed960df",
      "name": "Related Keywords",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5056,
        2784
      ],
      "parameters": {
        "color": 4,
        "width": 280,
        "height": 80,
        "content": "### Related Keywords\nFinds related suggestions based on your seed term. Uncovers adjacent topics."
      },
      "typeVersion": 1
    },
    {
      "id": "ca07827d-d588-4ca3-8fa2-f21ab6aa52cd",
      "name": "Merge Results",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5440,
        2496
      ],
      "parameters": {
        "color": 4,
        "height": 80,
        "content": "### Merge Results\nCombines all 4 keyword sources into a single dataset."
      },
      "typeVersion": 1
    },
    {
      "id": "1ad7b71d-8f83-411d-a901-9ff17a91c8ee",
      "name": "Analysis",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5616,
        2080
      ],
      "parameters": {
        "color": 4,
        "content": "### Analysis\nScores keywords by volume, difficulty, and CPC. Detects search intent, suggests content types, and assigns priority rankings."
      },
      "typeVersion": 1
    },
    {
      "id": "de459f21-44b9-4a5e-b503-18735e26e9b7",
      "name": "Export",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5904,
        2128
      ],
      "parameters": {
        "color": 4,
        "height": 80,
        "content": "### Export\nAppends analyzed keywords to Google Sheets with 17 columns including metrics and recommendations."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "",
  "connections": {
    "Get related keywords": {
      "main": [
        [
          {
            "node": "Merge all keyword types",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "Get similar keywords": {
      "main": [
        [
          {
            "node": "Merge all keyword types",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Get longtail keywords": {
      "main": [
        [
          {
            "node": "Merge all keyword types",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get question keywords": {
      "main": [
        [
          {
            "node": "Merge all keyword types",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge all keyword types": {
      "main": [
        [
          {
            "node": "Analyze & Score Keywords for Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking 'Execute workflow'": {
      "main": [
        [
          {
            "node": "Get longtail keywords",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get question keywords",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get similar keywords",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get related keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze & Score Keywords for Content": {
      "main": [
        [
          {
            "node": "Export to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}