# App Store & Google Play Review Monitor (`matteogenovese/app-review-monitor`) Actor

Monitor App Store and Google Play reviews for any app. Get normalized review data, filter by rating or keywords, deduplicate new reviews, and send Slack, Discord, or JSON webhook alerts

- **URL**: https://apify.com/matteogenovese/app-review-monitor.md
- **Developed by:** [Matteo Genovese](https://apify.com/matteogenovese) (community)
- **Categories:** Automation, Developer tools, Social media
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.01 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## App Review Monitor

Turn App Store and Google Play reviews into alerts, weekly digests, and structured data.

### Why it matters
App reviews are one of the fastest public signals that something changed: a release broke login, a pricing update upset users, or a competitor is shipping badly and losing trust. This Actor turns those reviews into something operational.

### What it does
- monitors the Apple App Store and Google Play
- fetches the latest reviews for a single app
- normalizes Apple and Google Play data into one output shape
- filters by minimum rating if needed
- matches configured keywords inside titles and review text
- keeps track of seen review IDs in monitor mode
- posts alerts to a webhook when new reviews are found
- supports generic JSON, Slack, and Discord webhook payloads

### Best for
- product and growth teams
- support and ops teams
- indie app makers
- agencies managing client apps
- analysts tracking ratings and review trends

### Why it wins
- one clean schema for Apple and Google Play
- no browser automation
- no HTML scraping
- no heavyweight setup
- easy to plug into Apify schedules, webhooks, and datasets

### Quick start
1. Choose a platform: `apple` or `googlePlay`.
2. Set the app identifier.
   - Apple: numeric app ID
   - Google Play: package name
3. Pick a country code such as `us`, `gb`, `de`, or `fr`.
4. Set `language` for Google Play if needed.
5. Leave `monitorMode` enabled if you want only unseen reviews on later runs.
6. Optionally set `minRating`, `keywords`, and `webhookUrl`.
7. Choose `webhookFormat` if you want Slack or Discord friendly payloads.
8. Run it once or schedule it in Apify.

### Input example
```json
{
  "platform": "apple",
  "appId": "284882215",
  "country": "us",
  "language": "en",
  "reviewLimit": 50,
  "minRating": 1,
  "monitorMode": true,
  "webhookUrl": "https://example.com/app-review-alert",
  "webhookFormat": "slack",
  "keywords": ["crash", "refund", "login"],
  "dryRun": false
}
````

### Output

Each dataset row is one normalized review. App metadata is attached when available.

```json
[
  {
    "reviewId": "1122334455",
    "author": "ReviewerName",
    "rating": 1,
    "title": "Crashes after update",
    "text": "The latest version crashes every time I open it.",
    "publishedAt": "2026-07-04T09:00:00-07:00",
    "version": "3.2.1",
    "appId": "284882215",
    "country": "us",
    "platform": "apple",
    "appName": "Example App",
    "sellerName": "Example Ltd",
    "bundleId": "com.example.app",
    "storeUrl": "https://apps.apple.com/us/app/example-app/id123",
    "iconUrl": "https://example.com/icon.png",
    "sourceUrl": "https://apps.apple.com/us/review/...",
    "matchedKeywords": ["crash"]
  }
]
```

### Weekly digest

If you want a weekly digest, schedule the Actor in Apify once per week and keep `monitorMode` on.

Recommended setup:

- schedule it every Monday morning
- keep `reviewLimit` at a sensible recent window, usually 50 to 100
- use `webhookUrl` if you want the digest pushed somewhere automatically
- use `webhookFormat: slack` or `webhookFormat: discord` for native payloads

That gives you a clean weekly review summary without building a separate pipeline.

### Ready-made Slack and Discord alerts

#### Slack

Set:

- `webhookUrl` to a Slack incoming webhook
- `webhookFormat` to `slack`

The Actor sends a Slack-friendly payload with:

- a short headline
- app name and platform
- average rating
- number of new reviews
- low-rated review count
- top review snippets

#### Discord

Set:

- `webhookUrl` to a Discord webhook
- `webhookFormat` to `discord`

The Actor sends a Discord embed with:

- headline
- app name and platform
- average rating
- new review count
- top keywords
- top review snippets

#### Generic JSON

If you want full control, keep `webhookFormat` on `generic` and wire the payload into your own automation.

### Data fields

- `reviewId` — stable review identifier used for monitor deduplication
- `author` — reviewer display name when available
- `rating` — 1 to 5
- `title` — review title
- `text` — full review text
- `publishedAt` — publication or update time
- `version` — app version reviewed when available
- `appId` — input app identifier
- `country` — store country code
- `platform` — `apple` or `googlePlay`
- `appName` — store app name when available
- `sellerName` — developer or seller name when available
- `bundleId` — bundle ID or developer ID when available
- `storeUrl` — store listing URL when available
- `iconUrl` — app icon URL when available
- `sourceUrl` — original review page URL
- `matchedKeywords` — keyword hits from the configured filter list

### Why this actor exists

Teams do not need a review warehouse. They need the signal when reviews start telling a story.

### Competition

- generic scraping workflows
- app analytics dashboards
- manual review checking

### Pricing

- pricing is optimized for monitoring single apps with recurring checks
- use Apify billing and schedule settings to fit your volume
- webhook and dataset outputs are included in the normal actor flow

### Publish status

- public on Apify
- designed for scheduled monitoring
- ready for webhook-driven workflows

# Actor input Schema

## `platform` (type: `string`):

App store platform to monitor.

## `appId` (type: `string`):

Apple App Store numeric ID or Google Play package name.

## `country` (type: `string`):

Two-letter store country code.

## `language` (type: `string`):

Language code used for app metadata and Google Play requests.

## `reviewLimit` (type: `integer`):

Maximum number of recent reviews to process.

## `minRating` (type: `integer`):

Only include reviews with this rating or higher. Leave empty to include all ratings.

## `monitorMode` (type: `boolean`):

When enabled, compare reviews against stored state and emit only reviews not seen before.

## `webhookUrl` (type: `string`):

Optional endpoint that receives a concise JSON alert when new reviews are found.

## `webhookFormat` (type: `string`):

Payload shape to send to the webhook endpoint.

## `keywords` (type: `array`):

Optional terms to count and flag in review titles and text.

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

Fetch and summarize reviews without writing dataset items, updating state, or sending webhooks.

## Actor input object example

```json
{
  "platform": "apple",
  "country": "us",
  "language": "en",
  "reviewLimit": 50,
  "monitorMode": true,
  "webhookFormat": "generic",
  "dryRun": false
}
```

# Actor output Schema

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

No description

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

No description

# 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("matteogenovese/app-review-monitor").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("matteogenovese/app-review-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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 matteogenovese/app-review-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=matteogenovese/app-review-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "App Store & Google Play Review Monitor",
        "description": "Monitor App Store and Google Play reviews for any app. Get normalized review data, filter by rating or keywords, deduplicate new reviews, and send Slack, Discord, or JSON webhook alerts",
        "version": "0.1",
        "x-build-id": "k0HctRvgUL8u6IFtL"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/matteogenovese~app-review-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-matteogenovese-app-review-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/matteogenovese~app-review-monitor/runs": {
            "post": {
                "operationId": "runs-sync-matteogenovese-app-review-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/matteogenovese~app-review-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-matteogenovese-app-review-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "appId"
                ],
                "properties": {
                    "platform": {
                        "title": "Platform",
                        "enum": [
                            "apple",
                            "googlePlay"
                        ],
                        "type": "string",
                        "description": "App store platform to monitor.",
                        "default": "apple"
                    },
                    "appId": {
                        "title": "App ID",
                        "type": "string",
                        "description": "Apple App Store numeric ID or Google Play package name."
                    },
                    "country": {
                        "title": "Country",
                        "type": "string",
                        "description": "Two-letter store country code.",
                        "default": "us"
                    },
                    "language": {
                        "title": "Language",
                        "type": "string",
                        "description": "Language code used for app metadata and Google Play requests.",
                        "default": "en"
                    },
                    "reviewLimit": {
                        "title": "Review Limit",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum number of recent reviews to process.",
                        "default": 50
                    },
                    "minRating": {
                        "title": "Minimum Rating",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Only include reviews with this rating or higher. Leave empty to include all ratings."
                    },
                    "monitorMode": {
                        "title": "Monitor Mode",
                        "type": "boolean",
                        "description": "When enabled, compare reviews against stored state and emit only reviews not seen before.",
                        "default": true
                    },
                    "webhookUrl": {
                        "title": "Webhook URL",
                        "type": "string",
                        "description": "Optional endpoint that receives a concise JSON alert when new reviews are found."
                    },
                    "webhookFormat": {
                        "title": "Webhook Format",
                        "enum": [
                            "generic",
                            "slack",
                            "discord"
                        ],
                        "type": "string",
                        "description": "Payload shape to send to the webhook endpoint.",
                        "default": "generic"
                    },
                    "keywords": {
                        "title": "Keywords",
                        "type": "array",
                        "description": "Optional terms to count and flag in review titles and text.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "dryRun": {
                        "title": "Dry Run",
                        "type": "boolean",
                        "description": "Fetch and summarize reviews without writing dataset items, updating state, or sending webhooks.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
