AutomationFlowsAI & RAG › Generate Youtube Content Ideas with Firecrawl, Openai and Notion

Generate Youtube Content Ideas with Firecrawl, Openai and Notion

ByWildan Adli @iwilwildan on n8n.io

This workflow acts as an autonomous Chief Solution Officer, automating the process of deep market research. Instead of simply tracking video views, it scrapes deep into YouTube data—including descriptions and top 20 comments—to identify the real "Decision Confusion" and…

Cron / scheduled trigger★★★★☆ complexityAI-powered24 nodesOpenAI ChatOutput Parser StructuredHTTP RequestAgentNotion
AI & RAG Trigger: Cron / scheduled Nodes: 24 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #12509 — we link there as the canonical source.

This workflow follows the Agent → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "RxDy1M56m2aYClX0",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Generate YouTube Content Ideas with Firecrawl, OpenAI & Notion",
  "tags": [],
  "nodes": [
    {
      "id": "40fb2709-240f-43b0-a33f-f3e60d1848c8",
      "name": "Set Niche",
      "type": "n8n-nodes-base.set",
      "position": [
        -4416,
        -532
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "be118a09-c919-47ac-968e-b44fdc6e9bec",
              "name": "query",
              "type": "string",
              "value": "<YOUR_NICHE_OR_KEYWORD>"
            },
            {
              "id": "2717ce3d-62b0-4127-9eb0-3e1f42ece9d4",
              "name": "limit",
              "type": "number",
              "value": 10
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "11c7bbd8-07ea-4d38-b55a-2477a1a8044a",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -2392,
        -432
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1",
          "cachedResultName": "gpt-4.1"
        },
        "options": {},
        "responsesApiEnabled": false
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "7f24a79e-1d36-40c4-878e-5f87cf595b63",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -2264,
        -432
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"analysis\": {\n    \"audienceProfile\": {\n      \"goals\": [\"goal 1\", \"goal 2\", \"goal 3\"],\n      \"needs\": [\"need 1\", \"need 2\", \"need 3\"],\n      \"painPoints\": [\"pain 1\", \"pain 2\", \"pain 3\"],\n      \"challenges\": [\"challenge 1\", \"challenge 2\", \"challenge 3\"]\n    },\n    \"keyInsights\": [\n      \"Insight 1 - supported by specific comments\",\n      \"Insight 2 - supported by engagement patterns\",\n      \"Insight 3 - supported by topic gaps\"\n    ],\n    \"topCommentAnalysis\": {\n      \"mostEngagedTheme\": \"Theme from the most-liked comments\",\n      \"topicGaps\": [\"Gap 1\", \"Gap 2\", \"Gap 3\"]\n    }\n  },\n  \"contentIdeas\": [\n    {\n      \"id\": 1,\n      \"title\": \"Content Idea Title\",\n      \"brief\": \"2-3 sentence brief\",\n      \"angle\": \"1-2 sentence unique angle\",\n      \"whyThisTopic\": \"Connection to audience insights\",\n      \"format\": \"Content format - reasoning\",\n      \"keyPoints\": [\"Point 1\", \"Point 2\", \"Point 3\", \"Point 4\", \"Point 5\"],\n      \"engagementPotential\": \"High/Medium/Low - reasoning\"\n    }\n  ],\n  \"strategy\": {\n    \"overallTheme\": \"General theme of the 5 ideas\",\n    \"publishingOrder\": \"Suggested publication order and reasoning\",\n    \"seriesOpportunity\": \"Potential for a series? How to link them together?\"\n  }\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "34698409-62aa-4b7e-b819-160e33c75265",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -3072,
        -532
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "93c15cec-cacc-442a-be28-d6da346c1f4d",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -928,
        -532
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "id"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4daadba4-bc4a-4b22-90b9-12f2f3d8444f",
      "name": "ContentIdeas",
      "type": "n8n-nodes-base.set",
      "position": [
        -1824,
        -656
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ad12b694-99ba-4426-9f10-288ebce0b1c9",
              "name": "contentIdeas",
              "type": "array",
              "value": "={{ $('Identify Strategic Gaps').item.json.output.contentIdeas }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "4ff16f55-7e13-44d1-bec2-11fe3ca1a006",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5264,
        -912
      ],
      "parameters": {
        "width": 496,
        "height": 544,
        "content": "## How it works\n\nThis workflow automates market research by identifying what your audience actually wants. It starts by searching for top-performing YouTube videos in your niche using Firecrawl. The system then performs a deep scrape of video descriptions and the top 20 comments to capture raw audience feedback. An AI Strategist analyzes this data to identify \"decision confusion\" and \"operational pain points,\" finally generating 5 data-backed content ideas. All insights are automatically structured and saved into Notion for your editorial team.\n\n## Setup steps\n1. **Firecrawl:** Get your API Key from firecrawl.dev and add it to the Header Auth in the HTTP Request nodes.\n2. **OpenAI:** Connect your OpenAI credentials (GPT-4o is recommended for best reasoning).\n3. **Notion:** Connect your Notion account and ensure you have two databases ready for \"Insights\" and \"Ideas.\"\n4. **Configuration:** Enter your target keyword in the 'Set Niche' node.\n5. **Execution:** Run the workflow to populate your Notion workspace with new strategy ideas.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e5d3f751-6b5d-4b6e-b1ae-43433a99a9d5",
      "name": "Search YouTube Videos",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -4192,
        -532
      ],
      "parameters": {
        "url": "https://api.firecrawl.dev/v2/scrape",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "=https://www.youtube.com/results?search_query={{ $json.query.split(' ').join('+') }}"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "b7805e06-4470-47df-b7e6-d80517a0894a",
      "name": "Check Search Status",
      "type": "n8n-nodes-base.if",
      "position": [
        -3968,
        -532
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9f7b19eb-6c5e-412e-97d0-2f0481a2c79d",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.success }}",
              "rightValue": true
            },
            {
              "id": "e8daf3c8-2fbd-402d-a73a-34578f621c78",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.data.metadata.statusCode }}",
              "rightValue": 200
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "432fd24a-92a7-475d-aa0a-36da792bf266",
      "name": "Parse Video List",
      "type": "n8n-nodes-base.code",
      "position": [
        -3744,
        -532
      ],
      "parameters": {
        "jsCode": "const videos = [];\nconst inputItem = $input.first().json;\nconst limit = $('Set Niche').first().json.limit; \n\nif (!inputItem || !inputItem.data || !inputItem.data.markdown) {\n    return [{ json: { error: \"Data Not Found.\" } }];\n}\n\nconst markdown = inputItem.data.markdown;\n\nconst cleanString = (str) => {\n    return str.replace(/\\\\/g, '').trim();\n};\n\nconst parseNumericValue = (value) => {\n    if (!value || value === 'N/A') return 0;\n    const cleanedValue = value.toLowerCase().replace(/ subscribers| views/g, '').trim();\n    const multiplier = cleanedValue.slice(-1);\n    let num = parseFloat(cleanedValue);\n    if (isNaN(num)) return 0;\n    \n    if (multiplier === 'k') {\n        num *= 1000;\n    } else if (multiplier === 'm') {\n        num *= 1000000;\n    } else if (multiplier === 'b') {\n        num *= 1+1234567890;\n    }\n    \n    return num;\n};\n\nconst parseTimeAgo = (timeStr) => {\n    if (!timeStr || timeStr === 'N/A') return 999999;\n    \n    const lowerTime = timeStr.toLowerCase();\n    const match = lowerTime.match(/(\\d+)\\s*(second|minute|hour|day|week|month|year)/);\n    \n    if (!match) return 999999;\n    \n    const value = parseInt(match[1]);\n    const unit = match[2];\n    \n    switch(unit) {\n        case 'second': return value / 86400;\n        case 'minute': return value / 1440;\n        case 'hour': return value / 24;\n        case 'day': return value;\n        case 'week': return value * 7;\n        case 'month': return value * 30;\n        case 'year': return value * 365;\n        default: return 999999;\n    }\n};\n\nconst subscriberData = {};\nconst channelSubscriberRegex = /@([^\u2022]+?)\u2022(\\d+\\.?\\d*[KMB]? subscribers)/g;\nlet subMatch;\nwhile ((subMatch = channelSubscriberRegex.exec(markdown)) !== null) {\n    subscriberData[subMatch[1].trim()] = subMatch[2].trim();\n}\n\nconst videoBlockRegex = new RegExp(\n    /### \\[(.*?)\\]\\((https:\\/\\/www\\.youtube\\.com\\/watch\\?v=[^&]+).*?\\)/.source +\n    /[\\s\\S]*?\\[(.*?)\\]\\((https:\\/\\/www\\.youtube\\.com\\/@([^)]+))\\)/.source +\n    /[\\s\\S]*?(\\d+\\.?\\d*[KMB]? views)(.*?)ago/.source,\n    'g'\n);\n\nconst matches = [...markdown.matchAll(videoBlockRegex)];\n\nfor (const match of matches) {\n    const title = cleanString(match[1]);\n    const url = cleanString(match[2]);\n    const channelName = cleanString(match[3]);\n    const channelHandle = cleanString(match[5]); \n    const viewsRaw = cleanString(match[6]);\n    const timeAgo = cleanString(match[7] + 'ago');\n    \n    const channelSubscriberRaw = subscriberData[channelHandle] || 'N/A';\n    \n    const viewsNumeric = parseNumericValue(viewsRaw);\n    const subscriberNumeric = parseNumericValue(channelSubscriberRaw);\n    const daysAgo = parseTimeAgo(timeAgo);\n    \n    videos.push({\n        title: title,\n        url: url,\n        channelName: channelName,\n        channelHandle: `@${channelHandle}`,\n        channelSubscriber: channelSubscriberRaw,\n        views: viewsRaw,\n        uploadedAgo: timeAgo,\n        like: 'N/A', \n        comment: 'N/A',\n        _viewsNumeric: viewsNumeric,\n        _subscriberNumeric: subscriberNumeric,\n        _daysAgo: daysAgo\n    });\n}\n\nvideos.sort((a, b) => {\n    if (a._daysAgo !== b._daysAgo) {\n        return a._daysAgo - b._daysAgo; \n    }\n    if (b._viewsNumeric !== a._viewsNumeric) {\n        return b._viewsNumeric - a._viewsNumeric;\n    }\n    return b._subscriberNumeric - a._subscriberNumeric;\n});\n\nconst topNVideos = videos.slice(0, limit);\n\nconst finalVideos = topNVideos.map(video => {\n    delete video._viewsNumeric;\n    delete video._subscriberNumeric;\n    delete video._daysAgo;\n    return video;\n});\n\nreturn [{ json: { videos: finalVideos } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "0f8b256a-409e-4649-8ae3-1e9a80334bb9",
      "name": "Scrape Video Details",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -2848,
        -656
      ],
      "parameters": {
        "url": "https://api.firecrawl.dev/v2/scrape",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $json.url }}"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "e5a772ed-f6cb-486e-8ddb-489d8d459bb2",
      "name": "Extract Audience Comments",
      "type": "n8n-nodes-base.code",
      "position": [
        -2624,
        -656
      ],
      "parameters": {
        "jsCode": "const output = {};\nconst inputItem = $input.first().json;\n\nif (!inputItem || !inputItem.data || !inputItem.data.markdown) {\n    return [{ json: { error: \"Markdown data not found in input.\" } }];\n}\n\nconst markdown = inputItem.data.markdown;\n\n\n\nlet channelNameMatch = markdown.match(/\\[([^\\]]+)\\]\\(https:\\/\\/www\\.youtube\\.com\\/@[^\\)]+\\)/);\nif (!channelNameMatch) {\n    channelNameMatch = markdown.match(/\\[([^\\]]+)\\]\\(https:\\/\\/www\\.youtube\\.com\\/channel\\/[^\\)]+\\)/);\n}\noutput.channelName = channelNameMatch ? channelNameMatch[1].trim() : 'N/A';\n\n\nlet viewsMatch = markdown.match(/(\\d+(?:,\\d+)*)\\s+views/);\nif (!viewsMatch) {\n    // Fallback: Try to find views in format like \"722K views\"\n    viewsMatch = markdown.match(/(\\d+(?:\\.\\d+)?[KMB])\\s+views/);\n}\noutput.views = viewsMatch ? viewsMatch[1].trim() : 'N/A';\n\n\nlet likesMatch = markdown.match(/(\\d+(?:\\.\\d+)?[KMB]?)\\s*(?:Share|Dislike)/);\nif (!likesMatch) {\n    likesMatch = markdown.match(/^(\\d+(?:\\.\\d+)?[KMB]?)$/m);\n}\noutput.totalLikes = likesMatch ? likesMatch[1].trim() : 'N/A';\n\nlet descriptionMatch = markdown.match(/Show less\\n\\n([\\s\\S]*?)(?:\\n\\nTimestamps:|\\n\\nHow this was made|\\n\\n\\.\\.\\.more)/i);\nif (!descriptionMatch) {\n    \n    descriptionMatch = markdown.match(/\\d+\\s+views[\\s\\S]*?\\n\\n([\\s\\S]*?)(?:\\n\\nTimestamps:|\\n\\nHow this was made)/i);\n}\n\nlet description = 'N/A';\nif (descriptionMatch) {\n    description = descriptionMatch[1]\n        .replace(/\\n\\n/g, ' ')                      \n        .replace(/\\n/g, ' ')                        \n        .replace(/\\[.*?\\]\\(.*?\\)/g, '')           \n        .replace(/!\\[.*?\\]\\(.*?\\)/g, '')          \n        .replace(/\\s+/g, ' ')                       \n        .replace(/Show lessRead more/g, '')         // Remove UI text\n        .replace(/Show less/g, '')\n        .replace(/Read more/g, '')\n        .replace(/\\.\\.\\.more/g, '')\n        .trim();\n    \n    // Limit description to first 500 characters for cleaner output\n    if (description.length > 500) {\n        description = description.substring(0, 500) + '...';\n    }\n}\n\noutput.description = description;\n\n\nlet urlMatch = markdown.match(/https:\\/\\/www\\.youtube\\.com\\/watch\\?v=([a-zA-Z0-9_-]+)/);\nif (urlMatch) {\n    output.url = `https://www.youtube.com/watch?v=${urlMatch[1]}`;\n} else {\n    output.url = 'N/A';\n}\n\n\n\nconst comments = [];\n\n\n\nconst commentRegex = /!\\[\\]\\((https?:\\/\\/[^\\)]+)\\)\\s*\\n\\n([^\\n]*?)(?:\\n\\n(?:Show lessRead more|Read more|Show less)?)?\\n\\nLike\\s*\\n\\n(\\d+(?:\\.\\d+)?[KMB]?)?\\s*\\n\\nDislike/gs;\n\nlet commentMatch;\nlet count = 0;\n\nwhile ((commentMatch = commentRegex.exec(markdown)) !== null) {\n    let commentText = commentMatch[2] || '';\n    let likesRaw = commentMatch[3] || '0';\n    \n    // Clean up comment text\n    commentText = commentText\n        .replace(/\\\\n/g, ' ')                    // Remove backslash escapes\n        .replace(/\\s+/g, ' ')                    // Normalize whitespace\n        .replace(/Show lessRead more/g, '')      // Remove YouTube UI text\n        .replace(/Show less/g, '')\n        .replace(/Read more/g, '')\n        .replace(/\\[.*?\\]/g, '')                 // Remove markdown links\n        .replace(/!\\[.*?\\]\\(.*?\\)/g, '')         // Remove markdown images\n        .replace(/\u200b@\\w+\\s*-\\s*/g, '')            // Remove mentions like @user -\n        .replace(/\\s*\u2764 by @\\w+/g, '')           // Remove heart reactions\n        .replace(/!\\[.*?\\]\\(.*?\\)/g, '')         // Remove emoji images\n        .trim();\n    \n    // Convert likes from format like \"333\" or \"10K\" to number\n    let likesNumber = 0;\n    if (likesRaw && likesRaw !== '0') {\n        if (likesRaw.includes('K')) {\n            likesNumber = parseInt(likesRaw) * 1000;\n        } else if (likesRaw.includes('M')) {\n            likesNumber = parseInt(likesRaw) * 1000000;\n        } else {\n            likesNumber = parseInt(likesRaw) || 0;\n        }\n    }\n    \n    // Only include comments with meaningful content (at least 5 characters)\n    if (commentText.length >= 5) {\n        comments.push({\n            comment: commentText,\n            likes: likesNumber\n        });\n        count++;\n    }\n}\n\n// Sort by likes in descending order and take top 20\ncomments.sort((a, b) => b.likes - a.likes);\noutput.top20Comments = comments.slice(0, 20);\noutput.totalCommentsExtracted = count;\n\n\nreturn [{ json: output }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "b9dc0fce-ba19-4efa-8b0f-0029b28e208c",
      "name": "Identify Strategic Gaps",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -2400,
        -656
      ],
      "parameters": {
        "text": "make content Idea",
        "options": {
          "systemMessage": "=**Role:** You are the **Chief Solution Officer & Content Strategist** at an **AI Automation Agency** serving **established small-to-medium businesses (SMEs)**.\n\n**Your Tasks:**\n\n1. Analyze the description, likes, views, and top 20 comments of provided content.\n2. Identify the goals, needs, pain points, and challenges of a **decision-maker level** audience.\n3. Propose 5 content ideas **rooted in systems and business decisions**.\n4. Ensure all ideas are **strategic & actionable**.\n\n---\n\n## \ud83e\uddec BRAND ARCHETYPE (MANDATORY)\n\n**Sage (Primary) + Ruler + Creator**\n\n**Principles:**\n\n* Focus on the *why & how the system works*, not the *how to build it*.\n* Demonstrate structure, control, and intellectual maturity.\n* Tone: Calm, objective, non-hype, and non-hard-selling.\n\n---\n\n## \ud83e\uddf1 CONTENT PILLARS\n\nEach idea must fall into one of these categories:\n\n1. Operational Bottleneck & Business Pain\n2. Decision-Making & System Thinking\n3. AI Automation Reality Check\n4. Scalable Workflow & Control System\n5. Case-Based Insight (hype-free)\n\n\u274c **Avoid technical tutorials & beginner-level content.**\n\n---\n\n## \ud83c\udfa5 DEMO WORKFLOW (SHOWCASE ONLY)\n\nDemos are recommended only under these conditions:\n\n* They are not a tutorial or step-by-step guide.\n* They focus on logical flow, integration, control, and business impact.\n* The narrative explains *why this structure was chosen*, risks involved, and common mistakes.\n* The demo should trigger curiosity, not provide a \"recipe.\"\n\n---\n\n## INPUT\n\n* **videoTitle:** {{ $('Limit Search Results').item.json.title }}\n* **channelName:** {{ $('Limit Search Results').item.json.channelName }}\n* **description:** {{ $json.description }}\n* **totalLikes:** {{ $json.totalLikes }}\n* **views:** {{ $json.views }}\n* **topComments:** {{ $json.top20Comments.map((item, i) => ' ' + i + ')' + item.comment + ' likes: ' + item.likes) }}\n\n---\n\n## ANALYSIS FRAMEWORK\n\n### 1. COMMENT ANALYSIS\n\nFocus on:\n\n* Decision confusion\n* Operational frustration\n* Skepticism & unrealistic expectations\n* Structural issues (rather than tool-specific issues)\n\n**Categories:**\n\n* Decision Confusion\n* Operational Frustration\n* Skepticism\n* Experience Insight\n* Validation\n\n### 2. AUDIENCE PROFILE\n\n* **Goals:** Reduce operational burden, increase oversight/control.\n* **Needs:** Thinking frameworks & decision validation.\n* **Pain Points:** Owner as the bottleneck, failed automation attempts.\n* **Challenges:** Misplaced priorities, over-optimization of tools.\n\n### 3. CONTENT OPPORTUNITIES\n\nPrioritize topics that:\n\n* Correct popular assumptions.\n* Halt implementation errors.\n* Highlight systemic issues.\n\n---\n\n## STRUCTURE OF THE 5 CONTENT IDEAS\n\nFor each idea, provide:\n\n1. **Title** \u2014 Problem & decision-based.\n2. **Brief** \u2014 Business impact (2\u20133 sentences).\n3. **Angle** \u2014 Unique perspective from a Chief Solution Officer.\n4. **Why This Topic** \u2014 Connection to audience insights/comments.\n5. **Format** \u2014 Strategic video / system demo / case breakdown.\n6. **Key Points** \u2014 5 strategic points (non-technical).\n7. **Engagement Potential** \u2014 High / Medium / Low + reasoning.\n\n---\n\n## OUTPUT FORMAT (JSON)\n\n{\n  \"analysis\": {\n    \"audienceProfile\": {\n      \"goals\": [\"goal 1\", \"goal 2\", \"goal 3\"],\n      \"needs\": [\"need 1\", \"need 2\", \"need 3\"],\n      \"painPoints\": [\"pain 1\", \"pain 2\", \"pain 3\"],\n      \"challenges\": [\"challenge 1\", \"challenge 2\", \"challenge 3\"]\n    },\n    \"keyInsights\": [\n      \"Insight 1 - supported by specific comments\",\n      \"Insight 2 - supported by engagement patterns\",\n      \"Insight 3 - supported by topic gaps\"\n    ],\n    \"topCommentAnalysis\": {\n      \"mostEngagedTheme\": \"Theme from the most liked comments\",\n      \"topicGaps\": [\"Gap 1\", \"Gap 2\", \"Gap 3\"]\n    }\n  },\n  \"contentIdeas\": [\n    {\n      \"id\": 1,\n      \"title\": \"Content Idea Title\",\n      \"brief\": \"2-3 sentence brief\",\n      \"angle\": \"1-2 sentence unique angle\",\n      \"whyThisTopic\": \"Connection to audience insight\",\n      \"format\": \"Content format - reasoning\",\n      \"keyPoints\": [\"Point 1\", \"Point 2\", \"Point 3\", \"Point 4\", \"Point 5\"],\n      \"engagementPotential\": \"High/Medium/Low - reasoning\"\n    }\n  ],\n  \"strategy\": {\n    \"overallTheme\": \"General theme of the 5 ideas\",\n    \"publishingOrder\": \"Suggested publication order and reasoning\",\n    \"seriesOpportunity\": \"Can this be a series? How to link them?\"\n  }\n}\n\n\n---\n\n## FINAL PRINCIPLES\n\nEvery content idea must have:\n\n* A **Hook** that is relatable to a broad professional audience.\n* A **Mid-section** that corrects the viewer's mindset/approach.\n* A **Closing** that reinforces your authority."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3.1
    },
    {
      "id": "53826d14-f904-4b5c-acf7-f8e8d3e815bf",
      "name": "Store Competitor Data",
      "type": "n8n-nodes-base.notion",
      "position": [
        -2048,
        -656
      ],
      "parameters": {
        "title": "={{ $('Split Video Items').item.json.title }}",
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "2d7bf4c7-dad2-8037-a141-d86dff2712b6",
          "cachedResultUrl": "https://www.notion.so/2d7bf4c7dad28037a141d86dff2712b6",
          "cachedResultName": "Competitor Content Insigth"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Description|rich_text",
              "textContent": "={{ $('Extract Audience Comments').item.json.description }}"
            },
            {
              "key": "URL|url",
              "urlValue": "={{ $('Extract Audience Comments').item.json.url }}"
            },
            {
              "key": "Likes|rich_text",
              "textContent": "={{ $('Extract Audience Comments').item.json.totalLikes }}"
            },
            {
              "key": "Views|rich_text",
              "textContent": "={{ $('Extract Audience Comments').item.json.views }}"
            },
            {
              "key": "AudienceInsigths|rich_text",
              "textContent": "=Goals: {{ $json.output.analysis.audienceProfile.goals }}\n\nNeeds: {{ $json.output.analysis.audienceProfile.needs }}\n\nPain Points: {{ $json.output.analysis.audienceProfile.painPoints }}\n\nChallenges: {{ $json.output.analysis.audienceProfile.challenges }}\n"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "02c19438-38a2-4a6d-b71b-9b50c77d61fc",
      "name": "Store Content Strategy",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1152,
        -656
      ],
      "parameters": {
        "title": "={{ $json.title }}",
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "2d7bf4c7-dad2-8027-a02f-fc9c481a529a",
          "cachedResultUrl": "https://www.notion.so/2d7bf4c7dad28027a02ffc9c481a529a",
          "cachedResultName": "Content Idea"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Angle|rich_text",
              "textContent": "={{ $json.angle }}"
            },
            {
              "key": "Brief|rich_text",
              "textContent": "={{ $json.brief }}"
            },
            {
              "key": "Idea Number|number",
              "numberValue": "={{ $json.id }}"
            },
            {
              "key": "Format|rich_text",
              "textContent": "={{ $json.format }}"
            },
            {
              "key": "Reference|url",
              "urlValue": "={{ $('Store Competitor Data').item.json.url }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "de7c2258-2e69-43cf-8c3b-778733aab586",
      "name": "Set Video Analysis Limit",
      "type": "n8n-nodes-base.limit",
      "position": [
        -1376,
        -656
      ],
      "parameters": {
        "maxItems": 100
      },
      "typeVersion": 1
    },
    {
      "id": "e5c45cdf-4d1d-48d9-bb8e-fcb9c5fdde28",
      "name": "Monthly Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -4640,
        -532
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "months"
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "07687b5f-6b21-4819-8df2-0636a5512674",
      "name": "Limit Search Results",
      "type": "n8n-nodes-base.limit",
      "position": [
        -3296,
        -532
      ],
      "parameters": {
        "maxItems": "={{ $('Set Niche').item.json.limit }}"
      },
      "typeVersion": 1
    },
    {
      "id": "a63767de-6d1c-4bd4-917f-540dab421534",
      "name": "Split Video Items",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -3520,
        -532
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "videos"
      },
      "typeVersion": 1
    },
    {
      "id": "fad0e94c-d6a0-43ca-896a-e24c05c21964",
      "name": "Split Content Ideas",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -1600,
        -656
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "contentIdeas"
      },
      "typeVersion": 1
    },
    {
      "id": "37b57d42-c4e7-44dc-beb3-af6a00b60902",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4712,
        -916
      ],
      "parameters": {
        "color": 6,
        "width": 1584,
        "height": 544,
        "content": "## Step 1: Fetch & Filter Videos"
      },
      "typeVersion": 1
    },
    {
      "id": "da68bc51-954a-4944-ae82-746a88e730bc",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3120,
        -916
      ],
      "parameters": {
        "width": 640,
        "height": 544,
        "content": "## Step 2: Scrape & Extract Insights"
      },
      "typeVersion": 1
    },
    {
      "id": "9cd01b0e-750a-46bf-ae9c-3f1422931785",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2448,
        -832
      ],
      "parameters": {
        "color": 3,
        "width": 320,
        "height": 544,
        "content": "## Step 3: AI Strategy Generation"
      },
      "typeVersion": 1
    },
    {
      "id": "42a67a0e-afb5-498c-a4aa-ac8fa2d74d69",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2112,
        -916
      ],
      "parameters": {
        "color": 5,
        "width": 1344,
        "height": 544,
        "content": "## Step 4: Save to Notion"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "bc32fa99-70a3-4060-b21b-3b349e872e21",
  "connections": {
    "Aggregate": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Niche": {
      "main": [
        [
          {
            "node": "Search YouTube Videos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ContentIdeas": {
      "main": [
        [
          {
            "node": "Split Content Ideas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Scrape Video Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Monthly Trigger": {
      "main": [
        [
          {
            "node": "Set Niche",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Video List": {
      "main": [
        [
          {
            "node": "Split Video Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Identify Strategic Gaps",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Split Video Items": {
      "main": [
        [
          {
            "node": "Limit Search Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Search Status": {
      "main": [
        [
          {
            "node": "Parse Video List",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Content Ideas": {
      "main": [
        [
          {
            "node": "Set Video Analysis Limit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limit Search Results": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Video Details": {
      "main": [
        [
          {
            "node": "Extract Audience Comments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search YouTube Videos": {
      "main": [
        [
          {
            "node": "Check Search Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store Competitor Data": {
      "main": [
        [
          {
            "node": "ContentIdeas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store Content Strategy": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Identify Strategic Gaps": {
      "main": [
        [
          {
            "node": "Store Competitor Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Video Analysis Limit": {
      "main": [
        [
          {
            "node": "Store Content Strategy",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Identify Strategic Gaps",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Extract Audience Comments": {
      "main": [
        [
          {
            "node": "Identify Strategic Gaps",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow acts as an autonomous Chief Solution Officer, automating the process of deep market research. Instead of simply tracking video views, it scrapes deep into YouTube data—including descriptions and top 20 comments—to identify the real "Decision Confusion" and…

Source: https://n8n.io/workflows/12509/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This workflow automates short-interval market signal evaluation for intraday trading using live technical indicators and deterministic decision logic. It is designed for traders, analysts, and automat

HTTP Request, Agent, OpenAI Chat +5
AI & RAG

Automate your YouTube research workflow by extracting audio from any video, transcribing it with Whisper AI, and generating structured GEO (Goal–Execution–Outcome) summaries using GPT-4o-mini. 🎥🤖 This

HTTP Request, Notion, YouTube +5
AI & RAG

Discover and analyze the most valuable community-built n8n workflows on GitHub. This automation searches public repositories, analyzes JSON workflows using AI, and saves a ranked report to Google Shee

Notion, HTTP Request, Agent +3
AI & RAG

Complete PostgreSQL-backed system: Keyword scoring → AI research → Multi-part content generation → fal.ai Nano Banana image generation → WordPress publishing

WordPress, OpenAI, Perplexity +8
AI & RAG

LinkedIn_Job_Hunt_and_Cover_Letter. Uses outputParserStructured, outputParserAutofixing, googleDrive, agent. Scheduled trigger; 85 nodes.

Output Parser Structured, Output Parser Autofixing, Google Drive +6