This workflow corresponds to n8n.io template #14896 — 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "af722205-903b-44c0-b21f-5587111117b6",
"name": "Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
272,
144
],
"parameters": {
"color": 4,
"width": 476,
"height": 904,
"content": "## Google Reviews Monitor \u2014 Auto Reply Drafts via GPT-4o-mini + Gmail\n\nFor local business owners, agencies, and reputation managers who want to automatically monitor Google reviews every day and receive AI-written reply drafts by email. The workflow runs daily at 9AM, fetches the latest reviews from Google Places API, classifies them as positive or negative, and uses GPT-4o-mini to write a personalised reply for each one. Gmail delivers a clean digest with all drafts ready to copy and paste.\n\n## How it works\n- **1. Schedule \u2014 Every Day 9AM** triggers the workflow automatically each morning\n- **2. Set \u2014 Config Values** stores your Place ID, API key, business name, email, and name\n- **3. HTTP \u2014 Fetch Google Places Reviews** calls the Google Places Details API to get recent reviews\n- **4. Code \u2014 Parse and Classify Reviews** separates positive (4\u20135 stars) from negative (1\u20133 stars)\n- **5. IF \u2014 Are There Reviews?** stops the workflow if no reviews are found\n- **6. AI Agent \u2014 Generate Reply Drafts** writes a personalised reply for each review\n- **8. Set \u2014 Prepare Email Fields** assembles the subject, recipient, and body\n- **9. Gmail \u2014 Send Review Report** delivers the digest with all reply drafts to the owner\n\n## Set up steps\n1. In **2. Set \u2014 Config Values** \u2014 replace YOUR_GOOGLE_PLACE_ID, YOUR_GOOGLE_PLACES_API_KEY, YOUR BUSINESS NAME, owner@yourbusiness.com, and YOUR NAME\n2. In **7. OpenAI \u2014 GPT-4o-mini Model** \u2014 connect your OpenAI credential\n3. In **9. Gmail \u2014 Send Review Report** \u2014 connect your Gmail OAuth2 credential\n4. Activate the workflow \u2014 it will run every day at 9AM automatically"
},
"typeVersion": 1
},
{
"id": "c6446563-93b5-470c-a71b-b6d40f9dabf2",
"name": "Section \u2014 Schedule and Config",
"type": "n8n-nodes-base.stickyNote",
"position": [
800,
192
],
"parameters": {
"color": 5,
"width": 436,
"height": 372,
"content": "## Schedule and Config\nWorkflow triggers every day at 9AM. All config values \u2014 Place ID, API key, business name, recipient email, and owner name \u2014 are set here once and used throughout."
},
"typeVersion": 1
},
{
"id": "fdbcba27-a5dc-439a-917c-6ae3fcf976f9",
"name": "Section \u2014 Review Fetch and Classification",
"type": "n8n-nodes-base.stickyNote",
"position": [
1248,
192
],
"parameters": {
"color": 6,
"width": 612,
"height": 372,
"content": "## Review Fetch and Classification\nFetches the latest reviews from Google Places API. Parses the response, separates positive (4\u20135 stars) from negative (1\u20133 stars), and checks if any reviews exist before continuing."
},
"typeVersion": 1
},
{
"id": "fb96ebc4-88d4-450f-b4f0-e4ee4671d62e",
"name": "Section \u2014 AI Reply Generation",
"type": "n8n-nodes-base.stickyNote",
"position": [
1920,
192
],
"parameters": {
"color": 6,
"width": 280,
"height": 612,
"content": "## AI Reply Generation\nGPT-4o-mini reads all review texts and writes a personalised reply draft for each one. Positive reviews get a warm thank-you. Negative reviews get a professional apology with an offline resolution offer."
},
"typeVersion": 1
},
{
"id": "73297ab7-2d9e-4d52-ae5d-d09262e9b122",
"name": "Section \u2014 Email Delivery",
"type": "n8n-nodes-base.stickyNote",
"position": [
2288,
192
],
"parameters": {
"color": 4,
"width": 420,
"height": 436,
"content": "## Email Delivery\nAssembles the email subject, recipient, and body with all reply drafts. Gmail sends the daily digest to the business owner."
},
"typeVersion": 1
},
{
"id": "709cd612-3041-4146-8a90-e1a5811f5f3a",
"name": "Note \u2014 Edit Config Before Activating",
"type": "n8n-nodes-base.stickyNote",
"position": [
1248,
656
],
"parameters": {
"color": 3,
"width": 668,
"content": "## \u26a0\ufe0f Edit This Node Before Activating\nThis is the only node you need to change. Replace all five values: Place ID (find it at developers.google.com/maps/documentation/places/web-service/place-id), Google Places API key (from Google Cloud Console with Places API enabled), business name, owner email, and owner name."
},
"typeVersion": 1
},
{
"id": "f5b2c072-7ab3-452e-9c0d-8f2924c51a69",
"name": "1. Schedule \u2014 Every Day 9AM",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
848,
400
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 9 * * *"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "a750d23f-651a-4291-afb6-8bd3da4574d8",
"name": "2. Set \u2014 Config Values",
"type": "n8n-nodes-base.set",
"position": [
1072,
400
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "cfg-001",
"name": "placeId",
"type": "string",
"value": "YOUR_GOOGLE_PLACE_ID"
},
{
"id": "cfg-002",
"name": "apiKey",
"type": "string",
"value": "YOUR_GOOGLE_PLACES_API_KEY"
},
{
"id": "cfg-003",
"name": "businessName",
"type": "string",
"value": "YOUR BUSINESS NAME"
},
{
"id": "cfg-004",
"name": "ownerEmail",
"type": "string",
"value": "user@example.com"
},
{
"id": "cfg-005",
"name": "ownerName",
"type": "string",
"value": "YOUR NAME"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b503df1b-b8f3-4e0c-89a6-99cbdd239d26",
"name": "3. HTTP \u2014 Fetch Google Places Reviews",
"type": "n8n-nodes-base.httpRequest",
"position": [
1296,
400
],
"parameters": {
"url": "=https://maps.googleapis.com/maps/api/place/details/json?place_id={{ $json.placeId }}&fields=name,rating,reviews&key={{ $json.apiKey }}",
"options": {}
},
"typeVersion": 4.2
},
{
"id": "18467af9-e908-4bf0-a77b-9a1d8e6563a5",
"name": "4. Code \u2014 Parse and Classify Reviews",
"type": "n8n-nodes-base.code",
"position": [
1520,
400
],
"parameters": {
"jsCode": "const data = $input.first().json;\nconst config = $('2. Set \u2014 Config Values').item.json;\n\n// Extract reviews from Google Places response\nconst result = data.result || {};\nconst reviews = result.reviews || [];\nconst overallRating = result.rating || 'N/A';\n\nif (reviews.length === 0) {\n return [{\n json: {\n hasReviews: false,\n message: 'No reviews found for this business.',\n businessName: config.businessName,\n ownerEmail: config.ownerEmail,\n ownerName: config.ownerName,\n overallRating: overallRating,\n reviews: []\n }\n }];\n}\n\n// Separate positive (4-5 stars) and negative (1-3 stars)\nconst positiveReviews = reviews.filter(r => r.rating >= 4);\nconst negativeReviews = reviews.filter(r => r.rating <= 3);\n\n// Build a clean summary of all reviews\nlet reviewSummary = '';\nreviews.forEach((r, i) => {\n const stars = r.rating || 0;\n const author = r.author_name || 'Anonymous';\n const text = r.text || 'No written review.';\n const time = r.relative_time_description || 'recently';\n const sentiment = stars >= 4 ? 'POSITIVE' : 'NEGATIVE';\n reviewSummary += `Review ${i + 1} [${sentiment} - ${stars} stars]\\nAuthor: ${author} (${time})\\nReview: ${text}\\n\\n`;\n});\n\nreturn [{\n json: {\n hasReviews: true,\n businessName: config.businessName,\n ownerEmail: config.ownerEmail,\n ownerName: config.ownerName,\n overallRating: overallRating,\n totalReviews: reviews.length,\n positiveCount: positiveReviews.length,\n negativeCount: negativeReviews.length,\n reviewSummary: reviewSummary,\n reviews: JSON.stringify(reviews)\n }\n}];"
},
"typeVersion": 2
},
{
"id": "5adadc89-1c14-4e65-a356-7fbebfe740c5",
"name": "5. IF \u2014 Are There Reviews?",
"type": "n8n-nodes-base.if",
"position": [
1728,
400
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": false,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "cond-001",
"operator": {
"type": "boolean",
"operation": "true"
},
"leftValue": "={{ $json.hasReviews }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "8be104e1-8bd2-4f77-874f-f6f25e57ecc0",
"name": "6. AI Agent \u2014 Generate Reply Drafts",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1968,
384
],
"parameters": {
"text": "=You are a professional reputation manager for a local business.\n\nYour job is to write personalised reply drafts for Google reviews.\n\nBUSINESS NAME: {{ $json.businessName }}\nOVERALL RATING: {{ $json.overallRating }} stars\nOWNER NAME: {{ $json.ownerName }}\n\nREVIEWS TO RESPOND TO:\n{{ $json.reviewSummary }}\n\nFor EACH review above write a reply draft.\n\nFor POSITIVE reviews (4-5 stars):\n- Start by thanking the reviewer by name\n- Mention one specific thing they said in their review\n- Express genuine appreciation\n- Invite them to visit or contact again\n- Keep it warm, friendly, and under 60 words\n\nFor NEGATIVE reviews (1-3 stars):\n- Start by apologising sincerely\n- Acknowledge their concern without making excuses\n- Offer to resolve the issue offline (ask them to contact directly)\n- Keep it professional, calm, and under 70 words\n- Never argue or be defensive\n\nOUTPUT FORMAT:\nFor each review write exactly this structure:\n\nREVIEW [number] \u2014 [POSITIVE or NEGATIVE] \u2014 [author name]\nREPLY DRAFT:\n[your reply text here]\n---\n\nRULES:\n- Plain text only. No markdown. No asterisks.\n- End every reply with: Best regards, {{ $json.ownerName }}\n- Write all replies one after another separated by ---",
"options": {},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "f29171bd-d9fb-4038-ab1f-0f36751b421c",
"name": "7. OpenAI \u2014 GPT-4o-mini Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1968,
592
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini"
},
"options": {
"maxTokens": 1000,
"temperature": 0.7
}
},
"typeVersion": 1.2
},
{
"id": "37cc3aaa-4534-4b3f-bb03-3a00d03d520c",
"name": "8. Set \u2014 Prepare Email Fields",
"type": "n8n-nodes-base.set",
"position": [
2336,
384
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "email-001",
"name": "toEmail",
"type": "string",
"value": "={{ $('4. Code \u2014 Parse and Classify Reviews').item.json.ownerEmail }}"
},
{
"id": "email-002",
"name": "emailSubject",
"type": "string",
"value": "=New Google Reviews Alert \u2014 {{ $('4. Code \u2014 Parse and Classify Reviews').item.json.businessName }} \u2014 {{ $('4. Code \u2014 Parse and Classify Reviews').item.json.totalReviews }} review(s) found \u2014 Overall Rating: {{ $('4. Code \u2014 Parse and Classify Reviews').item.json.overallRating }} stars"
},
{
"id": "email-003",
"name": "emailBody",
"type": "string",
"value": "={{ $json.output || 'AI could not generate reply drafts. Please check OpenAI credentials.' }}"
},
{
"id": "email-004",
"name": "positiveCount",
"type": "number",
"value": "={{ $('4. Code \u2014 Parse and Classify Reviews').item.json.positiveCount }}"
},
{
"id": "email-005",
"name": "negativeCount",
"type": "number",
"value": "={{ $('4. Code \u2014 Parse and Classify Reviews').item.json.negativeCount }}"
},
{
"id": "email-006",
"name": "businessName",
"type": "string",
"value": "={{ $('4. Code \u2014 Parse and Classify Reviews').item.json.businessName }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "83532880-5a75-418d-82f5-e8a0162e1e0b",
"name": "9. Gmail \u2014 Send Review Report",
"type": "n8n-nodes-base.gmail",
"position": [
2560,
384
],
"parameters": {
"sendTo": "={{ $json.toEmail }}",
"message": "=Hi {{ $json.businessName }} Team,\n\nYour daily Google Reviews report is ready.\n\nSUMMARY\nPositive Reviews (4-5 stars): {{ $json.positiveCount }}\nNegative Reviews (1-3 stars): {{ $json.negativeCount }}\n\nREPLY DRAFTS \u2014 Copy and paste these directly to Google Business Profile:\n\n{{ $json.emailBody }}\n\n---\nTo post replies:\n1. Go to Google Business Profile: https://business.google.com\n2. Click Reviews\n3. Find the review and paste the draft\n4. Edit if needed and click Reply\n\nThis report was auto-generated by n8n + GPT-4o-mini",
"options": {
"appendAttribution": false
},
"subject": "={{ $json.emailSubject }}"
},
"typeVersion": 2.1
}
],
"connections": {
"2. Set \u2014 Config Values": {
"main": [
[
{
"node": "3. HTTP \u2014 Fetch Google Places Reviews",
"type": "main",
"index": 0
}
]
]
},
"5. IF \u2014 Are There Reviews?": {
"main": [
[
{
"node": "6. AI Agent \u2014 Generate Reply Drafts",
"type": "main",
"index": 0
}
]
]
},
"1. Schedule \u2014 Every Day 9AM": {
"main": [
[
{
"node": "2. Set \u2014 Config Values",
"type": "main",
"index": 0
}
]
]
},
"7. OpenAI \u2014 GPT-4o-mini Model": {
"ai_languageModel": [
[
{
"node": "6. AI Agent \u2014 Generate Reply Drafts",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"8. Set \u2014 Prepare Email Fields": {
"main": [
[
{
"node": "9. Gmail \u2014 Send Review Report",
"type": "main",
"index": 0
}
]
]
},
"6. AI Agent \u2014 Generate Reply Drafts": {
"main": [
[
{
"node": "8. Set \u2014 Prepare Email Fields",
"type": "main",
"index": 0
}
]
]
},
"4. Code \u2014 Parse and Classify Reviews": {
"main": [
[
{
"node": "5. IF \u2014 Are There Reviews?",
"type": "main",
"index": 0
}
]
]
},
"3. HTTP \u2014 Fetch Google Places Reviews": {
"main": [
[
{
"node": "4. Code \u2014 Parse and Classify Reviews",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
You activate this workflow once and it checks your Google reviews every morning at 9AM without any action from you. It fetches your latest reviews, classifies them as positive or negative, and uses GPT-4o-mini to write a personalised reply draft for each one. You receive a clean…
Source: https://n8n.io/workflows/14896/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This n8n automation workflow automates the creation, scripting, production, and posting of YouTube videos. It leverages AI (OpenAI), image generation (PIAPI), video rendering (Shotstack), and platform
Created by: Peyton Leveillee Last updated: October 2025
The Multi-Model Agency Content Engine is a high-performance editorial system designed for agencies. It solves the "blank page" problem by alternating between real-world social proof and strategic expe
This workflow automates the creation, rendering, approval, and posting of TikTok-style POV (Point of View) videos to Instagram, with cross-posting to Facebook and YouTube. It eliminates manual video p
SEO Blog Article Generation Workflow. Uses outputParserStructured, httpRequest, agent, lmChatOpenAi. Scheduled trigger; 56 nodes.