AutomationFlowsAI & RAG › Analyze Google Business Reviews & Send Sentiment Reports to Slack with Gemini

Analyze Google Business Reviews & Send Sentiment Reports to Slack with Gemini

BySayOne Technologies @sayonetech on n8n.io

This workflow automates the process of collecting Google Business Profile reviews 🏪, analyzing customer sentiment with Google Gemini 🤖✨, and sending structured reports to Slack 💬. 📥 Fetches Google Business Profile reviews for a given business and time period 🧠 Runs sentiment…

Cron / scheduled trigger★★★★☆ complexityAI-powered25 nodesGoogle Business ProfileSentiment AnalysisGoogle Gemini ChatAgentSlack
AI & RAG Trigger: Cron / scheduled Nodes: 25 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Google Gemini Chat 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": "peemlQQi9udHOyNH",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Google review Sentiment analysis workflow",
  "tags": [],
  "nodes": [
    {
      "id": "3f44e182-92ad-4e47-9eab-4ffc6c9a3dfa",
      "name": "Get many reviews",
      "type": "n8n-nodes-base.googleBusinessProfile",
      "position": [
        -272,
        -80
      ],
      "parameters": {
        "limit": 1000,
        "account": {
          "__rl": true,
          "mode": "name",
          "value": "="
        },
        "location": {
          "__rl": true,
          "mode": "name",
          "value": "="
        },
        "resource": "review",
        "operation": "getAll",
        "requestOptions": {}
      },
      "typeVersion": 1
    },
    {
      "id": "29592644-4922-4095-a608-fc369882a249",
      "name": "Sentiment Analysis",
      "type": "@n8n/n8n-nodes-langchain.sentimentAnalysis",
      "position": [
        368,
        -96
      ],
      "parameters": {
        "options": {
          "batching": {
            "batchSize": 20,
            "delayBetweenBatches": 60000
          },
          "categories": "Positive, Neutral, Negative",
          "enableAutoFixing": true,
          "systemPromptTemplate": "=You are a highly intelligent and accurate sentiment analyzer.  \n\nYou will receive multiple JSON objects, each containing:  \n- Comment: \"{{ $json.Comment }}\"  \n- Rating: \"{{ $json.Raiting }}\"  \n- Date: \"{{ $json.Date }}\"  \n\nRules for analysis:  \n- If Comment = \"no comment\", ignore the comment and analyze sentiment only from the rating.  \n- If Comment has text, analyze sentiment based on both the comment and rating together.  \n- Use the Date field to group sentiments by month and identify trends.  \n\nYour tasks:  \n1. Classify the overall sentiment trends into one of the following categories: {categories}.  \n2. Group the results by month (based on the Date field) and provide the sentiment distribution for each month.  \n3. For each month, give a short explanation of why the sentiment appears that way (e.g., common themes in comments, tone, or rating alignment).  \n4. Provide a consolidated summary of sentiment across the entire dataset, including the key reasons driving the results.  ",
          "includeDetailedResults": true
        },
        "inputText": "={{ $json.Comment }}{{ $json.Raiting }}{{ $json.Date }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "692ed10b-947e-4386-9707-0c2ce1e307f9",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1056,
        -224
      ],
      "parameters": {
        "options": {
          "maxOutputTokens": 5000
        },
        "modelName": "models/gemini-2.0-flash"
      },
      "typeVersion": 1
    },
    {
      "id": "713c6715-380d-4adf-a681-092765116409",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -688,
        -80
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "months"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "20e79d80-cdce-4cae-ab1f-6ff44565731b",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1040,
        -432
      ],
      "parameters": {
        "text": "=You are an AI assistant that consolidates customer feedback consisting of comments, ratings, and sentiment analysis metadata. \n\nINPUT DATA:\n{{ $json.feedback }}\n\nTASK:\n1. Review all feedback entries together.\n   - Ignore entries where \"Comment\" = \"no comment\".\n   - Convert \"Raiting\" into numeric stars (FIVE = 5, FOUR = 4, etc.).\n   - Use \"sentimentAnalysis\" to confirm tone and consistency.\n   - Consider \"Date\" to identify any trends or changes over time.\n\n2. Produce ONE single consolidated report in **valid JSON format** with the following structure:\n\n{\n  \"overallSentiment\": \"string\",        // e.g. \"Positive\", \"Negative\", \"Mixed\"\n  \"averageRating\": number,             // average numeric rating\n  \"highlights\": [ \"string\", ... ],     // list of positive aspects\n  \"weaknessesConcerns\": [ \"string\", ... ], // list of concerns/issues\n  \"timeTrend\": \"string\",               // description of sentiment or rating trend over time\n  \"finalSummary\": \"string\"             // concise conclusion\n}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "97dce654-beb7-46f3-9d4c-9f4768b72324",
      "name": "AI Agent1",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1040,
        -128
      ],
      "parameters": {
        "text": "=You are an AI assistant that consolidates customer feedback consisting of comments, ratings, and sentiment analysis metadata. \n\nINPUT DATA:\n{{ $json.feedback }}\n\nTASK:\n1. Review all feedback entries together.\n   - Ignore entries where \"Comment\" = \"no comment\".\n   - Convert \"Raiting\" into numeric stars (FIVE = 5, FOUR = 4, etc.).\n   - Use \"sentimentAnalysis\" to confirm tone and consistency.\n   - Consider \"Date\" to identify any trends or changes over time.\n\n2. Produce ONE single consolidated report in **valid JSON format** with the following structure:\n\n{\n  \"overallSentiment\": \"string\",        // e.g. \"Positive\", \"Negative\", \"Mixed\"\n  \"averageRating\": number,             // average numeric rating\n  \"highlights\": [ \"string\", ... ],     // list of positive aspects\n  \"weaknessesConcerns\": [ \"string\", ... ], // list of concerns/issues\n  \"timeTrend\": \"string\",               // description of sentiment or rating trend over time\n  \"finalSummary\": \"string\"             // concise conclusion\n}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "bfc5447b-fd82-4c44-af66-0d2b60f75280",
      "name": "AI Agent2",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1056,
        112
      ],
      "parameters": {
        "text": "=You are an AI assistant that consolidates customer feedback consisting of comments, ratings, and sentiment analysis metadata. \n\nINPUT DATA:\n{{ $json.feedback }}\n\nTASK:\n1. Review all feedback entries together.\n   - Ignore entries where \"Comment\" = \"no comment\".\n   - Convert \"Raiting\" into numeric stars (FIVE = 5, FOUR = 4, etc.).\n   - Use \"sentimentAnalysis\" to confirm tone and consistency.\n   - Consider \"Date\" to identify any trends or changes over time.\n\n2. Produce ONE single consolidated report in **valid JSON format** with the following structure:\n\n{\n  \"overallSentiment\": \"string\",        // e.g. \"Positive\", \"Negative\", \"Mixed\"\n  \"averageRating\": number,             // average numeric rating\n  \"highlights\": [ \"string\", ... ],     // list of positive aspects\n  \"weaknessesConcerns\": [ \"string\", ... ], // list of concerns/issues\n  \"timeTrend\": \"string\",               // description of sentiment or rating trend over time\n  \"finalSummary\": \"string\"             // concise conclusion\n}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "f95e4642-38b6-48ea-bf53-5de3175a7846",
      "name": "Google Gemini Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        368,
        112
      ],
      "parameters": {
        "options": {
          "maxOutputTokens": 5000
        },
        "modelName": "models/gemini-2.0-flash"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8606a252-49af-472d-a47c-559be628fe60",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        -288
      ],
      "parameters": {
        "width": 752,
        "height": 432,
        "content": "## Reading Google review\n**Reading google review from the google business profile**"
      },
      "typeVersion": 1
    },
    {
      "id": "eb49d865-7578-4969-b505-b643caa3f29d",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        288,
        -288
      ],
      "parameters": {
        "width": 400,
        "height": 544,
        "content": "## Run sentiment analysis on google review\n**Based on the google review data a sentiment analysis run on top of the google review using Gemini model.**"
      },
      "typeVersion": 1
    },
    {
      "id": "17a9299c-5c99-466e-ae6a-895c29b25106",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        -624
      ],
      "parameters": {
        "width": 640,
        "height": 896,
        "content": "## Summarize the sentiment analysis report using AI model\n**After the sentiment of each review is analysed consolidating the overall sentiment and restructure the output.**"
      },
      "typeVersion": 1
    },
    {
      "id": "4b087a3b-d891-4f9a-97d1-be57259afb19",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1392,
        -656
      ],
      "parameters": {
        "width": 448,
        "height": 928,
        "content": "## Sent notification to slack channel\n\n**Restructure the data to slack block and send to slack channel.**"
      },
      "typeVersion": 1
    },
    {
      "id": "091e5606-4e04-4fe3-b2df-0625f32d6beb",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -816,
        -816
      ],
      "parameters": {
        "width": 512,
        "height": 448,
        "content": "\n## Google review Sentiment analysis workflow\n\n\n**What it does**\n- Read Google review from the google business profile\n- Run sentimental analysis on the review for a defined period.\n- Send notification to slack channel.\n\n**Requirement**\n- Google business profile with approved project by  Google.\n- Enable google business profile API service.\n- Gemini model with necessary credentials\n\n\n**Setup Instructions:**\n- Setup google business profile and enable Google Business Profile API.\n- Read google review using owner name and location.\n- Setup slack account to send notification from workflow.\n- Configure the time period of the review using set time period node\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b4506c66-8619-4eef-aed0-f4a9363af457",
      "name": "Set time period",
      "type": "n8n-nodes-base.set",
      "position": [
        -480,
        -80
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "6acde8ee-5eeb-451c-a491-ed4a19c7b765",
              "name": "period",
              "type": "string",
              "value": "year"
            },
            {
              "id": "f5212cc6-8ed1-45de-ac3b-ff839822bed2",
              "name": "time",
              "type": "string",
              "value": "3"
            }
          ]
        }
      },
      "executeOnce": true,
      "typeVersion": 3.4
    },
    {
      "id": "f284db6b-8852-427a-be86-e30961871f97",
      "name": "Filter review based on the time period",
      "type": "n8n-nodes-base.filter",
      "position": [
        -96,
        -80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2dd5772a-efc9-46ac-9054-c5a7de0abdc9",
              "operator": {
                "type": "dateTime",
                "operation": "after"
              },
              "leftValue": "={{ $json.updateTime }}",
              "rightValue": "={{ $today.minus({ [ $('Set time period').item.json.period ]: $('Set time period').item.json.time }).toISO() }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c775ac9e-4367-463d-b3d0-45e3d7bc648f",
      "name": "Map the comment and rating",
      "type": "n8n-nodes-base.set",
      "position": [
        112,
        -80
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4ad19e64-07ad-4351-a696-d2d0026aaa31",
              "name": "Comment",
              "type": "string",
              "value": "={{ $json.comment ?? \"no comment\" }}"
            },
            {
              "id": "ac2932fb-6a62-4179-98d3-5d66a9738ee8",
              "name": "Raiting",
              "type": "string",
              "value": "={{ $json.starRating ?? \"0\" }}"
            },
            {
              "id": "fcadfd58-3d78-44e3-9e95-a24cbdaec614",
              "name": "Date",
              "type": "string",
              "value": "={{ $json.updateTime }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "719cdaa0-f962-45da-91a4-34492f92119e",
      "name": "Convert to json string",
      "type": "n8n-nodes-base.code",
      "position": [
        816,
        -336
      ],
      "parameters": {
        "jsCode": "return [\n  {\n    json: {\n      feedback: JSON.stringify($input.all().map(item => item.json), null, 2)\n    }\n  }\n];"
      },
      "executeOnce": true,
      "typeVersion": 2
    },
    {
      "id": "68f2cf3c-4b21-4004-b8d4-3399d8c1bafa",
      "name": "Convert to json string1",
      "type": "n8n-nodes-base.code",
      "position": [
        816,
        -96
      ],
      "parameters": {
        "jsCode": "return [\n  {\n    json: {\n      feedback: JSON.stringify($input.all().map(item => item.json), null, 2)\n    }\n  }\n];"
      },
      "executeOnce": true,
      "typeVersion": 2
    },
    {
      "id": "046f17c6-c024-4b62-b16f-6d6ccdfeaad2",
      "name": "Convert to json string2",
      "type": "n8n-nodes-base.code",
      "position": [
        816,
        112
      ],
      "parameters": {
        "jsCode": "return [\n  {\n    json: {\n      feedback: JSON.stringify($input.all().map(item => item.json), null, 2)\n    }\n  }\n];"
      },
      "executeOnce": true,
      "typeVersion": 2
    },
    {
      "id": "cad3406f-e05d-4c9c-ae13-aa9d877286e3",
      "name": "Restructure the sentiment positive data to slack block",
      "type": "n8n-nodes-base.code",
      "position": [
        1456,
        -432
      ],
      "parameters": {
        "jsCode": "// Extract JSON string from $json.output (remove ```json ... ```)\nlet raw = $json.output.replace(/```json|```/g, \"\").trim();\n\n// Parse JSON\nlet data;\ntry {\n  data = JSON.parse(raw);\n} catch (e) {\n  throw new Error(\"Invalid JSON format in output: \" + e.message);\n}\n\n// Slack blocks array\nconst blocks = [\n  {\n    type: \"header\",\n    text: {\n      type: \"plain_text\",\n      text: \"\ud83d\udcca Customer Feedback Report\",\n      emoji: true\n    }\n  }\n];\n\n// Overall Sentiment\nif (data.overallSentiment) {\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Overall Sentiment:* ${data.overallSentiment}` }\n  });\n}\n\n// Average Rating\nif (data.averageRating) {\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Average Rating:* ${data.averageRating} \u2b50` }\n  });\n}\n\n// Highlights\nif (data.highlights && data.highlights.length > 0) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: \"*Highlights:*\" }\n  });\n\n  data.highlights.forEach(h => {\n    blocks.push({\n      type: \"section\",\n      text: { type: \"mrkdwn\", text: `\u2022 ${h}` }\n    });\n  });\n}\n\n// Weaknesses/Concerns\nif (data.weaknessesConcerns && data.weaknessesConcerns.length > 0) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: \"*Weaknesses / Concerns:*\" }\n  });\n\n  data.weaknessesConcerns.forEach(w => {\n    blocks.push({\n      type: \"section\",\n      text: { type: \"mrkdwn\", text: `\u2022 ${w}` }\n    });\n  });\n}\n\n// Time Trend\nif (data.timeTrend) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Time Trend:* ${data.timeTrend}` }\n  });\n}\n\n// Final Summary\nif (data.finalSummary) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Final Summary:* ${data.finalSummary}` }\n  });\n}\n\n// Return Slack-ready JSON\nreturn [\n  {\n    json: {\n      blocks\n    }\n  }\n];\n"
      },
      "executeOnce": true,
      "typeVersion": 2
    },
    {
      "id": "e734a3e0-5b2e-4930-a61a-c81a9263d34a",
      "name": "Restructure the sentiment neutral data to slack block",
      "type": "n8n-nodes-base.code",
      "position": [
        1440,
        -128
      ],
      "parameters": {
        "jsCode": "// Extract JSON string from $json.output (remove ```json ... ```)\nlet raw = $json.output.replace(/```json|```/g, \"\").trim();\n\n// Parse JSON\nlet data;\ntry {\n  data = JSON.parse(raw);\n} catch (e) {\n  throw new Error(\"Invalid JSON format in output: \" + e.message);\n}\n\n// Slack blocks array\nconst blocks = [\n  {\n    type: \"header\",\n    text: {\n      type: \"plain_text\",\n      text: \"\ud83d\udcca Customer Feedback Report\",\n      emoji: true\n    }\n  }\n];\n\n// Overall Sentiment\nif (data.overallSentiment) {\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Overall Sentiment:* ${data.overallSentiment}` }\n  });\n}\n\n// Average Rating\nif (data.averageRating) {\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Average Rating:* ${data.averageRating} \u2b50` }\n  });\n}\n\n// Highlights\nif (data.highlights && data.highlights.length > 0) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: \"*Highlights:*\" }\n  });\n\n  data.highlights.forEach(h => {\n    blocks.push({\n      type: \"section\",\n      text: { type: \"mrkdwn\", text: `\u2022 ${h}` }\n    });\n  });\n}\n\n// Weaknesses/Concerns\nif (data.weaknessesConcerns && data.weaknessesConcerns.length > 0) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: \"*Weaknesses / Concerns:*\" }\n  });\n\n  data.weaknessesConcerns.forEach(w => {\n    blocks.push({\n      type: \"section\",\n      text: { type: \"mrkdwn\", text: `\u2022 ${w}` }\n    });\n  });\n}\n\n// Time Trend\nif (data.timeTrend) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Time Trend:* ${data.timeTrend}` }\n  });\n}\n\n// Final Summary\nif (data.finalSummary) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Final Summary:* ${data.finalSummary}` }\n  });\n}\n\n// Return Slack-ready JSON\nreturn [\n  {\n    json: {\n      blocks\n    }\n  }\n];\n"
      },
      "executeOnce": true,
      "typeVersion": 2
    },
    {
      "id": "bf8ebac2-b4f9-43ea-8ec0-ab2a018760c2",
      "name": "Restructure the sentiment negative data to slack block",
      "type": "n8n-nodes-base.code",
      "position": [
        1456,
        112
      ],
      "parameters": {
        "jsCode": "// Extract JSON string from $json.output (remove ```json ... ```)\nlet raw = $json.output.replace(/```json|```/g, \"\").trim();\n\n// Parse JSON\nlet data;\ntry {\n  data = JSON.parse(raw);\n} catch (e) {\n  throw new Error(\"Invalid JSON format in output: \" + e.message);\n}\n\n// Slack blocks array\nconst blocks = [\n  {\n    type: \"header\",\n    text: {\n      type: \"plain_text\",\n      text: \"\ud83d\udcca Customer Feedback Report\",\n      emoji: true\n    }\n  }\n];\n\n// Overall Sentiment\nif (data.overallSentiment) {\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Overall Sentiment:* ${data.overallSentiment}` }\n  });\n}\n\n// Average Rating\nif (data.averageRating) {\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Average Rating:* ${data.averageRating} \u2b50` }\n  });\n}\n\n// Highlights\nif (data.highlights && data.highlights.length > 0) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: \"*Highlights:*\" }\n  });\n\n  data.highlights.forEach(h => {\n    blocks.push({\n      type: \"section\",\n      text: { type: \"mrkdwn\", text: `\u2022 ${h}` }\n    });\n  });\n}\n\n// Weaknesses/Concerns\nif (data.weaknessesConcerns && data.weaknessesConcerns.length > 0) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: \"*Weaknesses / Concerns:*\" }\n  });\n\n  data.weaknessesConcerns.forEach(w => {\n    blocks.push({\n      type: \"section\",\n      text: { type: \"mrkdwn\", text: `\u2022 ${w}` }\n    });\n  });\n}\n\n// Time Trend\nif (data.timeTrend) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Time Trend:* ${data.timeTrend}` }\n  });\n}\n\n// Final Summary\nif (data.finalSummary) {\n  blocks.push({ type: \"divider\" });\n  blocks.push({\n    type: \"section\",\n    text: { type: \"mrkdwn\", text: `*Final Summary:* ${data.finalSummary}` }\n  });\n}\n\n// Return Slack-ready JSON\nreturn [\n  {\n    json: {\n      blocks\n    }\n  }\n];\n"
      },
      "executeOnce": true,
      "retryOnFail": false,
      "typeVersion": 2
    },
    {
      "id": "8e8b11a1-1531-4f0d-90f6-5025e04a173e",
      "name": "Send message to slack channel if the analysis is positive",
      "type": "n8n-nodes-base.slack",
      "position": [
        1664,
        -432
      ],
      "parameters": {
        "select": "channel",
        "blocksUi": "={{ '{ \"blocks\": ' + JSON.stringify($json.blocks) + ' }' }}",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09DQ7EJ57A",
          "cachedResultName": "sentiment-analysis-report"
        },
        "messageType": "block",
        "otherOptions": {
          "includeLinkToWorkflow": false
        },
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "58b3519a-3484-4d0a-bf16-69fcd3c3cb9f",
      "name": "Send message to slack channel if the analysis is neutral",
      "type": "n8n-nodes-base.slack",
      "position": [
        1680,
        -128
      ],
      "parameters": {
        "select": "channel",
        "blocksUi": "={{ '{ \"blocks\": ' + JSON.stringify($json.blocks) + ' }' }}",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09DQ7EJ57A",
          "cachedResultName": "sentiment-analysis-report"
        },
        "messageType": "block",
        "otherOptions": {
          "includeLinkToWorkflow": false
        },
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "6b05d854-689d-473b-a02d-631293ff3817",
      "name": "Send message to slack channel if the analysis is negative",
      "type": "n8n-nodes-base.slack",
      "position": [
        1680,
        112
      ],
      "parameters": {
        "select": "channel",
        "blocksUi": "={{ '{ \"blocks\": ' + JSON.stringify($json.blocks) + ' }' }}",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09DQ7EJ57A",
          "cachedResultName": "sentiment-analysis-report"
        },
        "messageType": "block",
        "otherOptions": {
          "includeLinkToWorkflow": false
        },
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "9d0aab67-a72b-43f9-a8c3-e7b8c7aa7be3",
  "connections": {
    "AI Agent": {
      "main": [
        [
          {
            "node": "Restructure the sentiment positive data to slack block",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent1": {
      "main": [
        [
          {
            "node": "Restructure the sentiment neutral data to slack block",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent2": {
      "main": [
        [
          {
            "node": "Restructure the sentiment negative data to slack block",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set time period": {
      "main": [
        [
          {
            "node": "Get many reviews",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get many reviews": {
      "main": [
        [
          {
            "node": "Filter review based on the time period",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Set time period",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sentiment Analysis": {
      "main": [
        [
          {
            "node": "Convert to json string",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Convert to json string1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Convert to json string2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to json string": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to json string1": {
      "main": [
        [
          {
            "node": "AI Agent1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to json string2": {
      "main": [
        [
          {
            "node": "AI Agent2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "AI Agent1",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "AI Agent2",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Sentiment Analysis",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Map the comment and rating": {
      "main": [
        [
          {
            "node": "Sentiment Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter review based on the time period": {
      "main": [
        [
          {
            "node": "Map the comment and rating",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Restructure the sentiment neutral data to slack block": {
      "main": [
        [
          {
            "node": "Send message to slack channel if the analysis is neutral",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Restructure the sentiment negative data to slack block": {
      "main": [
        [
          {
            "node": "Send message to slack channel if the analysis is negative",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Restructure the sentiment positive data to slack block": {
      "main": [
        [
          {
            "node": "Send message to slack channel if the analysis is positive",
            "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 automates the process of collecting Google Business Profile reviews 🏪, analyzing customer sentiment with Google Gemini 🤖✨, and sending structured reports to Slack 💬. 📥 Fetches Google Business Profile reviews for a given business and time period 🧠 Runs sentiment…

Source: https://n8n.io/workflows/8111/ — 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

Created by: Peyton Leveillee Last updated: October 2025

OpenAI Chat, Google Sheets, HTTP Request +5
AI & RAG

This workflow is the AI analysis and alerting engine for a complete social media monitoring system. It's designed to work with data scraped from X (formerly Twitter) using a tool like the Apify Tweet

Google Sheets, Google Gemini Chat, Google Sheets Tool +4
AI & RAG

This workflow is designed for Japanese-speaking professionals, and learners who want to efficiently stay up to date with practical productivity, lifehack, and efficiency-related insights from Japanese

RSS Feed Read, Chain Llm, Google Gemini Chat +7
AI & RAG

Automate Customer Support Issue Resolution Using Ai Text Classifier. Uses lmChatOpenAi, scheduleTrigger, jira, outputParserStructured. Scheduled trigger; 36 nodes.

OpenAI Chat, Jira, Output Parser Structured +8
AI & RAG

Jiratool Schedule. Uses lmChatOpenAi, scheduleTrigger, jira, outputParserStructured. Scheduled trigger; 36 nodes.

OpenAI Chat, Jira, Output Parser Structured +8