Workflow: YouTube Comment Sentiment Analyzer
Integrations: googleSheets, httpRequest, if, manualTrigger, noOp, set, splitOut, stickyNote

{"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", "tags": ["automation", "n8n", "production-ready", "excellent", "optimized"], "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.2, "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 \u2018Test workflow\u2019", "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# \ud83d\ude80 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\ud83d\udcdd **YouTube Comment Sentiment Analyzer**\n\n1. \ud83d\udd18 **Trigger:** Click \"Execute Workflow\" to run it manually.\n\n2. \ud83d\udcc4 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. \ud83d\udd10 **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. \u2705 **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. \ud83d\udca1 **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, "pinData": {}, "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": {"aad11f42-b976-41d7-b771-151da60391d6": {"main": [[{"node": "error-handler-aad11f42-b976-41d7-b771-151da60391d6", "type": "main", "index": 0}], [{"node": "error-handler-aad11f42-b976-41d7-b771-151da60391d6-0ba81ca7", "type": "main", "index": 0}], [{"node": "error-handler-aad11f42-b976-41d7-b771-151da60391d6-8cd6a596", "type": "main", "index": 0}], [{"node": "error-handler-aad11f42-b976-41d7-b771-151da60391d6-f5eefa92", "type": "main", "index": 0}], [{"node": "error-handler-aad11f42-b976-41d7-b771-151da60391d6-cae656f0", "type": "main", "index": 0}], [{"node": "error-handler-aad11f42-b976-41d7-b771-151da60391d6-cdac2aaf", "type": "main", "index": 0}], [{"node": "error-handler-aad11f42-b976-41d7-b771-151da60391d6-929ac44e", "type": "main", "index": 0}], [{"node": "error-handler-aad11f42-b976-41d7-b771-151da60391d6-544e61b0", "type": "main", "index": 0}], [{"node": "error-handler-aad11f42-b976-41d7-b771-151da60391d6-8dc900c3", "type": "main", "index": 0}]]}, "236aaaab-6a9a-42d7-8645-980bf8c3254d": {"main": [[{"node": "error-handler-236aaaab-6a9a-42d7-8645-980bf8c3254d-119531cd", "type": "main", "index": 0}]]}, "d28f3fbf-6013-47af-ba84-3bdd9800fd3b": {"main": [[{"node": "error-handler-d28f3fbf-6013-47af-ba84-3bdd9800fd3b-d4d6d825", "type": "main", "index": 0}]]}, "6cd20a6e-8bcc-44c7-a62d-e3c3c75e6d9a": {"main": [[{"node": "error-handler-6cd20a6e-8bcc-44c7-a62d-e3c3c75e6d9a-794bc2c5", "type": "main", "index": 0}]]}, "ea240f38-1462-402b-8db2-36b3e8664c2f": {"main": [[{"node": "error-handler-ea240f38-1462-402b-8db2-36b3e8664c2f-83ebd389", "type": "main", "index": 0}]]}}, "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."}