AutomationFlowsAI & RAG › Analyze Youtube Comments with Openai, Google Sheets, and Gmail

Analyze Youtube Comments with Openai, Google Sheets, and Gmail

ByDr. Firas @drfiras on n8n.io

This workflow monitors a Google Sheets list of YouTube video IDs, fetches video details and top comments from the YouTube Data API, analyzes the comments with OpenAI into structured sentiment and themes, emails an HTML report via Gmail, and writes the results back to Google…

Event trigger★★★★☆ complexityAI-powered19 nodesGoogle Sheets TriggerHTTP RequestAgentOpenAI ChatOutput Parser StructuredGmailGoogle Sheets
AI & RAG Trigger: Event Nodes: 19 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Gmail 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": "pCRKZFvaYZndbmAU",
  "meta": {
    "builderVariant": "mcp",
    "aiBuilderAssisted": true
  },
  "name": "Analyze YouTube video comments with AI and email a report",
  "tags": [],
  "nodes": [
    {
      "id": "d7c0d19c-e23b-4dea-b7b1-e3b5be0f3cf4",
      "name": "Watch spreadsheet for videos",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "position": [
        -176,
        -576
      ],
      "parameters": {
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1NgEltUNbMRChjcatY7j7HvHwlbeq75_lnu2EnpV9UAc",
          "cachedResultName": "YouTube_Video"
        }
      },
      "credentials": {
        "googleSheetsTriggerOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0fae7829-664e-4c2d-b5a1-04ec8bc2e5be",
      "name": "Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        0,
        -576
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c1",
              "name": "video_id",
              "type": "string",
              "value": "={{ $json['Video ID'] }}"
            },
            {
              "id": "c2",
              "name": "video_status",
              "type": "string",
              "value": "={{ $json['Status'] }}"
            },
            {
              "id": "c3",
              "name": "row_number",
              "type": "number",
              "value": "={{ $json.row_number }}"
            },
            {
              "id": "c4",
              "name": "pending_value",
              "type": "string",
              "value": "Pending"
            },
            {
              "id": "c5",
              "name": "max_comments",
              "type": "number",
              "value": 100
            },
            {
              "id": "c6",
              "name": "comments_for_ai",
              "type": "number",
              "value": 60
            },
            {
              "id": "c7",
              "name": "comment_order",
              "type": "string",
              "value": "relevance"
            },
            {
              "id": "c8",
              "name": "output_language",
              "type": "string",
              "value": "English"
            },
            {
              "id": "c9",
              "name": "openai_model",
              "type": "string",
              "value": "gpt-5.4-mini"
            },
            {
              "id": "c10",
              "name": "email_recipient",
              "type": "string",
              "value": "you@example.com"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "71188d12-204b-4793-8939-c24b94147e8c",
      "name": "Keep only pending videos",
      "type": "n8n-nodes-base.filter",
      "position": [
        160,
        -576
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.video_status }}",
              "rightValue": "={{ $json.pending_value }}"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "16f63c04-c002-4229-84c7-ff433ec5f184",
      "name": "Get video details",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        384,
        -576
      ],
      "parameters": {
        "url": "https://www.googleapis.com/youtube/v3/videos",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpQueryAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "part",
              "value": "snippet,statistics"
            },
            {
              "name": "id",
              "value": "={{ $('Configuration').item.json.video_id }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "d3c641a5-127a-479b-bf08-730210711211",
      "name": "Fetch top comments",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        704,
        -576
      ],
      "parameters": {
        "url": "https://www.googleapis.com/youtube/v3/commentThreads",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpQueryAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "part",
              "value": "snippet"
            },
            {
              "name": "videoId",
              "value": "={{ $('Configuration').item.json.video_id }}"
            },
            {
              "name": "maxResults",
              "value": "={{ $('Configuration').item.json.max_comments }}"
            },
            {
              "name": "order",
              "value": "={{ $('Configuration').item.json.comment_order }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "b873f9a3-fe27-4a9c-8b62-59d3e8b7d072",
      "name": "Prepare comments for AI",
      "type": "n8n-nodes-base.code",
      "notes": "Aggregates the nested commentThreads array into flat stats + a single text block for the LLM. Native nodes cannot flatten this nested shape and compute stats in one clean step.",
      "position": [
        960,
        -656
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const res = $input.item.json;\nconst threads = Array.isArray(res.items) ? res.items : [];\nconst comments = threads.map(function(t){ var s = t.snippet.topLevelComment.snippet; return { text: s.textDisplay, likes: s.likeCount || 0 }; });\nconst total = comments.length;\nconst totalLikes = comments.reduce(function(a,c){ return a + c.likes; }, 0);\nconst avg = total ? Number((totalLikes/total).toFixed(1)) : 0;\nconst n = $('Configuration').item.json.comments_for_ai || 60;\nconst block = comments.slice(0, n).map(function(c,i){ return (i+1) + '. (' + c.likes + ' likes) ' + c.text; }).join('\\n---\\n');\nreturn { comment_count: total, avg_likes: avg, comments_block: block };"
      },
      "typeVersion": 2
    },
    {
      "id": "4eb60f65-8831-4a10-9159-f4ba6d015c13",
      "name": "Has comments?",
      "type": "n8n-nodes-base.if",
      "position": [
        1152,
        -656
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "h1",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.comment_count }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "9f128854-c36c-4d97-9c02-056435ee2a76",
      "name": "Analyze comments with AI",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1312,
        -704
      ],
      "parameters": {
        "text": "=Analyze the audience comments for the YouTube video: {{ $('Get video details').item.json.items[0].snippet.title }}.\n\nTotal comments analyzed: {{ $json.comment_count }}\nAverage likes per comment: {{ $json.avg_likes }}\n\nComments:\n{{ $json.comments_block }}",
        "options": {
          "systemMessage": "=You are a senior YouTube audience analyst. Read the viewer comments and produce a rigorous, structured analysis. Base every conclusion only on the comments provided. Write all textual fields (summary, main_themes, common_questions, key_feedback, actionable_insights) in {{ $('Configuration').item.json.output_language }}. The percentages in overall_sentiment must be integers that add up to about 100. sentiment_score is an integer from 1 (very negative) to 5 (very positive). Always fill every field defined in the output schema; use an empty array when a category has no items."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3.1
    },
    {
      "id": "20bce8b1-0323-4661-ab85-3a79bf4429d1",
      "name": "OpenAI analysis model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1312,
        -480
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Configuration').item.json.openai_model }}"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "3b690bfa-94dd-4075-b78a-4d71adf1151b",
      "name": "Structured analysis parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1440,
        -464
      ],
      "parameters": {
        "autoFix": true,
        "schemaType": "manual",
        "inputSchema": "{\"type\":\"object\",\"properties\":{\"sentiment_score\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":5},\"overall_sentiment\":{\"type\":\"object\",\"properties\":{\"positive_pct\":{\"type\":\"integer\"},\"negative_pct\":{\"type\":\"integer\"},\"neutral_pct\":{\"type\":\"integer\"}},\"required\":[\"positive_pct\",\"negative_pct\",\"neutral_pct\"]},\"main_themes\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"common_questions\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"key_feedback\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"actionable_insights\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"summary\":{\"type\":\"string\"}},\"required\":[\"sentiment_score\",\"overall_sentiment\",\"main_themes\",\"summary\"]}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "1a0bdf5c-c776-415b-8f14-affda9877b9d",
      "name": "Output fixer model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1440,
        -320
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Configuration').item.json.openai_model }}"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "ac29d2c2-459c-48c1-affc-224fde738c28",
      "name": "Build email report",
      "type": "n8n-nodes-base.code",
      "notes": "Templates the structured AI output into an HTML email body. Multi-array HTML templating is far cleaner here than a long Set expression.",
      "position": [
        1760,
        -592
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const o = ($input.item.json.output) || {};\nconst vd = $('Get video details').item.json;\nconst title = (vd.items && vd.items[0] && vd.items[0].snippet) ? vd.items[0].snippet.title : 'this video';\nconst s = o.overall_sentiment || {};\nconst pc = $('Prepare comments for AI').item.json;\nfunction ul(arr){ return '<ul>' + (arr||[]).map(function(x){ return '<li>' + x + '</li>'; }).join('') + '</ul>'; }\nconst html = '<div style=\"font-family:Arial,sans-serif;color:#333;max-width:640px\">'\n + '<h2 style=\"color:#c4302b;margin-bottom:4px\">YouTube comment analysis</h2>'\n + '<h3 style=\"margin-top:0\">' + title + '</h3>'\n + '<p><b>Comments analyzed:</b> ' + pc.comment_count + ' &nbsp; <b>Avg likes:</b> ' + pc.avg_likes + '</p>'\n + '<p><b>Sentiment score:</b> ' + o.sentiment_score + '/5 &nbsp; (positive ' + s.positive_pct + '% - negative ' + s.negative_pct + '% - neutral ' + s.neutral_pct + '%)</p>'\n + '<h4>Summary</h4><p>' + (o.summary || '') + '</p>'\n + '<h4>Main themes</h4>' + ul(o.main_themes)\n + '<h4>Common questions</h4>' + ul(o.common_questions)\n + '<h4>Key feedback</h4>' + ul(o.key_feedback)\n + '<h4>Actionable insights</h4>' + ul(o.actionable_insights)\n + '<hr><p style=\"font-size:12px;color:#888\">Generated automatically with n8n - The AI Doctor</p></div>';\nconst subject = 'YouTube analysis: ' + title + ' - sentiment ' + (o.sentiment_score || '?') + '/5';\nreturn { email_subject: subject, email_html: html };"
      },
      "typeVersion": 2
    },
    {
      "id": "b7eece65-563f-4fe2-973e-548816f193ed",
      "name": "Email the report",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1968,
        -592
      ],
      "parameters": {
        "sendTo": "={{ $('Configuration').item.json.email_recipient }}",
        "message": "={{ $json.email_html }}",
        "options": {},
        "subject": "={{ $json.email_subject }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "4fc7afa5-812d-42cb-aadc-bec22daea3e7",
      "name": "Log analysis to sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2224,
        -592
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "Analyzed",
            "Summary": "={{ $('Analyze comments with AI').item.json.output.summary }}",
            "Video ID": "={{ $('Configuration').item.json.video_id }}",
            "Neutral %": "={{ $('Analyze comments with AI').item.json.output.overall_sentiment.neutral_pct }}",
            "Negative %": "={{ $('Analyze comments with AI').item.json.output.overall_sentiment.negative_pct }}",
            "Positive %": "={{ $('Analyze comments with AI').item.json.output.overall_sentiment.positive_pct }}",
            "Top Themes": "={{ $('Analyze comments with AI').item.json.output.main_themes.join(', ') }}",
            "Analyzed At": "={{ $now.toISO() }}",
            "Sentiment Score": "={{ $('Analyze comments with AI').item.json.output.sentiment_score }}"
          },
          "schema": [
            {
              "id": "Video ID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Video ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Sentiment Score",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Sentiment Score",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Positive %",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Positive %",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Negative %",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Negative %",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Neutral %",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Neutral %",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Top Themes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Top Themes",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Summary",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Analyzed At",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Analyzed At",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Video ID"
          ]
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1NgEltUNbMRChjcatY7j7HvHwlbeq75_lnu2EnpV9UAc",
          "cachedResultName": "YouTube_Video"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "e613b3b0-0991-4b89-ad4d-8e812fc346fd",
      "name": "Mark row as no comments",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1056,
        -464
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "No comments",
            "Video ID": "={{ $('Configuration').item.json.video_id }}",
            "Analyzed At": "={{ $now.toISO() }}"
          },
          "schema": [
            {
              "id": "Video ID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Video ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Analyzed At",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Analyzed At",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Video ID"
          ]
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1NgEltUNbMRChjcatY7j7HvHwlbeq75_lnu2EnpV9UAc",
          "cachedResultName": "YouTube_Video"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "17de84b9-fe42-4711-87e5-85ecd9bc24e6",
      "name": "Sticky Note 1ff6c42e",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -976,
        -944
      ],
      "parameters": {
        "width": 740,
        "height": 1832,
        "content": "# Analyze YouTube video comments with AI and email a report\n# \ud83d\udce5  [Open full documentation on Notion](https://automatisation.notion.site/Analyze-YouTube-video-comments-with-AI-and-email-a-report-Course-39b3d6550fd981f0be27f5d4fa6f5934)\n\nThis workflow watches a Google Sheet of YouTube video IDs, pulls each video's top comments, runs an AI sentiment + theme analysis, emails a formatted report, and writes the results back to the sheet.\n\n## How it works\n1. A Google Sheet row set to `Pending` triggers the run.\n2. **Configuration** centralises every setting (model, language, comment count, recipient).\n3. The YouTube Data API returns the video metadata and top comments.\n4. An AI Agent with a Structured Output Parser scores sentiment and extracts themes, questions, feedback and insights.\n5. A formatted HTML report is emailed, and the sentiment/summary is written back to the sheet.\n\n## Setup\n1. Duplicate a Google Sheet with columns: `Video ID`, `Video Title`, `Status` (add `Sentiment Score`, `Positive %`, `Negative %`, `Neutral %`, `Top Themes`, `Summary`, `Analyzed At`).\n2. Select your Google Sheets credential on the trigger and both sheet nodes, and pick the document + tab.\n3. Create a **YouTube Data API v3** key in Google Cloud and add it to the `YouTube Data API Key` credential (Query Auth, name `key`).\n4. Select your OpenAI and Gmail credentials.\n5. Open **Configuration** and set `email_recipient`.\n\n## Requirements\n- Google account (Sheets + Gmail)\n- YouTube Data API v3 key\n- OpenAI API key\n\n## Customization\n- Change `openai_model`, `output_language`, `max_comments`, `comment_order` in Configuration.\n- Swap Gmail for Slack/Telegram, or extend the output columns.\n\n---\nNeed help customizing?\nContact me for consulting and support : [Linkedin](https://www.linkedin.com/in/doctor-firass/)\n\n# MY NEW YOUTUBE CHANNEL\n\ud83d\udc49 [Subscribe to my new YouTube channel](https://www.youtube.com/@DrFiras_AI). Here I'll share videos and Shorts with practical tutorials and FREE templates for n8n.\n\n[![The AI Doctor](https://www.dr-firas.com/the-ai-doctor.png)](https://www.youtube.com/@DrFiras_AI)"
      },
      "typeVersion": 1
    },
    {
      "id": "939a4aa0-1782-4651-87ad-f573260875b1",
      "name": "Sticky Note 2bfd975f",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        336,
        -848
      ],
      "parameters": {
        "color": 7,
        "width": 520,
        "height": 440,
        "content": "## Fetch YouTube data\nPulls video metadata and the top comments via the YouTube Data API v3 (API key)."
      },
      "typeVersion": 1
    },
    {
      "id": "fdd0189a-725c-47b7-a03e-237c4d224c65",
      "name": "Sticky Note 4795d65a",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        912,
        -848
      ],
      "parameters": {
        "color": 7,
        "width": 740,
        "height": 440,
        "content": "## AI comment analysis\nFlattens comments, then an AI Agent + Structured Output Parser returns sentiment, themes, questions, feedback and insights."
      },
      "typeVersion": 1
    },
    {
      "id": "f161ed4c-b780-41bb-a99b-847a3e2c76a8",
      "name": "Sticky Note 63a9dd65",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1712,
        -848
      ],
      "parameters": {
        "color": 7,
        "width": 740,
        "height": 456,
        "content": "## Report & logging\nBuilds an HTML report, emails it, and writes the analysis back to the sheet. No-comment videos are flagged instead."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "versionId": "2cbb7608-f938-4b8d-a7b7-74b1f3fa6dd0",
  "nodeGroups": [],
  "connections": {
    "Configuration": {
      "main": [
        [
          {
            "node": "Keep only pending videos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has comments?": {
      "main": [
        [
          {
            "node": "Analyze comments with AI",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark row as no comments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email the report": {
      "main": [
        [
          {
            "node": "Log analysis to sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get video details": {
      "main": [
        [
          {
            "node": "Fetch top comments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build email report": {
      "main": [
        [
          {
            "node": "Email the report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch top comments": {
      "main": [
        [
          {
            "node": "Prepare comments for AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Output fixer model": {
      "ai_languageModel": [
        [
          {
            "node": "Structured analysis parser",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI analysis model": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze comments with AI",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Prepare comments for AI": {
      "main": [
        [
          {
            "node": "Has comments?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze comments with AI": {
      "main": [
        [
          {
            "node": "Build email report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keep only pending videos": {
      "main": [
        [
          {
            "node": "Get video details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured analysis parser": {
      "ai_outputParser": [
        [
          {
            "node": "Analyze comments with AI",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Watch spreadsheet for videos": {
      "main": [
        [
          {
            "node": "Configuration",
            "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 monitors a Google Sheets list of YouTube video IDs, fetches video details and top comments from the YouTube Data API, analyzes the comments with OpenAI into structured sentiment and themes, emails an HTML report via Gmail, and writes the results back to Google…

Source: https://n8n.io/workflows/17088/ — 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 automation is designed to help you generate AI-powered music tracks, cover art, and fully rendered music videos — all triggered from a simple Telegram chat and managed via Google Sheets.

OpenAI Chat, Memory Buffer Window, Output Parser Structured +11
AI & RAG

Automated Book Generation System. Uses googleSheetsTrigger, gmail, lmChatOpenAi, outputParserStructured. Event-driven trigger; 43 nodes.

Google Sheets Trigger, Gmail, OpenAI Chat +6
AI & RAG

Want to skip the manual work and instantly generate SWOT analyses for your business plans, investor decks, or strategy docs? 🚀 This workflow lets you automate the entire SWOT (Strengths, Weaknesses, O

Google Sheets, Agent, Output Parser Structured +4
AI & RAG

The workflow runs every hour with a randomized delay of 5–20 minutes to help distribute load. It records the exact date and time a lead is emailed so you can track outreach. Follow-ups are automatical

Google Sheets, Agent, OpenAI Chat +5
AI & RAG

Enterprise-grade resume screening automation built for production environments. This workflow combines intelligent AI analysis with comprehensive error handling to ensure reliable processing of candid

Gmail Trigger, Google Drive, HTTP Request +6