AutomationFlowsSlack & Telegram › Review Reputation Engine

Review Reputation Engine

Review-Reputation-Engine. Uses httpRequest, slack. Webhook trigger; 21 nodes.

Webhook trigger★★★★☆ complexity21 nodesHTTP RequestSlack
Slack & Telegram Trigger: Webhook Nodes: 21 Complexity: ★★★★☆ Added:

This workflow follows the HTTP Request → Slack 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
{
  "nodes": [
    {
      "id": "sticky-ask",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -920,
        -200
      ],
      "parameters": {
        "content": "## The ask\n- Job closes in the field software, the customer gets the rating text within a minute",
        "height": 140,
        "width": 440,
        "color": 4
      }
    },
    {
      "id": "sticky-routing",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -920,
        380
      ],
      "parameters": {
        "content": "## The routing\n- A 4 or 5 gets the Google link, then a referral ask three days later\n- A 1 to 3 pings #reviews and puts a one-hour call task on Dana's list",
        "height": 160,
        "width": 440,
        "color": 5
      }
    },
    {
      "id": "wh-job-done",
      "name": "The field software says a job is done",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -880,
        0
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "demo/job-completed",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "code-job-tidy",
      "name": "Tidy up the job details",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -660,
        0
      ],
      "parameters": {
        "jsCode": "// Field software webhooks arrive flat or wrapped in a data object.\n// Check both shapes for the customer and the job.\nconst outer = $json.body && typeof $json.body === 'object' ? $json.body : $json;\nconst raw = outer.data && typeof outer.data === 'object' ? outer.data : outer;\n\nconst pick = (...keys) => {\n  for (const k of keys) {\n    const v = raw[k];\n    if (v !== undefined && v !== null && String(v).trim() !== '') return String(v).trim();\n  }\n  return '';\n};\n\nconst name = pick('customerName', 'customer_name', 'name', 'customer') || 'there';\n\nlet phone = pick('customerPhone', 'customer_phone', 'phone', 'phoneNumber').replace(/[^\\d+]/g, '');\nif (phone && !phone.startsWith('+')) {\n  phone = phone.length === 10 ? `+1${phone}` : `+${phone}`;\n}\n\nconst jobType = pick('jobType', 'job_type', 'serviceType', 'service') || 'service visit';\nconst techName = pick('techName', 'tech_name', 'technician', 'tech') || 'our tech';\n\nreturn {\n  name,\n  firstName: name.split(' ')[0],\n  phone,\n  jobType,\n  techName,\n};"
      }
    },
    {
      "id": "ghl-upsert",
      "name": "Save the customer in GoHighLevel",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -440,
        0
      ],
      "parameters": {
        "method": "POST",
        "url": "https://services.leadconnectorhq.com/contacts/upsert",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ locationId: 'bsHomeSvcDemo01', name: $json.name, phone: $json.phone, tags: ['survey-sent'] }) }}",
        "options": {}
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "sms-survey",
      "name": "Ask the customer how we did",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -220,
        0
      ],
      "parameters": {
        "method": "POST",
        "url": "https://services.leadconnectorhq.com/conversations/messages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ type: 'SMS', contactId: $json.contact?.id || $json.id, message: 'Hey ' + $('Tidy up the job details').item.json.firstName + ', this is Blue Summit. Thanks for having ' + $('Tidy up the job details').item.json.techName + ' out today. Quick one: 1 to 5, how did we do?' }) }}",
        "options": {}
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "respond-job",
      "name": "Tell the field software we got it",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        0,
        0
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "{\n  \"status\": \"received\"\n}",
        "options": {}
      }
    },
    {
      "id": "wh-survey-reply",
      "name": "The customer texts back their rating",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -880,
        600
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "demo/survey-reply",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "code-read-rating",
      "name": "Read the rating from their reply",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -660,
        600
      ],
      "parameters": {
        "jsCode": "// The reply can arrive flat or wrapped in a data object.\nconst outer = $json.body && typeof $json.body === 'object' ? $json.body : $json;\nconst raw = outer.data && typeof outer.data === 'object' ? outer.data : outer;\n\nconst pick = (...keys) => {\n  for (const k of keys) {\n    const v = raw[k];\n    if (v !== undefined && v !== null && String(v).trim() !== '') return String(v).trim();\n  }\n  return '';\n};\n\nconst message = pick('message', 'text', 'Body', 'messageBody', 'body');\n\n// Take the first 1-5 digit anywhere in the reply, so \"5!\" and\n// \"I'd say 4\" both count. No digit means a person should look at it.\nconst match = String(message).match(/[1-5]/);\nconst rating = match ? parseInt(match[0], 10) : 0;\n\nlet phone = pick('phone', 'from', 'From', 'contactPhone').replace(/[^\\d+]/g, '');\nif (phone && !phone.startsWith('+')) {\n  phone = phone.length === 10 ? `+1${phone}` : `+${phone}`;\n}\n\nconst contactId = pick('contactId', 'contact_id', 'id');\n\nreturn { rating, phone, contactId, message };"
      }
    },
    {
      "id": "respond-reply",
      "name": "Confirm we got the reply",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        -440,
        600
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "{\n  \"status\": \"received\"\n}",
        "options": {}
      }
    },
    {
      "id": "switch-rating",
      "name": "How did they rate us?",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        -220,
        600
      ],
      "parameters": {
        "mode": "rules",
        "rules": {
          "values": [
            {
              "outputKey": "Loved it",
              "renameOutput": true,
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "rating-high",
                    "leftValue": "={{ $json.rating }}",
                    "rightValue": 4,
                    "operator": {
                      "type": "number",
                      "operation": "gte"
                    }
                  }
                ]
              }
            },
            {
              "outputKey": "Not happy",
              "renameOutput": true,
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "rating-low-floor",
                    "leftValue": "={{ $json.rating }}",
                    "rightValue": 1,
                    "operator": {
                      "type": "number",
                      "operation": "gte"
                    }
                  },
                  {
                    "id": "rating-low-ceiling",
                    "leftValue": "={{ $json.rating }}",
                    "rightValue": 3,
                    "operator": {
                      "type": "number",
                      "operation": "lte"
                    }
                  }
                ]
              }
            },
            {
              "outputKey": "No rating",
              "renameOutput": true,
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "rating-missing",
                    "leftValue": "={{ $json.rating }}",
                    "rightValue": 0,
                    "operator": {
                      "type": "number",
                      "operation": "equals"
                    }
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "sms-review-link",
      "name": "Text them the Google review link",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        0,
        400
      ],
      "parameters": {
        "method": "POST",
        "url": "https://services.leadconnectorhq.com/conversations/messages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ type: 'SMS', contactId: $('Read the rating from their reply').item.json.contactId, message: 'Glad to hear it, thanks. If you have a minute, a quick Google review goes a long way for us: https://blue-summit.example.com/review' }) }}",
        "options": {}
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "tag-happy",
      "name": "Mark them as a happy customer",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        220,
        400
      ],
      "parameters": {
        "method": "POST",
        "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Read the rating from their reply').item.json.contactId }}/tags",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ tags: ['happy-customer'] }) }}",
        "options": {}
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "wait-3-days",
      "name": "Wait 3 days",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        440,
        400
      ],
      "parameters": {
        "amount": 3,
        "unit": "days"
      }
    },
    {
      "id": "sms-referral",
      "name": "Ask them to send a friend our way",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        660,
        400
      ],
      "parameters": {
        "method": "POST",
        "url": "https://services.leadconnectorhq.com/conversations/messages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ type: 'SMS', contactId: $('Read the rating from their reply').item.json.contactId, message: 'Hey, Blue Summit here. If you know anyone who needs their AC or plumbing looked at, send them our way. We take great care of referrals.' }) }}",
        "options": {}
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "tag-referral",
      "name": "Note that we asked for a referral",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        880,
        400
      ],
      "parameters": {
        "method": "POST",
        "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Read the rating from their reply').item.json.contactId }}/tags",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ tags: ['referral-asked'] }) }}",
        "options": {}
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "tag-recovery",
      "name": "Flag them for a recovery call",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        0,
        600
      ],
      "parameters": {
        "method": "POST",
        "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Read the rating from their reply').item.json.contactId }}/tags",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ tags: ['unhappy-recovery'] }) }}",
        "options": {}
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "slack-unhappy",
      "name": "Tell the team in #reviews",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        220,
        600
      ],
      "parameters": {
        "resource": "message",
        "operation": "post",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#reviews"
        },
        "text": "=Low score: {{ $('Read the rating from their reply').item.json.phone }} rated their job {{ $('Read the rating from their reply').item.json.rating }}/5. Their words: \"{{ $('Read the rating from their reply').item.json.message }}\". Dana has a task to call within the hour.",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "task-dana",
      "name": "Put a call task on Dana's list",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        600
      ],
      "parameters": {
        "method": "POST",
        "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Read the rating from their reply').item.json.contactId }}/tasks",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ title: 'Call them today before this becomes a 1-star review', body: 'Rated the job ' + $('Read the rating from their reply').item.json.rating + '/5. Their words: ' + $('Read the rating from their reply').item.json.message + '. Phone: ' + $('Read the rating from their reply').item.json.phone, dueDate: new Date(Date.now() + 60 * 60 * 1000).toISOString(), completed: false }) }}",
        "options": {}
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "tag-human",
      "name": "Mark this reply for a human",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        0,
        820
      ],
      "parameters": {
        "method": "POST",
        "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Read the rating from their reply').item.json.contactId }}/tags",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ tags: ['needs-a-human'] }) }}",
        "options": {}
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "slack-human",
      "name": "Send their message to #reviews",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        220,
        820
      ],
      "parameters": {
        "resource": "message",
        "operation": "post",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#reviews"
        },
        "text": "=Survey reply we could not score, from {{ $('Read the rating from their reply').item.json.phone }}: \"{{ $('Read the rating from their reply').item.json.message }}\". Someone should read it and reply.",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "The field software says a job is done": {
      "main": [
        [
          {
            "node": "Tidy up the job details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tidy up the job details": {
      "main": [
        [
          {
            "node": "Save the customer in GoHighLevel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save the customer in GoHighLevel": {
      "main": [
        [
          {
            "node": "Ask the customer how we did",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ask the customer how we did": {
      "main": [
        [
          {
            "node": "Tell the field software we got it",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "The customer texts back their rating": {
      "main": [
        [
          {
            "node": "Read the rating from their reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read the rating from their reply": {
      "main": [
        [
          {
            "node": "Confirm we got the reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Confirm we got the reply": {
      "main": [
        [
          {
            "node": "How did they rate us?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "How did they rate us?": {
      "main": [
        [
          {
            "node": "Text them the Google review link",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Flag them for a recovery call",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark this reply for a human",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Text them the Google review link": {
      "main": [
        [
          {
            "node": "Mark them as a happy customer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark them as a happy customer": {
      "main": [
        [
          {
            "node": "Wait 3 days",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 3 days": {
      "main": [
        [
          {
            "node": "Ask them to send a friend our way",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ask them to send a friend our way": {
      "main": [
        [
          {
            "node": "Note that we asked for a referral",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flag them for a recovery call": {
      "main": [
        [
          {
            "node": "Tell the team in #reviews",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tell the team in #reviews": {
      "main": [
        [
          {
            "node": "Put a call task on Dana's list",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark this reply for a human": {
      "main": [
        [
          {
            "node": "Send their message to #reviews",
            "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

Review-Reputation-Engine. Uses httpRequest, slack. Webhook trigger; 21 nodes.

Source: https://github.com/mcruz1799/automation-examples/blob/main/claude-code/02-automation-file-factory/skills/n8n/section-templates/review-reputation-engine.json — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

HR teams, IT Operations, and System Administrators managing employee onboarding at scale. It’s perfect if you use Odoo 18 to trigger account requests and need Redmine + GitLab accounts created instant

HTTP Request, Slack
Slack & Telegram

This workflow is a complete, production-ready solution for recovering abandoned carts in Shopify stores using a multi-channel, multi-touch approach. It automates personalized follow-ups via Email, SMS

HTTP Request, Shopify, SendGrid +5
Slack & Telegram

Backbrief: transcripts (Zoom webhook -> Slack + vault). Uses httpRequest, slack. Webhook trigger; 52 nodes.

HTTP Request, Slack
Slack & Telegram

This workflow automates end-to-end research analysis by coordinating multiple AI models—including NVIDIA NIM (Llama), OpenAI GPT-4, and Claude to analyze uploaded documents, extract insights, and gene

HTTP Request, Postgres, Slack +1
Slack & Telegram

Are you tired of the repetitive dance between git push, creating a pull request in GitHub, updating the corresponding task in JIRA, and then manually notifying your team in Slack, or Notion?

HTTP Request, Stop And Error, Jira +2