{"id":"xaC6zL4bWBo14xyJ","meta":{"instanceId":"workflow-3d3a83fb","versionId":"1.0.0","createdAt":"2025-09-29T07:07:54.777612","updatedAt":"2025-09-29T07:07:54.777621","owner":"n8n-user","license":"MIT","category":"automation","status":"active","priority":"high","environment":"production"},"name":"YouTube Comment Sentiment Analyzer","nodes":[{"id":"0bacd739-7ea3-42f5-8986-2f7d47628ee9","name":"Split Out","type":"n8n-nodes-base.splitOut","position":[820,-40],"parameters":{"options":{},"fieldToSplitOut":"body.items"},"typeVersion":1,"notes":"This splitOut node performs automated tasks as part of the workflow."},{"id":"236aaaab-6a9a-42d7-8645-980bf8c3254d","name":"OpenAI Chat Model","type":"n8n-nodes-base.noOp","position":[1080,180],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"credentials":{"openAiApi":{"id":"4d73v7kxEDNu3n25","name":"OpenAi account"}},"typeVersion":1,"notes":"This lmChatOpenAi node performs automated tasks as part of the workflow."},{"id":"c1eda3a6-9fbe-4150-8086-c3ffebaeb2e1","name":"No Operation, do nothing","type":"n8n-nodes-base.noOp","position":[380,140],"parameters":{},"typeVersion":1,"notes":"This noOp node performs automated tasks as part of the workflow."},{"id":"d28f3fbf-6013-47af-ba84-3bdd9800fd3b","name":"Get Video Urls from Google Sheet","type":"n8n-nodes-base.googleSheets","position":[-200,-40],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":760258523,"cachedResultUrl":"{{ $env.WEBHOOK_URL }}","cachedResultName":"Sheet2"},"documentId":{"__rl":true,"mode":"list","value":"1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4","cachedResultUrl":"{{ $env.WEBHOOK_URL }}","cachedResultName":"Youtube Videos Comments"},"authentication":"{{ $credentials.serviceAccount }}"},"credentials":{"googleApi":{"id":"jPoTdPxgVL0vr9SQ","name":"Google Sheets account"}},"typeVersion":4.5,"notes":"This googleSheets node performs automated tasks as part of the workflow."},{"id":"0ac06530-cfe7-4f1c-8c0a-8def2126df0f","name":"check next fetch time is available or not","type":"n8n-nodes-base.if","position":[-20,-40],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"92084960-e023-4cd6-a5c0-ddd43275cc33","operator":{"type":"string","operation":"empty","singleValue":true},"leftValue":"={{ $json.next_fetch_time }}","rightValue":"={{ $now.toISO() }}"}]}},"typeVersion":2.2,"notes":"This if node performs automated tasks as part of the workflow."},{"id":"ba42f450-3b0c-41a3-8e72-d2a38b97cfc7","name":"check next fetch time is before the current time","type":"n8n-nodes-base.if","position":[160,80],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"40c8d081-b298-46b1-850c-2322ed89d18d","operator":{"type":"dateTime","operation":"before"},"leftValue":"={{ $json.next_fetch_time }}","rightValue":"={{ $now.toISO() }}"}]}},"typeVersion":2.2,"notes":"This if node performs automated tasks as part of the workflow."},{"id":"aad11f42-b976-41d7-b771-151da60391d6","name":"Get Comments for video urls","type":"n8n-nodes-base.httpRequest","position":[360,-60],"parameters":{"url":"{{ $env.API_BASE_URL }}","options":{"response":{"response":{"fullResponse":true,"responseFormat":"json"}},"pagination":{"pagination":{"parameters":{"parameters":[{"name":"pageToken","value":"={{ $response.body.nextPageToken }}"}]},"completeExpression":"={{ !$response.body.nextPageToken}}","paginationCompleteWhen":"other"}}},"sendQuery":true,"authentication":"{{ $credentials.genericCredentialType }}","genericAuthType":"httpQueryAuth","queryParameters":{"parameters":[{"name":"part","value":"snippet"},{"name":"videoId","value":"={{ $json[\"video_urls\"].match(/(?:v=|\\/)([0-9A-Za-z_-]{11})/)[1] || ''}}"},{"name":"maxResults","value":"100"}]}},"credentials":{"httpQueryAuth":{"id":"LmsYEaslJmA6CMdL","name":"Query Auth account 4"}},"typeVersion":4.2,"notes":"This httpRequest node performs automated tasks as part of the workflow."},{"id":"4cf1ebd0-e260-4e53-bc26-be1db2f6e7f2","name":"Analyze sentiment of every comment","type":"n8n-nodes-base.noOp","position":[1060,-40],"parameters":{"options":{"categories":"Positive, Neutral, Negative","systemPromptTemplate":"You are highly intelligent and accurate sentiment analyzer. Analyze the sentiment of the provided text. Categorize it into one of the following: {categories}. Use the provided formatting instructions. Only output the JSON."},"inputText":"={{ $json.snippet.topLevelComment.snippet.textOriginal }}"},"typeVersion":1,"notes":"This sentimentAnalysis node performs automated tasks as part of the workflow."},{"id":"f306c5cd-6b6b-46fa-b7ef-f3ccef960931","name":"Format fields as required to save in google sheet","type":"n8n-nodes-base.set","position":[1500,-40],"parameters":{"options":{},"assignments":{"assignments":[{"id":"25fb96a0-de38-4495-8473-0385a3fd5df9","name":"commentId","type":"string","value":"={{ $json.snippet.topLevelComment.id }}"},{"id":"d824ecd0-89c0-4c07-992f-6a5d3421690e","name":"video_url","type":"string","value":"={{ $env.WEBHOOK_URL }}{{ $json.snippet.videoId }}"},{"id":"cdcbc3d9-ab3e-4d7d-80a7-bfe168b0ed27","name":"comment","type":"string","value":"={{ $json.snippet.topLevelComment.snippet.textOriginal }}"},{"id":"20bcfe96-3904-44d2-b72a-9eb49d603c8d","name":"authorName","type":"string","value":"={{ $json.snippet.topLevelComment.snippet.authorDisplayName }}"},{"id":"c92f56bf-8b37-4c4e-9ce7-b7a49d63deee","name":"likes","type":"string","value":"={{ $json.snippet.topLevelComment.snippet.likeCount }}"},{"id":"7cc4fdb3-7c41-418a-bf4f-71081fe9df74","name":"reply","type":"string","value":"={{ $json.snippet.totalReplyCount }}"},{"id":"9988ea66-7f31-4b2c-90ab-3cad8efabf95","name":"sentiment","type":"string","value":"={{ $json.sentimentAnalysis.category }}"},{"id":"6552df27-6e04-4048-b3c2-1e1755ccac28","name":"published_at","type":"string","value":"={{ $json.snippet.topLevelComment.snippet.publishedAt }}"}]}},"typeVersion":3.4,"notes":"This set node performs automated tasks as part of the workflow."},{"id":"6cd20a6e-8bcc-44c7-a62d-e3c3c75e6d9a","name":"Insert and update comment in google sheet","type":"n8n-nodes-base.googleSheets","position":[1720,-40],"parameters":{"columns":{"value":{},"schema":[{"id":"commentId","type":"string","display":true,"removed":false,"required":false,"displayName":"commentId","defaultMatch":false,"canBeUsedToMatch":true},{"id":"video_url","type":"string","display":true,"required":false,"displayName":"video_url","defaultMatch":false,"canBeUsedToMatch":true},{"id":"comment","type":"string","display":true,"required":false,"displayName":"comment","defaultMatch":false,"canBeUsedToMatch":true},{"id":"authorName","type":"string","display":true,"required":false,"displayName":"authorName","defaultMatch":false,"canBeUsedToMatch":true},{"id":"likes","type":"string","display":true,"required":false,"displayName":"likes","defaultMatch":false,"canBeUsedToMatch":true},{"id":"reply","type":"string","display":true,"required":false,"displayName":"reply","defaultMatch":false,"canBeUsedToMatch":true},{"id":"sentiment","type":"string","display":true,"required":false,"displayName":"sentiment","defaultMatch":false,"canBeUsedToMatch":true},{"id":"published_at","type":"string","display":true,"required":false,"displayName":"published_at","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"autoMapInputData","matchingColumns":["commentId"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"{{ $env.WEBHOOK_URL }}","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4","cachedResultUrl":"{{ $env.WEBHOOK_URL }}","cachedResultName":"Youtube Videos Comments"},"authentication":"{{ $credentials.serviceAccount }}"},"credentials":{"googleApi":{"id":"jPoTdPxgVL0vr9SQ","name":"Google Sheets account"}},"typeVersion":4.5,"notes":"This googleSheets node performs automated tasks as part of the workflow."},{"id":"ea240f38-1462-402b-8db2-36b3e8664c2f","name":"Update last fetched time and next_fetch_time","type":"n8n-nodes-base.googleSheets","position":[1940,-40],"parameters":{"columns":{"value":{"video_urls":"{{ $env.BASE_URL }}","next_fetch_time":"={{ $now.plus(5, 'min').toISO() }}","last_fetched_time":"={{ $now.toISO() }}"},"schema":[{"id":"video_urls","type":"string","display":true,"removed":false,"required":false,"displayName":"video_urls","defaultMatch":false,"canBeUsedToMatch":true},{"id":"last_fetched_time","type":"string","display":true,"required":false,"displayName":"last_fetched_time","defaultMatch":false,"canBeUsedToMatch":true},{"id":"next_fetch_time","type":"string","display":true,"required":false,"displayName":"next_fetch_time","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["video_urls"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":760258523,"cachedResultUrl":"{{ $env.WEBHOOK_URL }}","cachedResultName":"Sheet2"},"documentId":{"__rl":true,"mode":"list","value":"1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4","cachedResultUrl":"{{ $env.WEBHOOK_URL }}","cachedResultName":"Youtube Videos Comments"},"authentication":"{{ $credentials.serviceAccount }}"},"credentials":{"googleApi":{"id":"jPoTdPxgVL0vr9SQ","name":"Google Sheets account"}},"typeVersion":4.5,"notes":"This googleSheets node performs automated tasks as part of the workflow."},{"id":"610fa83c-a626-42c0-aa8b-1ebb1a6bcf44","name":"No Operation, do nothing1","type":"n8n-nodes-base.noOp","position":[820,140],"parameters":{},"typeVersion":1,"notes":"This noOp node performs automated tasks as part of the workflow."},{"id":"30570a68-78b8-434e-bb20-ea85a0689a63","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[-380,-40],"parameters":{},"typeVersion":1,"notes":"This manualTrigger node performs automated tasks as part of the workflow."},{"id":"4fe79a97-fc39-41c0-9d2f-f07865deef5e","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-440,-160],"parameters":{"color":5,"width":2620,"height":480,"content":"\n# 🚀 YouTube Comment Sentiment Analyzer with Google Sheets & OpenAI"},"typeVersion":1,"notes":"This stickyNote node performs automated tasks as part of the workflow."},{"id":"0ccb85d8-d29e-44a7-b644-49b3dcc6ce9b","name":"Check Success Response","type":"n8n-nodes-base.if","position":[560,-60],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"bce76f94-5904-4fdb-b172-adc1134855f9","operator":{"type":"number","operation":"equals"},"leftValue":"={{ $json.statusCode }}","rightValue":200}]}},"typeVersion":2.2,"notes":"This if node performs automated tasks as part of the workflow."},{"id":"880f570f-6300-4659-9dcf-d47880140131","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-1100,-500],"parameters":{"width":640,"height":820,"content":"### **How to Use This Workflow:**\n📝 **YouTube Comment Sentiment Analyzer**\n\n1. 🔘 **Trigger:** Click \"Execute Workflow\" to run it manually.\n\n2. 📄 Your Google Sheet should have **2 sheets**:\n   - **Sheet1 (Results with Sentiment):**\n     - Column A: `commentId` (YouTube comment id)\n     - Column B: `video_url` (url of video)\n     - Column C: `comment` (YouTube comment)\n     - Column D: `authorName` (Name of author as per Youtube)\n     - Column E: `likes` (Number of likes on that particular comment)\n     - Column f: `reply` (Number of replies on that particular comment)\n     - Column g: `sentiment` (Analyzed sentiment of the comment)\n     - Column h: `published_at` (timestamp of comment published)\n   \n   - **Sheet2 (Video URLs):**\n     - Column A: `video_urls` (list of YouTube video URLs)\n     - Column B: `last_fetched_time` (timestamp of the last fetch)\n     - Column C: `next_fetch_time` (time for the next fetch)\n\n3. 🔐 **Make sure these credentials are set up**:\n   - Google Sheets (Service Account)\n   - YouTube Data API v3\n   - OpenAI API Key (for sentiment analysis)\n\n4. ✅ **What this workflow does**:\n   - Reads **video URLs** from **Sheet2**.\n   - Checks **last fetched time** (if applicable).\n   - Fetches new comments from YouTube.\n   - Analyzes sentiment using OpenAI.\n   - Appends **comment**, **sentiment**, **video ID**, and **timestamp** to **Sheet1**.\n   - Updates **last_fetched** timestamp in **Sheet2**.\n\n5. 💡 **Tip:**\n   - You can replace the **Manual Trigger** with a **Cron node** for automatic execution at specified intervals.\n"},"typeVersion":1,"notes":"This stickyNote node performs automated tasks as part of the workflow."}],"active":false,"settings":{"executionOrder":"v1","saveManualExecutions":true,"callerPolicy":"workflowsFromSameOwner","errorWorkflow":null,"timezone":"UTC","executionTimeout":3600,"maxExecutions":1000,"retryOnFail":true,"retryCount":3,"retryDelay":1000},"versionId":"70007187-7437-4053-b909-5057bf816906","connections":{"Get Comments for video urls":{"main":[[],[],[],[],[],[],[],[],[]]},"OpenAI Chat Model":{"main":[[]]},"Get Video Urls from Google Sheet":{"main":[[]]},"Insert and update comment in google sheet":{"main":[[]]},"Update last fetched time and next_fetch_time":{"main":[[]]}},"description":"Automated workflow: YouTube Comment Sentiment Analyzer. This workflow integrates 11 different services: stickyNote, httpRequest, splitOut, noOp, set. It contains 22 nodes and follows best practices for error handling and security.","notes":"Excellent quality workflow: YouTube Comment Sentiment Analyzer. This workflow has been optimized for production use with comprehensive error handling, security, and documentation."}