51 min readAutonomous agents

Implementation Guide: Monitor ota review platforms and generate context-aware management responses

Step-by-step implementation guide for deploying AI to monitor ota review platforms and generate context-aware management responses for Hospitality clients.

Hardware Procurement

Staff Dashboard Tablet

AppleiPad 10th Generation (A2696) 64GB Wi-FiQty: 1

$349 per unit (MSP cost) / $499 suggested resale with configuration

Optional dedicated front-desk device for the General Manager or front-desk supervisor to review, approve, and edit AI-generated review responses in real time. Mounted at front desk or in back office. Not required if staff will use existing computers or personal devices.

Network Connectivity Verification Kit

UbiquitiUniFi USW-Flex-Mini (USW-Flex-Mini)Qty: 1

$29 per unit (MSP cost) / $79 suggested resale with configuration

Compact managed switch to ensure a dedicated, reliable wired connection for the back-office workstation used for review management. Provides network segmentation and QoS priority for business-critical traffic separate from guest Wi-Fi. Only needed if existing network infrastructure is unreliable.

Software Procurement

MARA AI Review Assistant

MARA Solutions GmbHSaaSQty: per property

€60–€130/month per property (MSP cost); suggest resale at $99–$199/month per property

Core AI platform for OTA review aggregation, sentiment analysis, brand voice training, AI response generation, and automated posting of management responses. Connects natively to Booking.com, Expedia, Google Business Profile, TripAdvisor, and 10+ other review sources. Includes Review Inbox, Smart Snippets, Review Analytics, and Service Ticket AI.

n8n Community Edition (Self-Hosted)

n8n GmbHCommunity EditionQty: 1

Free (self-hosted) or n8n Cloud Starter at $24/month; hosting cost ~$24–$30/month on DigitalOcean

Workflow automation platform to orchestrate advanced review processing pipelines: escalation routing for negative reviews, Slack/Teams/email notifications, weekly digest report generation, multi-property aggregation dashboards, and backup LLM response generation if MARA is unavailable.

OpenAI API (GPT-5.4 mini)

OpenAIGPT-5.4 mini

$0.15/1M input tokens + $0.60/1M output tokens; estimated $5–$20/month per property depending on review volume

Backup and supplementary LLM for custom workflows: generating executive summary reports, translating responses for international guests, creating sentiment trend narratives, and powering custom escalation analysis. Used via n8n HTTP Request nodes.

Free

Direct API access to read and respond to Google reviews programmatically. Used by MARA natively and also available for custom n8n workflows for Google-specific review management and analytics.

Slack (or Microsoft Teams)

Slack Technologies / Microsoftper-seat

Slack Pro $8.75/user/month or Microsoft Teams (typically included in client's M365 subscription)

Real-time notification channel for review alerts, escalation routing, and approval workflows. Negative reviews (1–3 stars) trigger immediate alerts to GM and duty manager. Positive reviews are posted to a team celebration channel.

DigitalOcean Droplet (n8n hosting)

DigitalOcean2 vCPU, 4GB RAM, 80GB SSD - Regular IntelQty: 1

$24/month

Cloud VM to host n8n Community Edition, PostgreSQL database for review state management, and custom workflow automations. Located in nearest region to hotel property for low latency.

UptimeRobot

UptimeRobotSaaSQty: 1

Free tier (50 monitors, 5-min checks) or Pro at $7/month

Monitoring service to ensure the n8n instance, MARA webhook endpoints, and OTA API connections remain operational. Alerts MSP NOC team if any component goes down.

Free

Client-facing monthly reporting dashboard showing review volume trends, average sentiment scores, response time metrics, AI response approval rates, and competitive benchmarking. Connects to review data exported from MARA and n8n PostgreSQL database.

Prerequisites

  • Stable business-grade internet connection at the property (minimum 10 Mbps download/upload) separate from guest Wi-Fi network
  • Active accounts with admin/owner access on all OTA platforms where the property is listed: Booking.com Extranet, Expedia Partner Central, Google Business Profile, TripAdvisor Management Center
  • A modern web browser (Chrome 90+, Edge 90+, Safari 15+, or Firefox 90+) on at least one staff workstation
  • Business email domain (e.g., manager@hotelname.com) for MARA account registration and notification delivery — no free email providers
  • Current Property Management System (PMS) identified with API access credentials if PMS integration is desired (Cloudbeds, Mews, Apaleo, or Oracle OPERA Cloud are natively supported)
  • General Manager or designated review responder identified who will serve as the human-in-the-loop approver for negative review responses
  • At least 20–30 existing management responses to past reviews available for Brand Voice AI training (can be from any OTA platform)
  • Slack workspace or Microsoft Teams tenant configured with a dedicated channel for review notifications (e.g., #guest-reviews)
  • Client has signed a Data Processing Agreement (DPA) acknowledging that guest review data will be processed by cloud-based AI services, in compliance with GDPR (EU properties) or CCPA/CPRA (California properties)
  • MSP has provisioned a DigitalOcean account (or equivalent cloud provider) for hosting the n8n automation server
  • DNS access or ability to create a subdomain (e.g., automation.hotelname.com) for the n8n instance with SSL certificate

Installation Steps

Step 1: Pre-Engagement Discovery & Environment Audit

Conduct a 60-minute discovery call with the hotel General Manager and/or ownership group. Document the property's current review management workflow, identify all active OTA profiles, catalog existing technology stack (PMS, CRM, messaging), determine review volume (average reviews per month per platform), and collect 20–30 sample management responses that represent the desired brand voice. Capture login credentials for all OTA extranets in the MSP's secure credential vault.

Note

Use a standardized discovery questionnaire. Key data points to capture: number of rooms, average occupancy rate, star rating, primary guest demographics (business vs. leisure, domestic vs. international), current average review response time, and any existing reputation management tools. This information directly impacts MARA configuration and Brand Voice training.

Step 2: Provision MARA Solutions Account

Navigate to mara-solutions.com and create a new account for the hotel property. Select the appropriate plan tier based on review volume: Starter (€60/mo) for properties with <50 reviews/month, or Business tier for higher volumes with full automation features. Complete the onboarding wizard by entering property details, uploading logo, and configuring basic property information.

  • Navigate to: https://app.mara-solutions.com/signup
  • Enter property details: Hotel name, address, star rating
  • Set primary language for responses
  • Set secondary languages (if international guest mix)
  • Upload hotel logo and brand colors for dashboard
Note

Use the MSP's partner/reseller email for the master admin account. Create a separate operator account for the hotel GM with limited permissions (review/approve responses only, no billing access). This preserves MSP control over the subscription while giving the client operational access.

Step 3: Connect OTA Review Sources to MARA

In MARA's Review Inbox settings, connect all active OTA platforms. For Booking.com and Expedia, MARA uses established connectivity partnerships — you will need to authorize MARA through each platform's partner authorization flow. For Google Business Profile, connect via Google OAuth. For TripAdvisor, connect via the TripAdvisor Content API authorization process. Verify that historical reviews are being imported for each connected source.

1
In MARA Dashboard → Settings → Review Sources
2
Booking.com: Click 'Connect Booking.com' → Enter Extranet credentials → Authorize
3
Google Business Profile: Click 'Connect Google' → OAuth flow → Select property listing
4
Expedia: Click 'Connect Expedia' → Enter Partner Central credentials → Authorize
5
TripAdvisor: Click 'Connect TripAdvisor' → Enter Management Center credentials → Authorize
6
Verify: Return to Review Inbox → Confirm reviews are populating from all sources
Note

Booking.com does not have a public API — MARA accesses reviews through their connectivity partner program. If the hotel is listed on additional platforms (Hotels.com, Agoda, HRS, etc.), connect those as well. Allow up to 24 hours for full historical review import. Some platforms may require email verification or 2FA during the authorization flow — ensure the hotel GM is available to approve.

Step 4: Train MARA Brand Voice AI

Upload the 20–30 sample management responses collected during discovery into MARA's Brand Voice training module. These should represent the hotel's ideal tone, level of formality, common phrases, and response structure. MARA's AI will analyze these samples to learn the property's unique communication style. After training, generate 5 test responses and have the GM evaluate whether they match the hotel's voice.

1
In MARA Dashboard → Settings → Brand Voice
2
Click 'Train Brand Voice'
3
Paste or upload 20–30 sample responses
4
Set voice parameters: Formality level (e.g., 'Professional but warm'), Greeting style (e.g., 'Dear [Guest Name],' or 'Hello [Guest Name],'), Closing style (e.g., 'Warm regards, [GM Name], General Manager'), Property-specific terms (e.g., 'our rooftop terrace', 'Chef Antonio's creations')
5
Click 'Train Model' — processing takes 5–15 minutes
6
Use 'Test Voice' feature to generate sample responses and review with GM
Note

Brand Voice quality is the single most important factor in client satisfaction with the system. Invest time here. Avoid using generic hotel responses — the AI needs to learn what makes THIS hotel's communication unique. Include responses that reference specific amenities, local attractions, and staff members by name. Retrain quarterly or whenever the GM changes.

Step 5: Configure Smart Snippets & Response Rules

Set up MARA's Smart Snippets for recurring topics mentioned in reviews (e.g., parking, breakfast, pool, Wi-Fi, noise). Each snippet provides the AI with factual, up-to-date information about the hotel so responses are accurate. Then configure automation rules: auto-publish responses for 4–5 star reviews, require human approval for 1–3 star reviews, and set escalation alerts for reviews mentioning safety, health, or legal issues.

1
In MARA Dashboard → Smart Snippets: Create a snippet for 'Parking': 'We offer complimentary valet parking for all guests, available 24/7.'
2
In MARA Dashboard → Smart Snippets: Create a snippet for 'Breakfast': 'Our breakfast buffet is served daily from 6:30 AM to 10:30 AM in The Garden Restaurant.'
3
In MARA Dashboard → Smart Snippets: Create a snippet for 'Pool': 'Our heated rooftop pool is open from 7 AM to 10 PM, April through October.'
4
In MARA Dashboard → Smart Snippets: Create a snippet for 'Wi-Fi': 'Complimentary high-speed Wi-Fi is available throughout the property.'
5
In MARA Dashboard → Smart Snippets: Create a snippet for 'Check-in/Check-out': 'Check-in begins at 3 PM, and check-out is at 11 AM. Early check-in is available upon request.'
6
In MARA Dashboard → Automation Rules: For reviews rated 4–5 stars — Auto-generate AND auto-publish (no human review).
7
In MARA Dashboard → Automation Rules: For reviews rated 3 stars — Auto-generate draft → Send to GM for approval via email/Slack.
8
In MARA Dashboard → Automation Rules: For reviews rated 1–2 stars — Auto-generate draft → ESCALATE to GM + MSP via Slack → Require manual approval.
9
In MARA Dashboard → Automation Rules: For reviews mentioning keywords ['safety', 'injury', 'sick', 'lawsuit', 'health department', 'discrimination', 'harass'] — BLOCK auto-response → Escalate immediately to GM + hotel legal contact.
Note

Smart Snippets must be updated whenever hotel amenities, hours, or policies change. Set a calendar reminder for the MSP to review and update snippets quarterly. For the automation rules, start conservatively (human approval for everything) during the first 2 weeks, then gradually enable auto-publish for positive reviews after the GM is confident in response quality. Never auto-publish responses to negative reviews — always maintain human-in-the-loop.

Step 6: Provision n8n Automation Server

Deploy a DigitalOcean Droplet to host n8n Community Edition for advanced workflow automation. This server handles escalation routing, Slack notifications, weekly digest reports, multi-property aggregation, and backup LLM processing. Use Docker Compose for a clean, maintainable deployment with PostgreSQL for persistent workflow data storage.

1
Create DigitalOcean Droplet
2
SSH into the droplet
3
Update system and install Docker
4
Create n8n directory structure
5
Create docker-compose.yml (see custom_ai_components for full file)
6
Create environment file
7
Start n8n
8
Verify n8n is running
1. Create DigitalOcean Droplet
bash
doctl compute droplet create n8n-hotel-reviews \
  --region nyc3 \
  --size s-2vcpu-4gb \
  --image ubuntu-22-04-x64 \
  --ssh-keys $(doctl compute ssh-key list --format ID --no-header | head -1)
2. SSH into the droplet
bash
ssh root@<DROPLET_IP>
3. Update system and install Docker
bash
apt update && apt upgrade -y
curl -fsSL https://get.docker.com | sh
apt install -y docker-compose-plugin
4. Create n8n directory structure
bash
mkdir -p /opt/n8n && cd /opt/n8n
5. Create docker-compose.yml (see custom_ai_components for full file)
bash
nano docker-compose.yml
6. Create environment file
bash
cat > .env << 'EOF'
N8N_BASIC_AUTH_USER=mspadmin
N8N_BASIC_AUTH_PASSWORD=<GENERATE_STRONG_PASSWORD>
N8N_HOST=automation.hotelname.com
N8N_PORT=5678
N8N_PROTOCOL=https
WEBHOOK_URL=https://automation.hotelname.com/
POSTGRES_USER=n8n
POSTGRES_PASSWORD=<GENERATE_STRONG_PASSWORD>
POSTGRES_DB=n8n
OPENAI_API_KEY=sk-<YOUR_OPENAI_KEY>
MARA_WEBHOOK_SECRET=<GENERATE_SECRET>
SLACK_BOT_TOKEN=xoxb-<YOUR_SLACK_BOT_TOKEN>
SLACK_CHANNEL_NEGATIVE=#review-escalations
SLACK_CHANNEL_POSITIVE=#guest-kudos
EOF
7. Start n8n
bash
docker compose up -d
8. Verify n8n is running
bash
docker compose ps
curl -s http://localhost:5678/healthz
Note

Replace all placeholder values (<DROPLET_IP>, passwords, API keys) with actual values. Store all credentials in the MSP's password vault (e.g., IT Glue, Hudu, or Passportal). Set up a DNS A record pointing automation.hotelname.com to the Droplet IP. Use Caddy or nginx-proxy-manager as a reverse proxy for automatic SSL certificate provisioning via Let's Encrypt. For multi-property deployments, a single n8n instance can serve up to ~20 properties before needing to scale.

Step 7: Configure SSL Reverse Proxy for n8n

Set up Caddy as a reverse proxy in front of n8n to provide automatic HTTPS via Let's Encrypt. This is required for secure webhook endpoints that MARA and Slack will call.

Create Caddyfile, restart stack, and verify SSL
bash
# Add Caddy to docker-compose.yml (or create separate)
cd /opt/n8n

cat > Caddyfile << 'EOF'
automation.hotelname.com {
    reverse_proxy n8n:5678 {
        flush_interval -1
    }
}
EOF

# Restart stack
docker compose down && docker compose up -d

# Verify SSL
curl -I https://automation.hotelname.com/healthz
  • Update docker-compose.yml to include Caddy service (See custom_ai_components for full docker-compose.yml with Caddy)
Note

Ensure port 80 and 443 are open on the DigitalOcean firewall. The DNS A record must be propagated before Caddy can obtain the SSL certificate. If using Cloudflare DNS, set the proxy status to 'DNS only' (grey cloud) initially, then enable proxying after SSL is confirmed working.

Step 8: Configure Slack Integration for Review Alerts

Create a Slack App in the client's workspace (or the MSP's workspace if managing centrally) with Bot Token permissions. Set up dedicated channels for review notifications and escalations. Configure n8n workflows to post formatted review alerts with action buttons.

1
Go to https://api.slack.com/apps → Create New App → From Scratch
2
App Name: 'Hotel Review Bot'
3
Workspace: Select client's Slack workspace
4
OAuth & Permissions → Bot Token Scopes: Add: chat:write, chat:write.public, channels:read, reactions:write, files:write
5
Install App to Workspace → Copy Bot User OAuth Token (xoxb-...)
6
Create Slack channels: #review-escalations (private, invite GM + MSP), #guest-kudos (public, all staff), #review-weekly-digest (private, invite GM + ownership)
Test bot posting to Slack channel
bash
curl -X POST https://slack.com/api/chat.postMessage \
  -H 'Authorization: Bearer xoxb-YOUR-BOT-TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"channel": "#review-escalations", "text": "🏨 Review Bot is connected and ready!"}'
Note

If the client uses Microsoft Teams instead of Slack, substitute with a Teams Incoming Webhook connector and adjust the n8n workflow to use the Microsoft Teams node instead of the Slack node. The workflow logic remains identical — only the notification destination changes.

Step 9: Import and Configure n8n Workflows

Import the pre-built n8n workflow JSONs for review monitoring, escalation routing, and weekly digest reporting. Configure each workflow with the property-specific credentials, Slack channels, and MARA webhook endpoints. Activate workflows and verify trigger conditions.

1
Access n8n dashboard: https://automation.hotelname.com
2
Login with MSP admin credentials
3
Go to Settings → Credentials → Add: a. OpenAI API credential (API key from .env) | b. Slack API credential (Bot Token from Step 8) | c. HTTP Header Auth for MARA webhook verification
4
Import workflows: a. Workflows → Import from File → upload 'review-escalation-workflow.json' | b. Workflows → Import from File → upload 'weekly-digest-workflow.json' | c. Workflows → Import from File → upload 'negative-review-analysis-workflow.json'
5
In each workflow, update credential bindings to match the credentials created in step 3
6
Activate all workflows (toggle ON in the workflow list)
7
Test with a manual trigger to verify end-to-end flow
Note

Full workflow JSON specifications are provided in the custom_ai_components section. After importing, walk through each workflow node to verify credential bindings are correct. The review escalation workflow should be tested by creating a mock 1-star review notification to confirm it reaches the correct Slack channel within 60 seconds.

Step 10: Configure MARA Webhook to n8n

Set up MARA to send webhook notifications to the n8n server whenever a new review is received or when an AI-generated response is published. This enables the n8n workflows to process reviews in parallel with MARA's built-in automation, adding MSP-specific escalation logic, reporting, and multi-property aggregation.

1
In MARA Dashboard → Settings → Integrations → Webhooks: Add New Webhook: - Name: 'n8n Review Pipeline' - URL: https://automation.hotelname.com/webhook/mara-review-incoming - Events: 'New Review Received', 'Response Published', 'Response Requires Approval' - Secret: <MARA_WEBHOOK_SECRET from .env> - Click 'Test Webhook' → Verify n8n receives test payload
2
Add Second Webhook (for escalations): - Name: 'n8n Escalation Handler' - URL: https://automation.hotelname.com/webhook/mara-escalation - Events: 'Negative Review Detected', 'Flagged Content' - Secret: <MARA_WEBHOOK_SECRET from .env>
Note

If MARA's webhook feature is limited on the Starter plan, an alternative approach is to use n8n's Schedule Trigger node to poll the MARA API every 15 minutes for new reviews. The polling approach is slightly less real-time but works on all MARA plan tiers. See the alternative polling workflow in custom_ai_components.

If the hotel uses a supported PMS (Cloudbeds, Mews, Apaleo, or Oracle OPERA Cloud), connect it to MARA to enrich review responses with guest stay context. This allows the AI to reference specific stay details (room type, length of stay, amenities used) in responses, making them dramatically more personalized.

1
For Apaleo (native MARA integration): In MARA Dashboard → Settings → PMS Integration → Apaleo
2
Click 'Connect Apaleo'
3
Enter Apaleo API credentials (Client ID + Client Secret from Apaleo developer portal)
4
Map property → Select the correct Apaleo property
5
Enable 'Guest Context Enrichment' toggle
1
For Cloudbeds (via API bridge in n8n): Obtain Cloudbeds API key from Cloudbeds Marketplace → API Access
2
In n8n, create a new credential: HTTP Header Auth — Name: 'Cloudbeds API', Header Name: 'Authorization', Header Value: 'Bearer <CLOUDBEDS_API_KEY>'
3
Import the 'cloudbeds-guest-lookup-workflow.json' to n8n
4
This workflow: receives guest name from MARA review → queries Cloudbeds → returns stay details → enriches MARA response context
Note

PMS integration is optional for Phase 1 deployment but highly recommended for Phase 2 (week 4-6). Guest context enrichment is the feature that elevates AI responses from 'good' to 'indistinguishable from a thoughtful human GM.' Not all PMS systems have open APIs — for legacy on-premise PMS systems (e.g., old versions of Opera PMS), this integration may not be feasible.

Step 12: Two-Week Supervised Testing Period

Run the entire system in 'supervised mode' for two weeks. All AI-generated responses — including those for positive reviews — require manual approval before posting. The GM reviews each response in MARA's dashboard or via Slack notification, approving, editing, or rejecting each one. Track approval rate, edit frequency, and response quality metrics daily.

  • In MARA Dashboard → Automation Rules: Set ALL reviews to 'Draft + Require Approval' mode
  • Disable any auto-publish rules temporarily

Daily Monitoring Checklist (MSP Technician)

Note

Target metrics for the supervised period: >80% of AI responses approved without edits by GM, average response time under 4 hours, zero factually incorrect responses. If approval-without-edit rate is below 70%, retrain Brand Voice AI with the GM's edited versions as additional training data. Do not enable auto-publish until the GM explicitly confirms satisfaction with response quality.

Step 13: Enable Graduated Automation

After the two-week supervised period, gradually enable automation. Start with auto-publishing 5-star reviews only, then add 4-star reviews after one week of successful 5-star automation. Negative reviews (1–3 stars) remain in human-approval mode permanently. Configure the final automation rules and document the decision matrix.

Graduated automation rules — Week 3 through final production configuration

1
Week 3: Enable auto-publish for 5-star reviews
2
In MARA Dashboard → Automation Rules: - 5-star reviews: Auto-generate AND Auto-publish - 4-star reviews: Auto-generate → Draft → Require Approval - 3-star reviews: Auto-generate → Draft → Require Approval + Slack alert - 1-2 star reviews: Auto-generate → Draft → ESCALATE + Slack alert → Require Approval Week 4: If 5-star auto-publish is successful, enable 4-star - 4-star reviews: Auto-generate AND Auto-publish - All others: unchanged
3
Final production configuration (after Week 4): - 4-5 star: Fully automated - 3 star: Human-in-the-loop (draft + approval) - 1-2 star: Escalation + human-in-the-loop - Keyword flagged: Blocked + escalation to GM + legal
Note

FTC compliance reminder: Auto-published responses are management replies to reviews, NOT fake reviews themselves. This is fully compliant with the August 2024 FTC rule. However, never auto-generate fake guest reviews — this carries penalties up to $51,744 per violation. Document the automation rules and get written sign-off from the hotel GM before enabling auto-publish.

Step 14: Configure Reporting & Analytics Dashboard

Set up the Google Looker Studio dashboard that provides the hotel GM and ownership with monthly visibility into review performance metrics. Connect it to data exported from MARA's analytics and the n8n PostgreSQL database. Schedule automated monthly report delivery via email.

1
Access Looker Studio: https://lookerstudio.google.com
2
Create New Report → 'Hotel Review Performance Dashboard'
3
Add Data Sources: a. Google Sheets (connected to MARA CSV export via n8n scheduled workflow) b. PostgreSQL (n8n database with processed review metadata)
4
Create dashboard pages: Page 1: Executive Summary - Total reviews (this month vs. last month) - Average rating by platform - Response rate percentage - Average response time Page 2: Sentiment Analysis - Sentiment trend over time (positive/neutral/negative) - Top mentioned topics (word cloud or bar chart) - Topic sentiment breakdown Page 3: Platform Comparison - Reviews by OTA platform - Average rating by platform - Response rate by platform Page 4: Competitive Benchmarking - Property rating vs. competitive set (if available)
5
Schedule email delivery: Monthly on 1st of month to GM + ownership
Note

Looker Studio is free and provides a professional client-facing deliverable. For multi-property clients, add a property selector filter so ownership can compare performance across locations. This dashboard becomes a key differentiator in the MSP's value proposition — it transforms raw review data into actionable business intelligence that justifies the monthly managed service fee.

Step 15: UptimeRobot Monitoring Configuration

Configure monitoring for all critical system components to ensure the MSP is alerted immediately if any part of the review pipeline goes down. Set up monitors for the n8n instance, MARA platform availability, and webhook endpoints.

1
Log into UptimeRobot: https://uptimerobot.com
2
Add monitors: a. n8n Health Check: - Type: HTTP(s) - URL: https://automation.hotelname.com/healthz - Interval: 5 minutes - Alert contacts: MSP NOC email + MSP technician b. MARA Platform: - Type: HTTP(s) - URL: https://app.mara-solutions.com - Interval: 5 minutes - Alert contacts: MSP NOC email c. Webhook Endpoint: - Type: HTTP(s) - Keyword - URL: https://automation.hotelname.com/webhook-test/mara-review-incoming - Keyword: (expected response body content) - Interval: 5 minutes
3
Create Status Page (optional - share with client): - Add all monitors to a public status page - URL: status.hotelname.com
Note

UptimeRobot's free tier supports up to 50 monitors with 5-minute intervals, which is sufficient for single-property deployments. For multi-property MSP operations, upgrade to Pro ($7/month) for 1-minute intervals and advanced alerting (SMS, webhook to PagerDuty/OpsGenie). Set up escalation: if a monitor is down for >15 minutes, escalate from email to SMS/phone call.

Custom AI Components

n8n Docker Compose Configuration

Type: integration

Complete Docker Compose configuration file for deploying n8n with PostgreSQL database and Caddy reverse proxy. This is the infrastructure foundation for all custom automation workflows.

Implementation:

docker-compose.yml — Location: /opt/n8n/docker-compose.yml
yaml
# docker-compose.yml
# Location: /opt/n8n/docker-compose.yml

version: '3.8'

services:
  n8n:
    image: docker.n8n.io/n8nio/n8n:latest
    restart: always
    ports:
      - '5678:5678'
    environment:
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=${N8N_BASIC_AUTH_USER}
      - N8N_BASIC_AUTH_PASSWORD=${N8N_BASIC_AUTH_PASSWORD}
      - N8N_HOST=${N8N_HOST}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=${WEBHOOK_URL}
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
      - DB_POSTGRESDB_USER=${POSTGRES_USER}
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      - GENERIC_TIMEZONE=America/New_York
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy
    networks:
      - n8n-net

  postgres:
    image: postgres:15-alpine
    restart: always
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init-db.sql:/docker-entrypoint-initdb.d/init-db.sql
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - n8n-net

  caddy:
    image: caddy:2-alpine
    restart: always
    ports:
      - '80:80'
      - '443:443'
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - n8n-net

volumes:
  n8n_data:
  postgres_data:
  caddy_data:
  caddy_config:

networks:
  n8n-net:
    driver: bridge

PostgreSQL Review Database Schema

Type: integration

Database initialization script that creates tables for storing review metadata, AI response drafts, escalation history, and reporting metrics. This provides persistent state management and enables the Looker Studio reporting dashboard.

Implementation:

init-db.sql
sql
-- Location: /opt/n8n/init-db.sql — Automatically executed on first
-- PostgreSQL container startup

-- init-db.sql
-- Location: /opt/n8n/init-db.sql
-- Automatically executed on first PostgreSQL container startup

CREATE TABLE IF NOT EXISTS reviews (
    id SERIAL PRIMARY KEY,
    external_id VARCHAR(255) UNIQUE NOT NULL,
    platform VARCHAR(50) NOT NULL, -- 'booking', 'google', 'expedia', 'tripadvisor'
    property_id VARCHAR(100) NOT NULL,
    guest_name VARCHAR(255),
    rating INTEGER CHECK (rating >= 1 AND rating <= 5),
    review_text TEXT NOT NULL,
    review_language VARCHAR(10) DEFAULT 'en',
    review_date TIMESTAMP NOT NULL,
    received_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    sentiment_score DECIMAL(3,2), -- -1.00 to 1.00
    sentiment_label VARCHAR(20), -- 'positive', 'neutral', 'negative'
    topics TEXT[], -- array of detected topics
    is_escalated BOOLEAN DEFAULT FALSE,
    escalation_reason VARCHAR(255),
    status VARCHAR(30) DEFAULT 'pending' -- 'pending', 'draft_generated', 'approved', 'published', 'rejected'
);

CREATE TABLE IF NOT EXISTS responses (
    id SERIAL PRIMARY KEY,
    review_id INTEGER REFERENCES reviews(id),
    ai_draft TEXT NOT NULL,
    final_response TEXT,
    was_edited BOOLEAN DEFAULT FALSE,
    edit_distance INTEGER, -- Levenshtein distance between draft and final
    approved_by VARCHAR(255),
    approved_at TIMESTAMP,
    published_at TIMESTAMP,
    generation_model VARCHAR(100), -- 'mara', 'gpt-5.4-mini', 'claude-sonnet'
    generation_time_ms INTEGER,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS escalations (
    id SERIAL PRIMARY KEY,
    review_id INTEGER REFERENCES reviews(id),
    escalation_type VARCHAR(50), -- 'negative_review', 'keyword_flag', 'legal_risk', 'health_safety'
    escalated_to VARCHAR(255), -- 'gm', 'gm+legal', 'msp'
    slack_message_ts VARCHAR(50), -- Slack message timestamp for threading
    resolved BOOLEAN DEFAULT FALSE,
    resolved_at TIMESTAMP,
    resolution_notes TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS daily_metrics (
    id SERIAL PRIMARY KEY,
    property_id VARCHAR(100) NOT NULL,
    metric_date DATE NOT NULL,
    total_reviews INTEGER DEFAULT 0,
    avg_rating DECIMAL(2,1),
    positive_count INTEGER DEFAULT 0,
    neutral_count INTEGER DEFAULT 0,
    negative_count INTEGER DEFAULT 0,
    responses_generated INTEGER DEFAULT 0,
    responses_auto_published INTEGER DEFAULT 0,
    responses_approved_no_edit INTEGER DEFAULT 0,
    responses_approved_with_edit INTEGER DEFAULT 0,
    responses_rejected INTEGER DEFAULT 0,
    avg_response_time_minutes INTEGER,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(property_id, metric_date)
);

CREATE INDEX idx_reviews_platform ON reviews(platform);
CREATE INDEX idx_reviews_property ON reviews(property_id);
CREATE INDEX idx_reviews_date ON reviews(review_date);
CREATE INDEX idx_reviews_rating ON reviews(rating);
CREATE INDEX idx_reviews_status ON reviews(status);
CREATE INDEX idx_escalations_resolved ON escalations(resolved);
CREATE INDEX idx_daily_metrics_date ON daily_metrics(property_id, metric_date);

Review Escalation & Notification Workflow

Type: workflow

n8n workflow that receives incoming review webhooks from MARA, classifies reviews by severity, routes negative reviews to the appropriate Slack channel with formatted rich messages including action buttons, logs all reviews to the PostgreSQL database, and sends summary notifications. This is the core autonomous agent orchestration layer.

Implementation:

n8n Workflow: Review Escalation & Notification — Import this as JSON in n8n → Workflows → Import from File

// Workflow Logic: // 1. Webhook receives review data from MARA // 2. Validate webhook signature // 3. Classify review severity // 4. Store in PostgreSQL // 5. Route to appropriate Slack channel // 6. For negative reviews: generate supplementary analysis via GPT-5.4 mini { "name": "Review Escalation & Notification", "nodes": [ { "parameters": { "httpMethod": "POST", "path": "mara-review-incoming", "responseMode": "responseNode", "options": {} }, "name": "Webhook - MARA Review", "type": "n8n-nodes-base.webhook", "position": [250, 300] }, { "parameters": { "conditions": { "number": [ { "value1": "={{$json.rating}}", "operation": "smallerEqual", "value2": 2 } ] } }, "name": "IF Negative (1-2 stars)", "type": "n8n-nodes-base.if", "position": [650, 200] }, { "parameters": { "conditions": { "number": [ { "value1": "={{$json.rating}}", "operation": "equal", "value2": 3 } ] } }, "name": "IF Neutral (3 stars)", "type": "n8n-nodes-base.if", "position": [650, 500] }, { "parameters": { "operation": "insert", "table": "reviews", "columns": "external_id, platform, property_id, guest_name, rating, review_text, review_language, review_date, sentiment_score, sentiment_label, topics, status", "additionalFields": {} }, "name": "PostgreSQL - Store Review", "type": "n8n-nodes-base.postgres", "position": [450, 300] }, { "parameters": { "channel": "#review-escalations", "text": "", "blocksUi": { "blocksValues": [ { "type": "header", "text": { "type": "plain_text", "text": "🚨 Negative Review Alert ({{$json.rating}}⭐)" } }, { "type": "section", "text": { "type": "mrkdwn", "text": "*Platform:* {{$json.platform}}\n*Guest:* {{$json.guest_name}}\n*Date:* {{$json.review_date}}\n\n> {{$json.review_text}}" } }, { "type": "section", "text": { "type": "mrkdwn", "text": "*AI Draft Response:*\n{{$json.ai_response_draft}}" } }, { "type": "section", "text": { "type": "mrkdwn", "text": "*AI Analysis:*\n{{$json.gpt_analysis}}" } }, { "type": "actions", "elements": [ { "type": "button", "text": {"type": "plain_text", "text": "✅ Approve Response"}, "style": "primary", "action_id": "approve_response" }, { "type": "button", "text": {"type": "plain_text", "text": "✏️ Edit in MARA"}, "url": "https://app.mara-solutions.com/reviews/{{$json.external_id}}" }, { "type": "button", "text": {"type": "plain_text", "text": "🚫 Reject"}, "style": "danger", "action_id": "reject_response" } ] } ] } }, "name": "Slack - Escalation Alert", "type": "n8n-nodes-base.slack", "position": [1050, 200] }, { "parameters": { "channel": "#guest-kudos", "text": "⭐ New {{$json.rating}}-star review on {{$json.platform}} from {{$json.guest_name}}!\n\n> {{$json.review_text}}\n\n✅ AI response auto-published." }, "name": "Slack - Positive Notification", "type": "n8n-nodes-base.slack", "position": [1050, 700] }, { "parameters": { "resource": "chat", "operation": "create", "model": "gpt-5.4-mini", "messages": { "values": [ { "role": "system", "content": "You are a hospitality operations analyst. Analyze this negative guest review and provide: 1) Root cause category (service, cleanliness, facilities, noise, F&B, value), 2) Specific operational failure identified, 3) Recommended corrective action for hotel management, 4) Risk assessment (low/medium/high) for reputation impact. Be concise — max 150 words." }, { "role": "user", "content": "Guest review ({{$json.rating}} stars on {{$json.platform}}): {{$json.review_text}}" } ] } }, "name": "OpenAI - Analyze Negative Review", "type": "@n8n/n8n-nodes-langchain.openAi", "position": [850, 200] }, { "parameters": { "respondWith": "json", "responseBody": "={\"status\": \"received\", \"review_id\": \"{{$json.external_id}}\"}" }, "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "position": [1250, 300] } ], "connections": { "Webhook - MARA Review": { "main": [[{"node": "PostgreSQL - Store Review", "type": "main", "index": 0}]] }, "PostgreSQL - Store Review": { "main": [ [ {"node": "IF Negative (1-2 stars)", "type": "main", "index": 0}, {"node": "IF Neutral (3 stars)", "type": "main", "index": 0} ] ] }, "IF Negative (1-2 stars)": { "main": [ [{"node": "OpenAI - Analyze Negative Review", "type": "main", "index": 0}], [{"node": "Slack - Positive Notification", "type": "main", "index": 0}] ] }, "OpenAI - Analyze Negative Review": { "main": [[{"node": "Slack - Escalation Alert", "type": "main", "index": 0}]] }, "IF Neutral (3 stars)": { "main": [ [{"node": "Slack - Escalation Alert", "type": "main", "index": 0}], [{"node": "Slack - Positive Notification", "type": "main", "index": 0}] ] }, "Slack - Escalation Alert": { "main": [[{"node": "Respond to Webhook", "type": "main", "index": 0}]] }, "Slack - Positive Notification": { "main": [[{"node": "Respond to Webhook", "type": "main", "index": 0}]] } } }
Sonnet 4.6
Note

After importing, manually verify the following:

Weekly Review Digest Workflow

Type: workflow

n8n workflow triggered on a weekly schedule (every Monday at 8 AM) that queries the PostgreSQL database for the past 7 days of review data, generates a narrative summary using GPT-5.4 mini, and delivers a formatted digest to the GM via Slack and email. This provides a high-level operational intelligence report without requiring the GM to log into any dashboard.

Implementation

n8n Workflow: Weekly Review Digest
json
# Trigger: Cron every Monday at 08:00 AM property local time

// n8n Workflow: Weekly Review Digest
// Trigger: Cron - Every Monday at 08:00 AM property local time

{
  "name": "Weekly Review Digest Report",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtDay": 1,
              "triggerAtHour": 8
            }
          ]
        }
      },
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [250, 300]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT platform, COUNT(*) as review_count, ROUND(AVG(rating), 1) as avg_rating, SUM(CASE WHEN rating >= 4 THEN 1 ELSE 0 END) as positive_count, SUM(CASE WHEN rating <= 2 THEN 1 ELSE 0 END) as negative_count FROM reviews WHERE review_date >= NOW() - INTERVAL '7 days' AND property_id = '{{$env.PROPERTY_ID}}' GROUP BY platform ORDER BY review_count DESC;"
      },
      "name": "PostgreSQL - Weekly Stats",
      "type": "n8n-nodes-base.postgres",
      "position": [450, 200]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT guest_name, platform, rating, LEFT(review_text, 200) as review_excerpt, sentiment_label FROM reviews WHERE review_date >= NOW() - INTERVAL '7 days' AND property_id = '{{$env.PROPERTY_ID}}' AND rating <= 2 ORDER BY review_date DESC LIMIT 5;"
      },
      "name": "PostgreSQL - Notable Negatives",
      "type": "n8n-nodes-base.postgres",
      "position": [450, 400]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT r.guest_name, r.platform, r.rating, LEFT(r.review_text, 200) as review_excerpt FROM reviews r LEFT JOIN responses resp ON r.id = resp.review_id WHERE r.review_date >= NOW() - INTERVAL '7 days' AND r.property_id = '{{$env.PROPERTY_ID}}' AND resp.id IS NULL ORDER BY r.review_date DESC;"
      },
      "name": "PostgreSQL - Unresponded Reviews",
      "type": "n8n-nodes-base.postgres",
      "position": [450, 600]
    },
    {
      "parameters": {
        "resource": "chat",
        "operation": "create",
        "model": "gpt-5.4-mini",
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a hospitality analytics consultant generating a concise weekly review digest for a hotel General Manager. Write in a professional but accessible tone. Use bullet points and bold text (Slack mrkdwn format). Include: 1) Executive summary (2-3 sentences), 2) Key metrics table, 3) Top positive themes, 4) Areas of concern from negative reviews, 5) One actionable recommendation for the coming week. Keep the total digest under 400 words."
            },
            {
              "role": "user",
              "content": "Weekly stats by platform: {{$node['PostgreSQL - Weekly Stats'].json}}\n\nNotable negative reviews: {{$node['PostgreSQL - Notable Negatives'].json}}\n\nUnresponded reviews: {{$node['PostgreSQL - Unresponded Reviews'].json}}\n\nGenerate the weekly review digest report."
            }
          ]
        }
      },
      "name": "OpenAI - Generate Digest",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [750, 300]
    },
    {
      "parameters": {
        "channel": "#review-weekly-digest",
        "text": "📊 *Weekly Review Digest — {{$now.format('MMMM D, YYYY')}}*\n\n{{$json.message.content}}"
      },
      "name": "Slack - Post Digest",
      "type": "n8n-nodes-base.slack",
      "position": [950, 300]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {"node": "PostgreSQL - Weekly Stats", "type": "main", "index": 0},
          {"node": "PostgreSQL - Notable Negatives", "type": "main", "index": 0},
          {"node": "PostgreSQL - Unresponded Reviews", "type": "main", "index": 0}
        ]
      ]
    },
    "PostgreSQL - Weekly Stats": {
      "main": [[{"node": "OpenAI - Generate Digest", "type": "main", "index": 0}]]
    },
    "PostgreSQL - Notable Negatives": {
      "main": [[{"node": "OpenAI - Generate Digest", "type": "main", "index": 0}]]
    },
    "PostgreSQL - Unresponded Reviews": {
      "main": [[{"node": "OpenAI - Generate Digest", "type": "main", "index": 0}]]
    },
    "OpenAI - Generate Digest": {
      "main": [[{"node": "Slack - Post Digest", "type": "main", "index": 0}]]
    }
  }
}

Negative Review Root Cause Analysis Prompt

Type: prompt

System prompt template for the GPT-5.4 mini analysis of negative reviews. This prompt is used in the Review Escalation workflow to generate actionable operational intelligence from negative guest feedback, categorizing issues and recommending corrective actions.

Implementation:

System Prompt: Negative Review Root Cause Analyst

You are an expert hospitality operations analyst specializing in guest experience recovery. Your role is to analyze negative guest reviews and provide actionable intelligence to hotel management.

For each review, produce a structured analysis with EXACTLY these sections:

  • 🔍 Root Cause Category: [Select ONE primary: Service Failure | Cleanliness Issue | Facility Problem | Noise Complaint | F&B Quality | Value Perception | Booking/Check-in Error | Safety Concern | Other]
  • 📋 Specific Issue: [One sentence describing the exact operational failure]
  • ⚠️ Risk Level: [LOW | MEDIUM | HIGH | CRITICAL] - LOW: Minor inconvenience, unlikely to deter future bookings - MEDIUM: Significant dissatisfaction, may influence potential guests reading reviews - HIGH: Serious failure, likely to generate multiple negative reviews if unaddressed - CRITICAL: Safety, health, legal, or discrimination issue requiring immediate action
  • 🛠️ Recommended Action: [One specific, actionable corrective measure the hotel should implement]
  • 💬 Response Guidance: [One sentence advising the GM on tone/approach for the management response]

Rules

  • Be direct and specific — avoid vague suggestions like "improve service"
  • If the review mentions a specific staff member, note this but do NOT recommend disciplinary action
  • If the review mentions health, safety, injury, discrimination, or legal threats, ALWAYS rate as CRITICAL
  • Keep total analysis under 120 words
  • Do not include the guest's name in your analysis
  • If the review is in a non-English language, still analyze in English

User Prompt Template:

Guest review ({{rating}} stars on {{platform}}, date: {{review_date}}):

"{{review_text}}"

handlebars
{{#if guest_stay_context}}
Guest stay context from PMS: {{guest_stay_context}}
{{/if}}

Analyze this review.

Brand Voice Response Generation Prompt

Type: prompt

Backup prompt template for generating review responses directly via OpenAI API when MARA is unavailable or for edge cases requiring custom LLM processing. This prompt is designed to produce hospitality-grade management responses that match the property's brand voice.

Implementation:

System Prompt: Hotel Review Response Generator

You are the General Manager of {{hotel_name}}, a {{hotel_description}}. You are writing personal responses to guest reviews on online travel platforms.

Your writing style:

  • Tone: {{tone_descriptor}} (e.g., "warm, professional, and genuinely caring")
  • Greeting format: {{greeting_format}} (e.g., "Dear {{guest_name}},")
  • Closing format: {{closing_format}} (e.g., "Warm regards,\n{{gm_name}}\nGeneral Manager, {{hotel_name}}")
  • Signature phrases: {{signature_phrases}} (e.g., "It was our pleasure to host you", "Your comfort is our priority")

Response guidelines:

1
ALWAYS address the guest by name
2
ALWAYS reference at least one SPECIFIC detail from their review (not generic)
3
For POSITIVE reviews (4-5 stars): Express genuine gratitude. Highlight the specific aspects they enjoyed. Invite them to return with a warm, non-salesy mention of an upcoming event, season, or new offering. Keep response to 80-120 words.
4
For NEUTRAL reviews (3 stars): Thank them for their balanced feedback. Acknowledge both the positives and areas for improvement. Describe a specific action being taken to address their concern. Invite them to return to experience the improvements. Keep response to 100-150 words.
5
For NEGATIVE reviews (1-2 stars): Express sincere empathy and apologize for their experience. DO NOT make excuses or be defensive. Reference the specific issue and describe the corrective action being taken. Offer to continue the conversation privately ("Please reach out to me directly at {{gm_email}}"). Keep response to 120-180 words.
Warning

NEVER: Offer compensation, discounts, or freebies in a public response. Dispute the guest's account of events. Use the word "but" after an apology. Include hashtags, emojis, or marketing language. Mention competitor properties. Reveal private guest information (room number, billing details, etc.).

{{#if property_facts}} Property facts for accurate references: {{property_facts}} {{/if}}

User Prompt Template:

User Prompt Template
handlebars
Write a management response to this {{rating}}-star review on {{platform}}:

Guest name: {{guest_name}}
Review date: {{review_date}}
Review text: "{{review_text}}"

{{#if topics_detected}}
Key topics detected: {{topics_detected}}
{{/if}}

{{#if smart_snippets}}
Relevant property information:
{{smart_snippets}}
{{/if}}

Generate the response.

Configuration Variables (set per property):

json
{
  "hotel_name": "The Grand Seaside Hotel",
  "hotel_description": "boutique 45-room oceanfront hotel in Santa Monica, California, known for personalized service and locally-sourced cuisine",
  "tone_descriptor": "warm, professional, and genuinely caring with a touch of coastal California personality",
  "greeting_format": "Dear {guest_name},",
  "closing_format": "With warm regards,\nSarah Mitchell\nGeneral Manager, The Grand Seaside Hotel",
  "signature_phrases": ["It was our pleasure to welcome you", "The ocean will be waiting for your return", "Your experience matters deeply to our team"],
  "gm_name": "Sarah Mitchell",
  "gm_email": "gm@grandseaside.com",
  "property_facts": "Rooftop pool open 7AM-10PM year-round. Chef Antonio's Restaurant serves breakfast 6:30-10:30AM and dinner 5:30-10PM. Complimentary beach cruiser bicycles. Valet parking $35/night. Spa opening Q2 2025. Pet-friendly rooms available in Garden Wing."
}

Keyword Safety Filter Agent

Type: agent

An autonomous pre-processing agent that scans incoming reviews for high-risk keywords before any AI response is generated. Reviews containing keywords related to safety, legal threats, health violations, discrimination, or harassment are immediately flagged and blocked from automated response, requiring direct GM intervention. This is a critical compliance safeguard.

Implementation

Keyword Safety Filter
javascript
// n8n Function node. Place BEFORE the response generation step in the Review
// Escalation workflow. Node type: n8n-nodes-base.function

const review = $input.first().json;
const reviewText = (review.review_text || '').toLowerCase();
const guestName = (review.guest_name || '').toLowerCase();

// HIGH-RISK KEYWORD CATEGORIES
const SAFETY_KEYWORDS = [
  'injury', 'injured', 'hurt', 'fell', 'slipped', 'tripped',
  'fire', 'smoke detector', 'carbon monoxide', 'emergency exit',
  'unsafe', 'danger', 'hazard', 'accident', 'ambulance',
  'electric shock', 'burn', 'poisoned', 'allergic reaction'
];

const LEGAL_KEYWORDS = [
  'lawsuit', 'lawyer', 'attorney', 'legal action', 'sue',
  'court', 'litigation', 'negligence', 'liability',
  'class action', 'complaint filed', 'regulatory',
  'health department', 'health inspector', 'code violation',
  'osha', 'ada violation'
];

const DISCRIMINATION_KEYWORDS = [
  'discrimination', 'discriminated', 'racist', 'racism',
  'sexist', 'sexism', 'homophobic', 'transphobic',
  'ableist', 'disability', 'accessible', 'ada',
  'profiling', 'biased', 'prejudice', 'hate'
];

const HARASSMENT_KEYWORDS = [
  'harassment', 'harassed', 'stalked', 'threatened',
  'assault', 'assaulted', 'inappropriate', 'groped',
  'touched', 'sexual', 'hostile', 'intimidated', 'abuse'
];

const HEALTH_KEYWORDS = [
  'bed bugs', 'bedbugs', 'cockroach', 'roach', 'rat', 'mice', 'mouse',
  'mold', 'mould', 'food poisoning', 'vomit', 'diarrhea',
  'blood', 'needle', 'syringe', 'feces', 'urine',
  'legionella', 'legionnaires'
];

const FRAUD_KEYWORDS = [
  'scam', 'fraud', 'stolen', 'theft', 'stole',
  'credit card', 'overcharged', 'double charged',
  'unauthorized charge', 'identity theft', 'bait and switch'
];

// CHECK FUNCTION
function findMatches(text, keywords) {
  return keywords.filter(kw => text.includes(kw));
}

const safetyMatches = findMatches(reviewText, SAFETY_KEYWORDS);
const legalMatches = findMatches(reviewText, LEGAL_KEYWORDS);
const discrimMatches = findMatches(reviewText, DISCRIMINATION_KEYWORDS);
const harassMatches = findMatches(reviewText, HARASSMENT_KEYWORDS);
const healthMatches = findMatches(reviewText, HEALTH_KEYWORDS);
const fraudMatches = findMatches(reviewText, FRAUD_KEYWORDS);

const allMatches = [
  ...safetyMatches.map(k => ({keyword: k, category: 'SAFETY'})),
  ...legalMatches.map(k => ({keyword: k, category: 'LEGAL'})),
  ...discrimMatches.map(k => ({keyword: k, category: 'DISCRIMINATION'})),
  ...harassMatches.map(k => ({keyword: k, category: 'HARASSMENT'})),
  ...healthMatches.map(k => ({keyword: k, category: 'HEALTH'})),
  ...fraudMatches.map(k => ({keyword: k, category: 'FRAUD'}))
];

const isHighRisk = allMatches.length > 0;
const riskCategories = [...new Set(allMatches.map(m => m.category))];

// Determine escalation level
let escalationLevel = 'NONE';
if (legalMatches.length > 0 || discrimMatches.length > 0 || harassMatches.length > 0) {
  escalationLevel = 'CRITICAL'; // Requires GM + legal review
} else if (safetyMatches.length > 0 || healthMatches.length > 0) {
  escalationLevel = 'HIGH'; // Requires GM review + potential operational response
} else if (fraudMatches.length > 0) {
  escalationLevel = 'HIGH'; // Requires GM + finance review
}

return [{
  json: {
    ...review,
    safety_filter: {
      is_high_risk: isHighRisk,
      escalation_level: escalationLevel,
      risk_categories: riskCategories,
      matched_keywords: allMatches,
      block_auto_response: isHighRisk,
      requires_legal_review: legalMatches.length > 0 || discrimMatches.length > 0 || harassMatches.length > 0,
      filter_timestamp: new Date().toISOString()
    }
  }
}];

Downstream Routing

  • If safety_filter.block_auto_response === true: Route to 'CRITICAL Escalation' Slack alert (includes @channel mention)
  • If safety_filter.block_auto_response === true: Block any AI response generation
  • If safety_filter.block_auto_response === true: Insert escalation record into 'escalations' table
  • If safety_filter.block_auto_response === true: Email GM + designated legal contact
  • If safety_filter.block_auto_response === false: Continue normal review processing pipeline

MARA API Polling Fallback Workflow

Type: workflow

Alternative n8n workflow that polls MARA's review inbox on a 15-minute schedule instead of relying on webhooks. Use this if MARA's webhook feature is unavailable on the selected plan tier, or as a redundancy layer to catch any reviews missed by the webhook pipeline.

Implementation:

n8n Workflow JSON — MARA Review Polling Fallback
json
// n8n Workflow: MARA Review Polling (Fallback)
// Trigger: Schedule - Every 15 minutes
// Purpose: Poll MARA API for new reviews as alternative to webhook delivery

{
  "name": "MARA Review Polling Fallback",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 15
            }
          ]
        }
      },
      "name": "Schedule Trigger (15min)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [250, 300]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://api.mara-solutions.com/v1/reviews",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "since",
              "value": "={{$now.minus({minutes: 20}).toISO()}}"
            },
            {
              "name": "status",
              "value": "new"
            }
          ]
        },
        "options": {}
      },
      "name": "HTTP Request - Fetch New Reviews",
      "type": "n8n-nodes-base.httpRequest",
      "position": [450, 300]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$json.reviews.length}}",
              "operation": "larger",
              "value2": 0
            }
          ]
        }
      },
      "name": "IF New Reviews Exist",
      "type": "n8n-nodes-base.if",
      "position": [650, 300]
    },
    {
      "parameters": {
        "fieldToSplitOut": "reviews"
      },
      "name": "Split Reviews into Items",
      "type": "n8n-nodes-base.splitOut",
      "position": [850, 200]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO reviews (external_id, platform, property_id, guest_name, rating, review_text, review_language, review_date, status) VALUES ('{{$json.id}}', '{{$json.platform}}', '{{$json.property_id}}', '{{$json.guest_name}}', {{$json.rating}}, '{{$json.review_text}}', '{{$json.language}}', '{{$json.review_date}}', 'pending') ON CONFLICT (external_id) DO NOTHING RETURNING id;"
      },
      "name": "PostgreSQL - Deduplicate & Store",
      "type": "n8n-nodes-base.postgres",
      "position": [1050, 200]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$json.id}}",
              "operation": "isNotEmpty"
            }
          ]
        }
      },
      "name": "IF New (Not Duplicate)",
      "type": "n8n-nodes-base.if",
      "position": [1250, 200]
    }
  ],
  "connections": {
    "Schedule Trigger (15min)": {
      "main": [[{"node": "HTTP Request - Fetch New Reviews", "type": "main", "index": 0}]]
    },
    "HTTP Request - Fetch New Reviews": {
      "main": [[{"node": "IF New Reviews Exist", "type": "main", "index": 0}]]
    },
    "IF New Reviews Exist": {
      "main": [
        [{"node": "Split Reviews into Items", "type": "main", "index": 0}],
        []
      ]
    },
    "Split Reviews into Items": {
      "main": [[{"node": "PostgreSQL - Deduplicate & Store", "type": "main", "index": 0}]]
    },
    "PostgreSQL - Deduplicate & Store": {
      "main": [[{"node": "IF New (Not Duplicate)", "type": "main", "index": 0}]]
    }
  }
}

// NOTE: After 'IF New (Not Duplicate)' true branch,
// connect to the same Keyword Safety Filter and Slack notification
// nodes from the primary Review Escalation workflow.
// The ON CONFLICT (external_id) DO NOTHING clause ensures
// no duplicate processing if both webhook and polling capture the same review.

Testing & Validation

  • CONNECTIVITY TEST: Log into MARA dashboard and verify all 4 OTA platforms (Booking.com, Google, Expedia, TripAdvisor) show 'Connected' status with green indicators. Confirm historical reviews are populating in the Review Inbox — expect to see at least the last 30 days of reviews from each platform.
  • BRAND VOICE TEST: In MARA, use the 'Test Voice' feature to generate 10 sample responses across a mix of 1-star through 5-star reviews. Have the hotel GM rate each response on a 1-5 scale for voice accuracy, factual correctness, and appropriateness. Target: average score of 4.0+ across all responses before proceeding to production.
  • POSITIVE REVIEW AUTO-PUBLISH TEST: After enabling auto-publish for 5-star reviews, wait for (or manually simulate) a genuine 5-star review. Verify: MARA generates a response, the response is automatically published to the OTA platform without human intervention, and a celebratory notification appears in Slack #guest-kudos within 5 minutes.
  • NEGATIVE REVIEW ESCALATION TEST: Wait for (or simulate) a 1-star review. Verify: MARA generates a draft response (NOT published), GPT-5.4 mini generates an operational analysis, Slack #review-escalations receives a formatted alert with the review text, AI draft response, AI analysis, and Approve/Edit/Reject action buttons. Confirm the GM can click 'Edit in MARA' and be taken directly to the review in MARA's dashboard.
  • WEEKLY DIGEST TEST: Manually trigger the Weekly Digest workflow in n8n. Verify: PostgreSQL queries return valid data, GPT-5.4 mini generates a coherent narrative summary, and the formatted digest is posted to Slack #review-weekly-digest with proper formatting, metrics, and actionable recommendations.
  • UPTIME MONITORING TEST: In UptimeRobot, manually pause the n8n Docker container and wait 5 minutes. Verify: UptimeRobot sends a downtime alert to the MSP NOC email within 6 minutes. Restart n8n and verify UptimeRobot sends an 'up' recovery notification.
  • END-TO-END LATENCY TEST: Post a new Google review on the hotel's Google Business Profile. Start a timer. Measure: (1) Time until review appears in MARA inbox, (2) Time until AI response draft is generated, (3) Time until Slack notification is received, (4) If auto-publish is enabled, time until response appears on Google. Target: end-to-end under 15 minutes for auto-published positive reviews, under 5 minutes for Slack escalation notifications.
  • MULTI-LANGUAGE TEST: If the hotel receives international guests, submit a test review in Spanish, German, or another common guest language. Verify: MARA detects the language, generates a response in the same language, and the Slack notification includes both the original review and an English translation for the GM.

Webhook Delivery Test

Send a test POST request to the n8n webhook endpoint using curl. Verify: n8n execution log shows successful run, PostgreSQL has a new record in the 'reviews' table, and Slack #review-escalations channel receives a formatted alert within 60 seconds.

Webhook Delivery Test — POST request to n8n endpoint
bash
curl -X POST https://automation.hotelname.com/webhook/mara-review-incoming \
  -H 'Content-Type: application/json' \
  -d '{"external_id":"test-001","platform":"google","property_id":"hotel-1","guest_name":"Test Guest","rating":2,"review_text":"The room was dirty and the staff was rude. Very disappointed.","review_date":"2025-01-15T10:00:00Z"}'

Keyword Safety Filter Test

Submit a test review containing the text: 'I slipped on the wet bathroom floor and injured my back. I am contacting my lawyer.'

Critical

Verify the safety filter flags this review as CRITICAL with categories SAFETY + LEGAL, the auto-response is blocked, and an immediate escalation alert is sent to both the GM and the MSP's NOC Slack channel with @channel mention.

Database Integrity Test

After 48 hours of operation, run the following query against PostgreSQL. Verify: duplicates = 0, confirming the deduplication logic works correctly.

Database Integrity Check — deduplication validation query
sql
SELECT
  COUNT(*) AS total,
  COUNT(DISTINCT external_id) AS unique_ids,
  COUNT(*) - COUNT(DISTINCT external_id) AS duplicates
FROM reviews;

Uptime Monitoring Test — Docker Command

In UptimeRobot, manually pause the n8n Docker container using the command below, then wait 5 minutes.

Pause n8n container to trigger UptimeRobot downtime alert
bash
docker compose stop n8n

Compliance Audit

Review the final automation rules configuration and verify all of the following:

Client Handoff

Client Handoff Checklist

Training Session (2 hours, on-site or video call with GM + front desk supervisor)

Module 1: MARA Dashboard Orientation (30 minutes)

  • Walk through the Review Inbox — how to see all reviews across platforms in one place
  • Demonstrate how to review, edit, and approve AI-generated response drafts
  • Show how to reject a response and write a custom one
  • Explain the automation rules: which reviews auto-publish vs. require approval
  • Show where to update Smart Snippets when hotel amenities/policies change

Module 2: Slack Notifications & Escalation (20 minutes)

  • Walk through the three Slack channels: #guest-kudos, #review-escalations, #review-weekly-digest
  • Demonstrate the escalation workflow: how a negative review triggers an alert
  • Show how to use the Approve/Edit/Reject buttons in Slack
  • Explain the keyword safety filter and what CRITICAL escalations look like

Module 3: Reading the Weekly Digest (15 minutes)

  • Review a sample weekly digest report
  • Explain the metrics: review volume, average rating, sentiment trends, response rates
  • Show how to use the Looker Studio dashboard for deeper analysis

Module 4: Dos and Don'ts (15 minutes)

Critical

NEVER use the system to generate fake guest reviews (FTC violation, up to $51,744/violation)

  • ALWAYS review negative review responses before publishing
  • DO update Smart Snippets when policies change (seasonal hours, renovations, new amenities)
  • DO forward any review mentioning legal action, safety, or discrimination to the MSP immediately
  • DO review the weekly digest every Monday and share insights with department heads

Module 5: When to Call the MSP (10 minutes)

  • OTA platform shows disconnected in MARA
  • AI responses seem off-brand or factually incorrect
  • A CRITICAL escalation is received
  • Staff changes require updated notification routing
  • Any system errors or unexpected behavior

Documentation to Leave Behind

1
Quick Reference Card (1 page, laminated): MARA login URL, Slack channel names, MSP support contact, emergency escalation phone number
2
Smart Snippets Update Guide (2 pages): Step-by-step instructions with screenshots for updating property facts in MARA
3
Automation Rules Reference (1 page): Table showing which star ratings auto-publish vs. require approval
4
Keyword Safety Filter Reference (1 page): List of keyword categories that trigger escalation
5
Monthly Reporting Guide (2 pages): How to read and interpret the Looker Studio dashboard
6
MSP Service Agreement: Scope of managed services, SLA for response to system issues, monthly review cadence

Success Criteria to Review Together at Handoff

Maintenance

Ongoing Maintenance Responsibilities

Weekly Tasks (MSP Technician — 30 minutes/week)

  • Review n8n execution logs for any failed workflows — investigate and resolve errors
  • Check UptimeRobot dashboard for any downtime incidents in the past week
  • Verify OTA platform connections in MARA are all active (green status)
  • Review the Slack #review-escalations channel for any unresolved CRITICAL escalations
  • Spot-check 2-3 auto-published responses for quality and accuracy

Monthly Tasks (MSP Technician — 2 hours/month)

  • Generate and deliver the monthly Looker Studio report to the hotel GM and ownership
  • Review AI response approval metrics: if approval-without-edit rate drops below 75%, schedule Brand Voice retraining
  • Review OpenAI API usage and costs — ensure spending is within budget
  • Check PostgreSQL database size and run VACUUM ANALYZE if needed
  • Review and rotate API keys and credentials per security policy
Update n8n and Docker images
bash
cd /opt/n8n && docker compose pull && docker compose up -d

Quarterly Tasks (MSP Account Manager + Technician — 3 hours/quarter)

  • Quarterly Business Review with hotel GM: present sentiment trends, competitive benchmarking, ROI metrics
  • Update MARA Smart Snippets with any changed hotel policies, seasonal offerings, renovation updates
  • Retrain Brand Voice AI if GM has changed or hotel repositioning has occurred
  • Review and update the keyword safety filter for any new risk categories
  • Test disaster recovery: stop n8n, verify UptimeRobot alerts fire, restart and verify all workflows resume
  • Review MARA subscription tier — upgrade if review volume has grown
  • Audit compliance: verify no auto-responses on negative reviews, DPA still current, no fake review generation

Annual Tasks

  • Full platform audit: review all integrations, credentials, workflow logic, and automation rules
  • Renegotiate MARA subscription (annual billing discount typically 15-20%)
  • Evaluate new platform features or competitive alternatives that may improve the solution
  • Update the implementation documentation with any changes made during the year
  • Conduct a tabletop exercise for the CRITICAL escalation workflow with hotel management

SLA Considerations

  • System Availability Target: 99.5% uptime for the n8n automation pipeline
  • Response to CRITICAL Escalation: MSP acknowledges within 1 hour during business hours, 4 hours after hours
  • Response to System Outage: MSP begins troubleshooting within 30 minutes during business hours
  • Platform Integration Failure: If an OTA connection drops, MSP restores within 4 business hours
  • Monthly Reporting: Delivered by 5th business day of each month

Escalation Path

1
Level 1 (Hotel Staff): GM reviews and approves/edits AI responses in MARA; handles routine Slack notifications
2
Level 2 (MSP Technician): System errors, disconnected OTA platforms, workflow failures, Smart Snippet updates
3
Level 3 (MSP Senior Engineer): n8n server issues, database problems, API integration failures, prompt engineering
4
Level 4 (Vendor Support): MARA Solutions support for platform bugs, OTA API changes, new feature requests

Model Retraining Triggers

  • GM approval-without-edit rate drops below 75% for two consecutive weeks
  • New GM is hired (different communication style)
  • Hotel undergoes significant renovation or repositioning
  • Hotel adds new amenities, restaurants, or services
  • Guest demographic shifts significantly (e.g., business to leisure, domestic to international)
  • A new OTA platform is added to the monitoring scope

Alternatives

GuestRevu Budget Deployment

Replace MARA Solutions with GuestRevu as the core review management platform. GuestRevu offers a free LITE tier and a CORE tier at $34.99/month per property, making it the most affordable entry point for small independent hotels with fewer than 20 rooms and low review volumes (<20 reviews/month). The platform includes basic AI response suggestions, review aggregation, and guest survey capabilities.

Note

Tradeoffs: Cost savings of $25-$95/month per property vs. MARA, plus a free tier option for proof-of-concept deployments. However, GuestRevu's AI response engine is less sophisticated than MARA's Brand Voice AI — responses may feel more templated and require more manual editing. Fewer native OTA integrations and no Service Ticket AI feature. Recommend this for: budget-constrained independent hotels, properties with very low review volume, or as a 'land and expand' strategy where the MSP starts with GuestRevu free tier and upgrades to MARA once the client sees value.

TrustYou Enterprise Deployment

Replace MARA with TrustYou CXP Professional ($180/month per property) for hotel groups with 5+ properties that need enterprise features: unlimited AI surveys, full Customer Data Platform (CDP) integration, multi-property benchmarking, and connections to marketing platforms like HubSpot and Mailchimp. TrustYou also offers a stronger channel partner program for MSPs seeking formal reseller agreements.

Tradeoffs

Higher per-property cost ($180 vs $60-130 for MARA), but significantly more powerful for multi-property groups. TrustYou's CDP enables guest data unification across review, survey, and PMS data — a capability MARA doesn't offer. Better competitive intelligence and benchmarking features. Longer implementation timeline (4-8 weeks vs 3-6 for MARA) due to more complex configuration.

Note

Recommend this for: hotel groups with 5+ properties, luxury/upscale brands that need deep analytics, or clients that also want integrated guest survey capabilities.

Fully Custom Agent (n8n + LLM API, No SaaS Platform)

Eliminate the MARA subscription entirely and build the complete review monitoring and response pipeline using n8n workflows, direct OTA API connections (Google Business Profile API, Expedia Lodging Supply GraphQL API), web scraping for platforms without APIs, and OpenAI GPT-5.4 mini or Claude Haiku 3.5 for response generation. The MSP owns and white-labels the entire solution.

Tradeoffs

  • Eliminates the $60-180/month SaaS cost per property, replacing it with ~$25-50/month in infrastructure + API costs — dramatically better unit economics at scale (10+ properties).
  • Full white-label capability with complete MSP branding.
  • Requires Level 3 senior engineer (6-10 weeks build time).
  • Ongoing prompt engineering maintenance required.
  • Direct responsibility for OTA API compliance and changes.
  • No vendor support.
  • Booking.com reviews are extremely difficult to access without a connectivity partner (no public API).
  • Higher operational risk — if the engineer who built it leaves, institutional knowledge may be lost.
Warning

Recommend this ONLY when managing 10+ properties where the annual SaaS savings ($7,200-$21,600+) justify the development investment, or when the MSP wants to productize this as their own SaaS offering for resale to multiple hotel clients.

Birdeye Cross-Industry Platform

Use Birdeye ($299-$449/month) instead of MARA for hotels that also operate restaurants, spas, event venues, or other businesses under the same brand. Birdeye is not hospitality-specific but offers strong AI review response generation across multiple business listing types, with a single dashboard managing all locations and business categories.

Note

Tradeoffs: More expensive than MARA ($299+/month vs $60-130) and lacks hospitality-specific features like PMS integration, Service Ticket AI, and hotel Brand Voice training. However, Birdeye is significantly better for multi-vertical businesses (hotel + restaurant + spa as separate Google listings). Also stronger for local SEO management and review generation campaigns. Recommend this for: hotel properties that are part of a larger hospitality complex with multiple distinct Google/Yelp listings, or when the client already uses Birdeye for another business unit.

Revinate CRM-Centric Approach

Use Revinate ($4/room/month, minimum $399/month) as a combined CRM + review management platform. Revinate's core strength is guest CRM and email marketing, with review monitoring as a complementary feature. This approach is ideal when the hotel's primary pain point is guest lifecycle marketing and reviews are a secondary concern.

Tradeoffs

Higher minimum cost ($399/month) prices out small properties, but per-room pricing can be cost-effective for larger hotels (100+ rooms = ~$400/month). Revinate's review AI is less advanced than MARA's dedicated platform, but the integrated CRM enables powerful workflows: segment guests by review sentiment, trigger re-engagement campaigns for detractors, and upsell to promoters.

Note

Recommend this when: the hotel also needs a CRM/email marketing solution, the property has 80+ rooms (making per-room pricing competitive), or when review management is part of a broader guest engagement strategy.

Want early access to the full toolkit?