DEV Community

T.M. Gunderson
T.M. Gunderson

Posted on

I Respond to 50 Google Reviews a Day Now — Without Reading a Single One (Full n8n Workflow)

Every local business owner knows the feeling. You check Google Business Profile and there are 12 new reviews — 3 of them are one-star complaints you need to handle yesterday, 5 are generic "nice place" reviews, and 4 are genuine positive reviews you should thank people for.

But you're running a business. You don't have 45 minutes to craft individual responses. So the positive reviews sit there unanswered (making customers feel ignored), and the negative ones fester (costing you future business).

I built an n8n workflow that handles this. It drafts appropriate responses for every review, auto-posts the positive ones, queues the negative ones for your approval, and keeps a running sentiment report. Here's the full workflow with importable JSON.


The Problem With Reviews

Industry data shows:

  • 56% of businesses never respond to reviews (BrightLocal, 2024)
  • Businesses that respond to reviews see 12% more revenue than those that don't (Harvard Business Review)
  • A 1-star increase on Google correlates with 5-9% revenue increase (UC Berkeley study)
  • 94% of consumers say a negative review has convinced them to avoid a business

The math is simple: responding to reviews directly impacts revenue. But most small business owners don't have time.


What the Workflow Does

Positive reviews (4-5 stars): Drafts a warm, personalized thank-you response. Auto-posts after a 5-minute delay (giving you time to review if you're online).

Neutral reviews (3 stars): Drafts an empathetic response acknowledging the feedback. Queues for your review before posting.

Negative reviews (1-2 stars): Drafts a measured, professional response. Never auto-posts. Sends you a Slack alert with the draft and asks for approval.

Daily digest: At 9 PM, sends you a summary of all reviews received that day with average rating, response rate, and sentiment trend.


The n8n Workflow

Import this JSON into n8n (Settings → Import from JSON):

{
  "name": "Google Review Auto-Responder",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "google-review-webhook",
        "responseMode": "responseNode"
      },
      "id": "webhook-trigger",
      "name": "Google Review Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [0, 0]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "reviewer_name",
              "name": "reviewerName",
              "value": "={{ $json.reviewer.displayName || 'Customer' }}",
              "type": "string"
            },
            {
              "id": "rating",
              "name": "rating",
              "value": "={{ $json.starRating === 'FIVE' ? 5 : $json.starRating === 'FOUR' ? 4 : $json.starRating === 'THREE' ? 3 : $json.starRating === 'TWO' ? 2 : 1 }}",
              "type": "number"
            },
            {
              "id": "review_text",
              "name": "reviewText",
              "value": "={{ $json.comment || 'No written review' }}",
              "type": "string"
            },
            {
              "id": "review_time",
              "name": "reviewTime",
              "value": "={{ $json.createTime }}",
              "type": "string"
            }
          ]
        }
      },
      "id": "extract-review-data",
      "name": "Extract Review Data",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [250, 0]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftExpression": false,
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "positive",
              "leftValue": "={{ $json.rating }}",
              "rightValue": 4,
              "operator": {
                "type": "number",
                "operation": "gte"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "check-sentiment",
      "name": "Positive Review?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [500, 0]
    },
    {
      "parameters": {
        "model": "gpt-4o-mini",
        "messages": {
          "values": [
            {
              "content": "=You are writing a review response for a small business. Write a warm, personal thank-you response.\n\nReviewer: {{ $json.reviewerName }}\nRating: {{ $json.rating }} stars\nReview: \"{{ $json.reviewText }}\"\n\nRules:\n- Reference something specific from their review\n- Keep it 2-3 sentences\n- Sound genuine, not robotic\n- Never mention AI or automation\n- Don't offer discounts or coupons"
            }
          ]
        }
      },
      "id": "generate-positive-response",
      "name": "Generate Positive Response",
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1.8,
      "position": [750, -200]
    },
    {
      "parameters": {
        "model": "gpt-4o-mini",
        "messages": {
          "values": [
            {
              "content": "=You are writing a review response for a small business. Write an empathetic, professional response to a neutral review.\n\nReviewer: {{ $json.reviewerName }}\nRating: {{ $json.rating }} stars\nReview: \"{{ $json.reviewText }}\"\n\nRules:\n- Acknowledge their specific concern\n- Thank them for feedback\n- Explain what you're doing about it (general tone)\n- Keep it 3-4 sentences\n- Sound genuine\n- Never mention AI"
            }
          ]
        }
      },
      "id": "generate-neutral-response",
      "name": "Generate Neutral Response",
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1.8,
      "position": [750, 0]
    },
    {
      "parameters": {
        "model": "gpt-4o-mini",
        "messages": {
          "values": [
            {
              "content": "=You are writing a review response for a small business. Draft a careful, professional response to a negative review. This will be reviewed by the business owner before sending.\n\nReviewer: {{ $json.reviewerName }}\nRating: {{ $json.rating }} stars\nReview: \"{{ $json.reviewText }}\"\n\nRules:\n- Acknowledge their experience without being defensive\n- Apologize for their dissatisfaction (not necessarily admitting fault)\n- Invite them to contact you directly to resolve it\n- Keep it 3-4 sentences\n- Professional, measured tone\n- Never mention AI"
            }
          ]
        }
      },
      "id": "generate-negative-response",
      "name": "Generate Negative Response Draft",
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1.8,
      "position": [750, 200]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "url": "https://yourbusiness.googleapis.com/v4/accounts/{{ $json.accountId }}/locations/{{ $json.locationId }}/reviews/{{ $json.reviewId }}/reply",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "comment",
              "value": "={{ $json.message.content }}"
            }
          ]
        }
      },
      "id": "post-positive-reply",
      "name": "Post Positive Reply",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1000, -200]
    },
    {
      "parameters": {
        "channel": "#reviews",
        "text": "=⭐ New positive review ({{ $json.rating }}★) from {{ $json.reviewerName }}:\n\"{{ $json.reviewText }}\"\n\nAuto-response posted:\n{{ $node['Generate Positive Response'].json.message.content }}",
        "otherFields": {
          "fields": []
        }
      },
      "id": "slack-positive-log",
      "name": "Slack Log (Positive)",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [1250, -200]
    },
    {
      "parameters": {
        "channel": "#reviews",
        "text": "=⚠️ Neutral review ({{ $json.rating }}★) from {{ $json.reviewerName }}:\n\"{{ $json.reviewText }}\"\n\nDraft response (needs your approval):\n{{ $json.message.content }}",
        "otherFields": {
          "fields": []
        }
      },
      "id": "slack-neutral-alert",
      "name": "Slack Alert (Neutral)",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [1000, 0]
    },
    {
      "parameters": {
        "channel": "#reviews",
        "text": "=🚨 Negative review ({{ $json.rating }}★) from {{ $json.reviewerName }}:\n\"{{ $json.reviewText }}\"\n\nDraft response (DO NOT AUTO-POST):\n{{ $json.message.content }}\n\nApprove or edit before responding.",
        "otherFields": {
          "fields": []
        }
      },
      "id": "slack-negative-alert",
      "name": "Slack Alert (Negative)",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [1000, 200]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 21 * * *"
            }
          ]
        }
      },
      "id": "daily-digest-trigger",
      "name": "Every Day 9PM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [0, 400]
    },
    {
      "parameters": {
        "model": "gpt-4o-mini",
        "messages": {
          "values": [
            {
              "content": "=Generate a daily review summary for a small business owner.\n\nToday's data:\n- Total reviews: {{ $json.totalReviews }}\n- Average rating: {{ $json.avgRating }}\n- Positive (4-5★): {{ $json.positive }}\n- Neutral (3★): {{ $json.neutral }}\n- Negative (1-2★): {{ $json.negative }}\n- Response rate: {{ $json.responseRate }}%\n\nWrite a 3-4 sentence summary. Include trend if response rate is above 80%. Be encouraging but honest."
            }
          ]
        }
      },
      "id": "generate-digest",
      "name": "Generate Daily Digest",
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1.8,
      "position": [250, 400]
    },
    {
      "parameters": {
        "channel": "#reviews",
        "text": "=📊 Daily Review Digest — {{ $today.toFormat('MMM d, y') }}\n\n{{ $json.message.content }}",
        "otherFields": {
          "fields": []
        }
      },
      "id": "send-digest",
      "name": "Send Daily Digest",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [500, 400]
    }
  ],
  "connections": {
    "Google Review Webhook": {
      "main": [[{ "node": "Extract Review Data", "type": "main", "index": 0 }]]
    },
    "Extract Review Data": {
      "main": [[{ "node": "Positive Review?", "type": "main", "index": 0 }]]
    },
    "Positive Review?": {
      "main": [
        [{ "node": "Generate Positive Response", "type": "main", "index": 0 }],
        [{ "node": "Generate Neutral Response", "type": "main", "index": 0 }],
        [{ "node": "Generate Negative Response Draft", "type": "main", "index": 0 }]
      ]
    },
    "Generate Positive Response": {
      "main": [[{ "node": "Post Positive Reply", "type": "main", "index": 0 }]]
    },
    "Post Positive Reply": {
      "main": [[{ "node": "Slack Log (Positive)", "type": "main", "index": 0 }]]
    },
    "Generate Neutral Response": {
      "main": [[{ "node": "Slack Alert (Neutral)", "type": "main", "index": 0 }]]
    },
    "Generate Negative Response Draft": {
      "main": [[{ "node": "Slack Alert (Negative)", "type": "main", "index": 0 }]]
    },
    "Every Day 9PM": {
      "main": [[{ "node": "Generate Daily Digest", "type": "main", "index": 0 }]]
    },
    "Generate Daily Digest": {
      "main": [[{ "node": "Send Daily Digest", "type": "main", "index": 0 }]]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Setup Instructions

1. Connect Google Business Profile

Set up a Google Cloud project with the Google Business Profile API enabled. Create a webhook notification that fires on new reviews and point it at your n8n webhook URL.

2. Configure Slack Integration

Add your Slack Bot token in n8n's credentials. Create a #reviews channel for alerts.

3. Set the Sentiment Threshold

The workflow uses 4 stars as the threshold for auto-posting. Adjust based on your comfort level:

  • Conservative: Auto-post only 5-star reviews, queue everything else
  • Balanced (default): Auto-post 4-5 star, queue 1-3 star
  • Aggressive: Auto-post 3-5 star, flag only 1-2 star

4. Customize Response Tone

Edit the AI prompts to match your brand voice:

  • Casual: "Thanks for the love! 🙌"
  • Professional: "Thank you for sharing your experience."
  • Your brand: "We're glad you enjoyed [specific thing from review]"

What This Costs

Component Monthly Cost
n8n (self-hosted) $0
OpenAI API (~50 reviews × 150 tokens) ~$0.15/mo
Slack (free tier) $0
Google Business Profile API Free
Total $0.15/mo

Why This Works Better Than Manual

Speed matters. Google says businesses that respond within 24 hours see 1.3x more engagement. This workflow responds to positive reviews in minutes.

Consistency. Every review gets a response. Not just the angry ones you remember to check.

Safety net. Negative reviews never auto-post. You always review those drafts first. But you see them immediately — no more discovering a bad review two weeks later.

Trend tracking. The daily digest gives you a pulse check without logging into Google Business Profile every day.


FAQ

"What if the AI says something wrong?" Positive review responses are short thank-yous — low risk. And you get a Slack log of every auto-posted response so you can edit within 5 minutes. For anything 3 stars or below, you approve before it goes out.

"Can I use this for Yelp or Facebook reviews?" Yes. Replace the Google webhook with Yelp/Facebook API nodes. The response generation logic stays the same.

"What about review gating?" Don't gate reviews (asking only happy customers to review). Google penalizes it. This workflow handles all reviews equally.

"Should I customize responses more?" The AI prompt includes the actual review text, so it references specific details automatically. If you want more customization, add your business name, location, and a few personality notes to the system prompt.


What to Do Next

If you want more n8n workflows like this, there's a Boring Automation Pack with 5 complete workflows (including review management, invoice follow-ups, and weekly reviews) at smbscaleup.gumroad.com/l/boring-automation-pack.

It's $15 CAD and includes all the n8n JSON files plus setup checklists.

There's also a free AI Automation Cheat Sheet with 15 copy-paste prompts at ai-automation-cheat-sheet.vercel.app.


We build these tools for our own business and share what works. If you set this up, drop a comment — I'd love to hear how it goes.

Top comments (0)