{
  "id": "WG66hDWKadILXdpQ",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Identify competitor content gaps in AI search with SE Ranking",
  "tags": [],
  "nodes": [
    {
      "id": "2b3056bc-f4d7-4a1a-9b17-24e0d4f22a9d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -592,
        -192
      ],
      "parameters": {
        "color": 5,
        "width": 420,
        "height": 580,
        "content": "## \ud83d\udd0d Identify competitor content gaps in AI search with SE Ranking\n\n**Who is this for:**\n- Marketing teams tracking AI SEO performance\n- Content strategists planning editorial calendars\n- SEO teams doing competitive intelligence\n\n**What this workflow does:**\nIdentify content opportunities by analyzing where competitors outrank you in AI search and traditional SEO.\n\n**What you'll get:**\n- AI visibility gaps across ChatGPT, Perplexity, and Gemini\n- Keyword gaps with search volume and difficulty\n- Competitor backlink authority metrics\n- Prioritized opportunities with HIGH/MEDIUM/LOW scoring\n- Actionable recommendations for each gap\n\n**Requirements:**\n- Self-hosted n8n instance\n- [SE Ranking community node](https://www.npmjs.com/package/@seranking/n8n-nodes-seranking)\n- SE Ranking API token ([Get one here](https://online.seranking.com/admin.api.dashboard.html))\n- Google Sheets (optional)\n\n**Setup:**\n1. Install the SE Ranking community node\n2. Add your SE Ranking API credentials\n3. Update domains in the Configuration node\n4. Connect Google Sheets (optional)"
      },
      "typeVersion": 1
    },
    {
      "id": "8478e23c-d5bf-4a83-b26d-875412c794d3",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        480
      ],
      "parameters": {
        "height": 140,
        "content": "### Step 1: Configuration\nSet your domain, competitor, and region here.\n\nChange `source` for different regions:\nus, uk, de, fr, es, it, etc."
      },
      "typeVersion": 1
    },
    {
      "id": "3dd1140c-0dbb-43eb-aa35-51da2d4f284a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        144,
        32
      ],
      "parameters": {
        "width": 320,
        "height": 100,
        "content": "### Step 2: AI Visibility Data\nFetch AI search metrics for both domains across ChatGPT, Perplexity, and Gemini engines."
      },
      "typeVersion": 1
    },
    {
      "id": "5196ac29-71dd-414f-b675-7bf90fe89ca9",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        480
      ],
      "parameters": {
        "width": 260,
        "height": 100,
        "content": "### Step 3: Calculate AI Gaps\nCompare visibility metrics and calculate opportunity scores."
      },
      "typeVersion": 1
    },
    {
      "id": "980acf14-ad24-4bde-a40d-0bd391a888de",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1248,
        320
      ],
      "parameters": {
        "width": 300,
        "height": 100,
        "content": "### Step 4: Keyword & Backlink Research\nExtract competitor's top prompts, keywords, and backlink authority."
      },
      "typeVersion": 1
    },
    {
      "id": "fa4b78c3-6a7d-4e56-924c-ea1602b8a6b5",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2464,
        544
      ],
      "parameters": {
        "width": 280,
        "height": 100,
        "content": "### Step 5: Final Scoring & Export\nPrioritize opportunities (HIGH/MEDIUM/LOW) and export to Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "89db32c9-1251-4efe-8a39-0aeb880609c2",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -352,
        672
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "f9c678ae-aee0-46cc-b815-434c48c28e02",
      "name": "Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        -128,
        672
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "your_domain",
              "stringValue": "seranking.com"
            },
            {
              "name": "source",
              "stringValue": "us"
            },
            {
              "name": "scope",
              "stringValue": "base_domain"
            },
            {
              "name": "competitor_domain",
              "stringValue": "semrush.com"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "c36190bb-0134-4c94-ba0f-0032371e5a1a",
      "name": "Your Domain - ChatGPT",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        112,
        160
      ],
      "parameters": {
        "scope": "={{ $json.scope }}",
        "domain": "={{ $json.your_domain }}",
        "source": "={{ $json.source }}",
        "resource": "aiSearch"
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cf8056ef-508a-427b-8847-e2e26743934f",
      "name": "Your Domain - Perplexity",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        112,
        544
      ],
      "parameters": {
        "scope": "={{ $('Configuration').item.json.scope }}",
        "domain": "={{ $('Configuration').item.json.your_domain }}",
        "engine": "perplexity",
        "source": "={{ $('Configuration').item.json.source }}",
        "resource": "aiSearch"
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f0833fce-4c10-4ac9-860f-5b42139db078",
      "name": "Your Domain - Gemini",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        112,
        944
      ],
      "parameters": {
        "scope": "={{ $('Configuration').item.json.scope }}",
        "domain": "={{ $('Configuration').item.json.your_domain }}",
        "engine": "gemini",
        "source": "={{ $('Configuration').item.json.source }}",
        "resource": "aiSearch"
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "439ab460-8910-47b2-9cdc-6ff4408942ab",
      "name": "Wait (Rate Limit)",
      "type": "n8n-nodes-base.wait",
      "position": [
        112,
        384
      ],
      "parameters": {
        "amount": 3
      },
      "typeVersion": 1.1
    },
    {
      "id": "88657d48-3f58-4196-ad26-ea59c03d57d4",
      "name": "Competitor - ChatGPT",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        352,
        336
      ],
      "parameters": {
        "scope": "={{ $('Configuration').item.json.scope }}",
        "domain": "={{ $('Configuration').item.json.competitor_domain }}",
        "source": "={{ $('Configuration').item.json.source }}",
        "resource": "aiSearch"
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4439d5c6-1c6e-4af5-98d3-1632be4cb7ad",
      "name": "Competitor - Perplexity",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        352,
        704
      ],
      "parameters": {
        "scope": "={{ $('Configuration').item.json.scope }}",
        "domain": "={{ $('Configuration').item.json.competitor_domain }}",
        "engine": "perplexity",
        "source": "={{ $('Configuration').item.json.source }}",
        "resource": "aiSearch"
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "74ad1980-cca3-491b-b0d6-b3dc0c8d26a5",
      "name": "Competitor - Gemini",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        544,
        864
      ],
      "parameters": {
        "scope": "={{ $('Configuration').item.json.scope }}",
        "domain": "={{ $('Configuration').item.json.competitor_domain }}",
        "engine": "gemini",
        "source": "={{ $('Configuration').item.json.source }}",
        "resource": "aiSearch"
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2810ad33-5740-462d-a778-5c39dbfc2c1d",
      "name": "Merge AI Visibility Data",
      "type": "n8n-nodes-base.merge",
      "position": [
        784,
        672
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "mergeByPosition"
      },
      "typeVersion": 2.1
    },
    {
      "id": "9ad9ed1f-7b48-4cb1-8b50-6fbd3892ec0d",
      "name": "Calculate AI Gaps",
      "type": "n8n-nodes-base.code",
      "position": [
        1008,
        672
      ],
      "parameters": {
        "jsCode": "// Calculate AI Search Gap Analysis\nconst config = $('Configuration').first().json;\nconst yourData = [\n  $('Your Domain - ChatGPT').first().json,\n  $('Your Domain - Perplexity').first().json,\n  $('Your Domain - Gemini').first().json\n];\nconst compData = [\n  $('Competitor - ChatGPT').first().json,\n  $('Competitor - Perplexity').first().json,\n  $('Competitor - Gemini').first().json\n];\n\nconst engines = ['chatgpt', 'perplexity', 'gemini'];\nconst results = [];\n\nengines.forEach((engine, i) => {\n  const your = yourData[i]?.summary || {};\n  const comp = compData[i]?.summary || {};\n  \n  const yourLinkPresence = your.link_presence?.current || 0;\n  const compLinkPresence = comp.link_presence?.current || 0;\n  const yourAvgPos = your.average_position?.current || 0;\n  const compAvgPos = comp.average_position?.current || 0;\n  const yourTraffic = your.ai_opportunity_traffic?.current || 0;\n  const compTraffic = comp.ai_opportunity_traffic?.current || 0;\n  \n  // Calculate gaps (negative = competitor is better)\n  const linkPresenceGap = yourLinkPresence - compLinkPresence;\n  const avgPosGap = compAvgPos - yourAvgPos; // Lower is better, so flip\n  const trafficGap = yourTraffic - compTraffic;\n  \n  // Opportunity Score (higher = bigger opportunity to improve)\n  // Formula: Weighted average of gaps (negative gaps = opportunities)\n  const opportunityScore = Math.round(\n    (Math.abs(Math.min(linkPresenceGap, 0)) * 0.4) +\n    (Math.abs(Math.min(avgPosGap, 0)) * 0.3) +\n    (Math.abs(Math.min(trafficGap, 0)) * 0.3)\n  );\n  \n  results.push({\n    json: {\n      analysis_date: new Date().toISOString().split('T')[0],\n      your_domain: config.your_domain,\n      competitor_domain: config.competitor_domain,\n      engine: engine,\n      \n      // Your metrics\n      your_link_presence: yourLinkPresence,\n      your_avg_position: yourAvgPos.toFixed(2),\n      your_ai_traffic: yourTraffic,\n      \n      // Competitor metrics\n      comp_link_presence: compLinkPresence,\n      comp_avg_position: compAvgPos.toFixed(2),\n      comp_ai_traffic: compTraffic,\n      \n      // Gap analysis\n      link_presence_gap: linkPresenceGap,\n      avg_position_gap: avgPosGap.toFixed(2),\n      traffic_gap: trafficGap,\n      \n      // Opportunity scoring\n      opportunity_score: opportunityScore,\n      priority: opportunityScore > 100 ? 'HIGH' : opportunityScore > 50 ? 'MEDIUM' : 'LOW',\n      \n      // Status flags\n      is_competitor_winning: linkPresenceGap < 0 || avgPosGap < 0,\n      needs_immediate_action: opportunityScore > 100\n    }\n  });\n});\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "e57530fd-3e4d-44a1-a57e-607a1b98ae51",
      "name": "Competitor Top Prompts",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        1280,
        448
      ],
      "parameters": {
        "scope": "={{ $('Configuration').item.json.scope }}",
        "domain": "={{ $('Configuration').item.json.competitor_domain }}",
        "source": "={{ $('Configuration').item.json.source }}",
        "resource": "aiSearch",
        "operation": "getPromptsByTarget",
        "additionalFields": {
          "sort": "volume",
          "limit": 50,
          "sortOrder": "desc"
        }
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4b2c3381-a337-44ea-827e-2218d6893d65",
      "name": "Competitor Top Keywords",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        1440,
        768
      ],
      "parameters": {
        "domain": "={{ $('Configuration').item.json.competitor_domain }}",
        "source": "={{ $('Configuration').item.json.source }}",
        "operation": "getKeywords",
        "additionalFields": {
          "limit": 100,
          "orderType": "desc",
          "orderField": "traffic",
          "positionTo": 20,
          "volumeFrom": 500,
          "positionFrom": 1
        }
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8639f5ce-5111-4e1a-a82b-923d10d5b53d",
      "name": "Competitor Backlink Authority",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        1392,
        944
      ],
      "parameters": {
        "target": "={{ $('Configuration').item.json.competitor_domain }}",
        "resource": "backlinks",
        "additionalFields": {
          "historical": true
        }
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0eff6a85-4ccf-4da1-855f-7f9270c782ad",
      "name": "Extract Top Prompts",
      "type": "n8n-nodes-base.code",
      "position": [
        1584,
        448
      ],
      "parameters": {
        "jsCode": "// Extract top competitor prompts and format for keyword research\nconst input = $input.first().json;\nconst prompts = input.prompts || [];\n\n// Sort by volume (even if 0) and take top prompts\n// Filter can be adjusted based on actual data characteristics\nconst topPrompts = prompts\n  .filter(p => p.prompt && p.prompt.trim().length > 0) // Just check prompt exists\n  .slice(0, 20) // Take top 20\n  .map(p => p.prompt);\n\nreturn [{\n  json: {\n    keywords: topPrompts,\n    count: topPrompts.length,\n    original_total: input.total || 0\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "5ea1a0c8-7592-4a7d-9ca6-f6b609040a04",
      "name": "Extract Top Keywords",
      "type": "n8n-nodes-base.code",
      "position": [
        1600,
        640
      ],
      "parameters": {
        "jsCode": "// Extract competitor keywords that you don't rank for\nconst keywords = $input.all();\nconst topKeywords = keywords\n  .map(k => k.json)\n  .filter(k => k.volume > 500 && k.position <= 10) // High-value, top-ranking\n  .slice(0, 30)\n  .map(k => k.keyword);\n\nreturn [{\n  json: {\n    keywords: topKeywords,\n    count: topKeywords.length\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "0ff40ac4-c927-44e4-a899-a24c5d78ad6e",
      "name": "Gap Keywords - Full Metrics",
      "type": "@seranking/n8n-nodes-seranking.seRanking",
      "position": [
        2176,
        368
      ],
      "parameters": {
        "source": "={{ $('Configuration').first().json.source }}",
        "keywords": "=seo",
        "resource": "keywordResearch",
        "additionalFields": {
          "cols": [
            "keyword",
            "volume",
            "cpc",
            "competition",
            "difficulty"
          ],
          "sort": "volume",
          "sortOrder": "desc"
        }
      },
      "credentials": {
        "seRankingApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3c4e6b68-51c1-478f-ac52-ef3a69037dfa",
      "name": "Merge All Intelligence",
      "type": "n8n-nodes-base.merge",
      "position": [
        2288,
        672
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "mergeByPosition"
      },
      "typeVersion": 2.1
    },
    {
      "id": "da88eda5-db40-4861-b9d2-2a7e44400d2d",
      "name": "Final Opportunity Scoring",
      "type": "n8n-nodes-base.code",
      "position": [
        2512,
        672
      ],
      "parameters": {
        "jsCode": "// Final Opportunity Scoring & Prioritization\nconst aiGaps = $('Calculate AI Gaps').all();\nconst keywordMetrics = $('Gap Keywords - Full Metrics').all();\nconst backlinkData = $('Competitor Backlink Authority').first().json;\nconst config = $('Configuration').first().json;\n\n// Competitor authority context\nconst compAuthority = {\n  total_backlinks: backlinkData.backlinks_info?.backlinks || 0,\n  referring_domains: backlinkData.backlinks_info?.refdomains || 0,\n  domain_inlink_rank: backlinkData.backlinks_info?.domain_inlink_rank || 0\n};\n\nconst opportunities = [];\n\n// Process AI gaps by engine\naiGaps.forEach(gap => {\n  const g = gap.json;\n  if (g.is_competitor_winning) {\n    opportunities.push({\n      type: 'AI_VISIBILITY_GAP',\n      engine: g.engine,\n      priority: g.priority,\n      opportunity_score: g.opportunity_score,\n      metric: 'Link Presence',\n      your_value: g.your_link_presence,\n      comp_value: g.comp_link_presence,\n      gap: g.link_presence_gap,\n      action: g.link_presence_gap < -50 ? 'URGENT: Create AI-optimized content' : 'Improve content for AI citations'\n    });\n  }\n});\n\n// Process keyword gaps\nkeywordMetrics.forEach(kw => {\n  const k = kw.json;\n  if (k.volume > 1000 && k.difficulty < 70) {\n    // Calculate opportunity score\n    const opportunityScore = Math.round(\n      (k.volume * 0.5) + \n      ((100 - k.difficulty) * 0.3) +\n      (k.cpc * 10)\n    );\n    \n    opportunities.push({\n      type: 'KEYWORD_GAP',\n      keyword: k.keyword,\n      priority: opportunityScore > 5000 ? 'HIGH' : opportunityScore > 2000 ? 'MEDIUM' : 'LOW',\n      opportunity_score: opportunityScore,\n      volume: k.volume,\n      difficulty: k.difficulty,\n      cpc: k.cpc,\n      estimated_traffic: Math.round(k.volume * 0.15), // Assume 15% CTR at top position\n      action: k.difficulty < 40 ? 'Quick Win: Create optimized content' : 'Long-term: Build authority'\n    });\n  }\n});\n\n// Sort all opportunities by score\nopportunities.sort((a, b) => b.opportunity_score - a.opportunity_score);\n\n// Add metadata\nconst finalReport = opportunities.slice(0, 50).map((opp, i) => ({\n  json: {\n    rank: i + 1,\n    analysis_date: new Date().toISOString().split('T')[0],\n    your_domain: config.your_domain,\n    competitor_domain: config.competitor_domain,\n    competitor_authority: compAuthority.domain_inlink_rank,\n    competitor_backlinks: compAuthority.total_backlinks,\n    competitor_ref_domains: compAuthority.referring_domains,\n    ...opp\n  }\n}));\n\nreturn finalReport;"
      },
      "typeVersion": 2
    },
    {
      "id": "2f53f6de-e665-4835-af6b-c9d1406782b6",
      "name": "Export to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2736,
        672
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ouYDOeYe3tuNCEglNyWSh4e1gktN3ExpcbLl46xQ7Xc/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1ouYDOeYe3tuNCEglNyWSh4e1gktN3ExpcbLl46xQ7Xc/edit?gid=0#gid=0"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "c7dd2c56-fb89-4889-89a9-12d79b0eace8",
      "name": "Wait (Rate Limit)1",
      "type": "n8n-nodes-base.wait",
      "position": [
        112,
        768
      ],
      "parameters": {
        "amount": 3
      },
      "typeVersion": 1.1
    },
    {
      "id": "13f13dd0-27dc-4900-9b7b-e07877686509",
      "name": "Wait (Rate Limit)2",
      "type": "n8n-nodes-base.wait",
      "position": [
        352,
        160
      ],
      "parameters": {
        "amount": 3
      },
      "typeVersion": 1.1
    },
    {
      "id": "441e8e37-ab4e-479a-aff6-fb50ee340c04",
      "name": "Wait (Rate Limit)3",
      "type": "n8n-nodes-base.wait",
      "position": [
        352,
        528
      ],
      "parameters": {
        "amount": 3
      },
      "typeVersion": 1.1
    },
    {
      "id": "0f60aad1-1a71-4111-9bb6-ac7fc72d61a1",
      "name": "Wait (Rate Limit)4",
      "type": "n8n-nodes-base.wait",
      "position": [
        336,
        912
      ],
      "parameters": {
        "amount": 3
      },
      "typeVersion": 1.1
    },
    {
      "id": "1eb71c9d-5280-447b-8784-c684a7dcfd5e",
      "name": "Wait (Rate Limit)5",
      "type": "n8n-nodes-base.wait",
      "position": [
        1264,
        656
      ],
      "parameters": {
        "amount": 3
      },
      "typeVersion": 1.1
    },
    {
      "id": "4313bfdd-a6e8-41e6-b84a-1928918ddd5b",
      "name": "Wait (Rate Limit)6",
      "type": "n8n-nodes-base.wait",
      "position": [
        1088,
        432
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "1271dc83-21ae-4554-9b52-4e7bd8599f04",
      "name": "Merge All Intelligence1",
      "type": "n8n-nodes-base.merge",
      "position": [
        1824,
        544
      ],
      "parameters": {},
      "typeVersion": 2.1
    },
    {
      "id": "ae5e2be5-0382-4a62-bb67-63eb3f8c8fa1",
      "name": "Combine Keywords",
      "type": "n8n-nodes-base.code",
      "position": [
        2032,
        544
      ],
      "parameters": {
        "jsCode": "// Combine prompts and keywords into a single unified list\nconst allInputs = $input.all();\n\n// Extract all keyword arrays\nconst allKeywords = [];\n\nallInputs.forEach(item => {\n  if (item.json.keywords && Array.isArray(item.json.keywords)) {\n    allKeywords.push(...item.json.keywords);\n  }\n});\n\n// Remove duplicates (case-insensitive) and clean\nconst uniqueKeywords = [...new Set(\n  allKeywords.map(kw => kw.toLowerCase().trim())\n)];\n\n// Filter out inappropriate/adult content keywords\nconst inappropriateTerms = [\n  'porn', 'xxx', 'sex', 'adult', 'tube', 'leaked', 'incest', \n  'coomer', 'ashemaletube', 'missav', 'xpaja', 'javmost', \n  'sickjunk', 'xfreehd', 'celebjihad', 'ghettotube', 'bbw', \n  'boundhub', 'potnhub', 'pormhub', 'xorgasmo', 'ukdevilz',\n  'ero', 'thots', 'anonib', 'scrolller', 'webtoon', 'whoer',\n  'enf', 'cmnf', 'shahvani', 'leakedzone', 'sickjunk'\n];\n\nconst cleanKeywords = uniqueKeywords.filter(kw => {\n  return !inappropriateTerms.some(term => kw.includes(term));\n});\n\n// Additional validation - ensure keywords are valid strings\nconst validKeywords = cleanKeywords.filter(kw => {\n  return kw && \n         kw.length > 0 && \n         kw.length < 200 && // SE Ranking limit\n         /^[a-zA-Z0-9\\s\\-\\?\\.]+$/.test(kw); // Only alphanumeric, spaces, hyphens, question marks, periods\n});\n\nreturn [{\n  json: {\n    keywords: validKeywords.slice(0, 50), // Limit to 50 for API efficiency\n    total_count: validKeywords.length,\n    filtered_out: uniqueKeywords.length - validKeywords.length,\n    prompts_count: allInputs[0]?.json?.count || 0,\n    competitor_keywords_count: allInputs[1]?.json?.count || 0\n  }\n}];"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "cec4de78-00e4-4fd1-bbc8-2345e1809b65",
  "connections": {
    "Configuration": {
      "main": [
        [
          {
            "node": "Your Domain - ChatGPT",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Keywords": {
      "main": [
        [
          {
            "node": "Gap Keywords - Full Metrics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate AI Gaps": {
      "main": [
        [
          {
            "node": "Competitor Backlink Authority",
            "type": "main",
            "index": 0
          },
          {
            "node": "Wait (Rate Limit)6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait (Rate Limit)": {
      "main": [
        [
          {
            "node": "Your Domain - Perplexity",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait (Rate Limit)1": {
      "main": [
        [
          {
            "node": "Your Domain - Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait (Rate Limit)2": {
      "main": [
        [
          {
            "node": "Competitor - ChatGPT",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait (Rate Limit)3": {
      "main": [
        [
          {
            "node": "Competitor - Perplexity",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait (Rate Limit)4": {
      "main": [
        [
          {
            "node": "Competitor - Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait (Rate Limit)5": {
      "main": [
        [
          {
            "node": "Competitor Top Keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait (Rate Limit)6": {
      "main": [
        [
          {
            "node": "Competitor Top Prompts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Competitor - Gemini": {
      "main": [
        [
          {
            "node": "Merge AI Visibility Data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Extract Top Prompts": {
      "main": [
        [
          {
            "node": "Merge All Intelligence1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Competitor - ChatGPT": {
      "main": [
        [
          {
            "node": "Wait (Rate Limit)3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Top Keywords": {
      "main": [
        [
          {
            "node": "Merge All Intelligence1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Your Domain - Gemini": {
      "main": [
        [
          {
            "node": "Wait (Rate Limit)2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Your Domain - ChatGPT": {
      "main": [
        [
          {
            "node": "Wait (Rate Limit)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Competitor Top Prompts": {
      "main": [
        [
          {
            "node": "Extract Top Prompts",
            "type": "main",
            "index": 0
          },
          {
            "node": "Wait (Rate Limit)5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge All Intelligence": {
      "main": [
        [
          {
            "node": "Final Opportunity Scoring",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Competitor - Perplexity": {
      "main": [
        [
          {
            "node": "Merge AI Visibility Data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Wait (Rate Limit)4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Competitor Top Keywords": {
      "main": [
        [
          {
            "node": "Extract Top Keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge All Intelligence1": {
      "main": [
        [
          {
            "node": "Combine Keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge AI Visibility Data": {
      "main": [
        [
          {
            "node": "Calculate AI Gaps",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Your Domain - Perplexity": {
      "main": [
        [
          {
            "node": "Wait (Rate Limit)1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Final Opportunity Scoring": {
      "main": [
        [
          {
            "node": "Export to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gap Keywords - Full Metrics": {
      "main": [
        [
          {
            "node": "Merge All Intelligence",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Competitor Backlink Authority": {
      "main": [
        [
          {
            "node": "Merge All Intelligence",
            "type": "main",
            "index": 1
          }
        ]
      ]
    }
  }
}