# Google Maps Review Alerts to Slack — new reviews only (`travelmonitorlab/review-radar`) Actor

Monitor Google Maps reviews, detect new ones, alert Slack about negative reviews via MCP connector. Zero credentials in code.

- **URL**: https://apify.com/travelmonitorlab/review-radar.md
- **Developed by:** [Travel Monitor Lab](https://apify.com/travelmonitorlab) (community)
- **Categories:** E-commerce, Social media
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Review Radar — Google Maps review alerts to Slack via MCP connector

Monitor Google Maps reviews for a portfolio of businesses, detect **only what's new** across runs (persistent state), and post **Slack alerts for negative reviews** through an Apify MCP connector — the Actor never sees a credential, only a connector ID.

### Why this Actor is different

Most review scrapers are stateless: every run returns everything, and you diff by hand. Review Radar keeps a named key-value store of seen review IDs per place, so a scheduled run surfaces **exactly the reviews published since the last run** — the difference between a scraper and a monitor. The Slack side uses [MCP connectors](https://docs.apify.com/integrations/mcp-connectors): you authorize Slack once in your Apify account, the Actor receives a connector ID at runtime, and the proxy enforces which tools it may call.

### Use this tool when

- You run an agency and monitor reviews across a client portfolio (hotels, restaurants, local businesses)
- You want a Slack ping the moment a damaging review lands — not a weekly report
- You want a working example of persistent state (named KV store) + optional MCP connector in one Actor

### Input

| Field | Description |
|---|---|
| `placeUrls` | Google Maps `/maps/place/...` URLs to monitor |
| `query` | Alternative: a Maps search (first `maxPlaces` results) |
| `maxPlaces` | How many businesses (default 3, max 20) |
| `maxReviewsPerPlace` | Recent reviews scraped per business (default 10, max 50) |
| `alertThreshold` | New reviews at or below this rating trigger an alert (default 3) |
| `slackConnector` | Optional Slack MCP connector. Empty = dataset only |
| `proxyConfiguration` | Residential proxy strongly recommended |
| `dryRun` | Skip Slack alerts and skip state writes (testing) |

### Output

One dataset item per review: `place`, `author`, `rating`, `text`, `date`, `reviewId`, `isNew`, `alerted`, `mapsUrl`, `scrapedAt`.

### Prerequisites

- An Apify account (free plan works)
- Optional: a Slack workspace authorized as an MCP connector (Console → Settings → Integrations)
- A residential proxy for the Maps scraping

### Run it

1. Open the Actor in Apify Console (or `apify push` from this folder).
2. Provide place URLs (or a search query), set the threshold, pick your Slack connector.
3. Run once to seed the state (everything reports as new), then attach a daily schedule — subsequent runs only report fresh reviews.

### How it works

1. Playwright loads each place page (consent wall handled, media blocked, 240s handler timeout).
2. Reviews are scraped (author, rating from `aria-label`, text, relative date) and deduplicated by stable review ID.
3. Each ID is diffed against the named store `review-radar-state`; new IDs are flagged and persisted.
4. New reviews at or below the threshold are posted to Slack via the MCP proxy (`ACTOR_MCP_CONNECTOR_BASE_URL` + run `APIFY_TOKEN`).

### Terms

Public review data only. Google Maps scraping sits uneasily with Google's ToS — keep volumes polite (daily cadence, few places), weigh the risk for production use, and prefer official APIs where they cover your need.

AI-agent ready, API + MCP ready.

# Actor input Schema

## `placeUrls` (type: `array`):

Google Maps place URLs (/maps/place/...) to monitor

## `query` (type: `string`):

Google Maps search, e.g. 'restaurants Esch-sur-Alzette' — takes the first maxPlaces results. Ignored if placeUrls is non-empty.

## `maxPlaces` (type: `integer`):

How many businesses to monitor (from placeUrls or the search query)

## `maxReviewsPerPlace` (type: `integer`):

How many recent reviews to scrape per business

## `alertThreshold` (type: `integer`):

New reviews with this rating or lower trigger a Slack alert

## `dryRun` (type: `boolean`):

Testing mode: skips Slack alerts, state writes, and billing events

## `slackConnector` (type: `string`):

MCP connector to your Slack workspace. Authorize once in Apify Console → Settings → Integrations. The Actor only sees a connector ID. Leave empty to skip alerts (dataset only).

## `proxyConfiguration` (type: `object`):

A residential proxy is strongly recommended — Google Maps blocks datacenter IPs.

## Actor input object example

```json
{
  "placeUrls": [],
  "maxPlaces": 3,
  "maxReviewsPerPlace": 10,
  "alertThreshold": 3,
  "dryRun": false
}
```

# Actor output Schema

## `reviews` (type: `string`):

One item per scraped review (place, author, rating, text, date, isNew, alerted)

## `state` (type: `string`):

Named key-value store persisting seen review IDs across runs

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("travelmonitorlab/review-radar").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("travelmonitorlab/review-radar").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call travelmonitorlab/review-radar --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,travelmonitorlab/review-radar"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/xdyXzPggpe8PVrjxh/builds/HIL1IgqzGaa9sudlc/openapi.json
