# Google Workspace Marketplace Review Tracker (`dataspryva/google-workspace-marketplace-review-tracker`) Actor

Track and monitor reviews for any Google Workspace Marketplace app. Filter by date, rating, and sort order - ideal for daily sentiment monitoring and competitor analysis.

- **URL**: https://apify.com/dataspryva/google-workspace-marketplace-review-tracker.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** Automation, Developer tools, Integrations
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Workspace Marketplace Review Tracker

Follow the public review stream for Google Workspace Marketplace add-ons. Point the actor at one
or more app IDs or app URLs, choose the review language and filters, and get a clean dataset of
reviewer names, stars, review text, dates, helpful votes and developer replies. Schedule it with a
state key to receive only reviews that appeared or changed since the previous run.

No Google account, API key, cookie or proxy is needed.

### What you can do

| Task | How |
|---|---|
| Watch your app and competitors | Add each numeric App ID or full Marketplace app URL to `appIds` |
| Discover popular apps by keyword | Set `mode` to search and add keywords to `searchQueries` |
| Read reviews in another language | Pick a language, or keep all supported languages |
| Find complaints | Set a maximum star rating and a review-text keyword |
| Collect recent feedback only | Set a relative `sinceDate` such as `30 days` |
| Alert on new or changed reviews | Use `outputMode` `new` or `changed` with a `stateKey` |
| Re-baseline a monitor | Turn on `resetState` for one run |

### Inputs

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | select | `appReviews` | `appReviews` watches the app list; `search` ranks the public Marketplace index by keyword. |
| `appIds` | stringList | `["1008170693301"]` | Numeric IDs or full app URLs. One app per item. |
| `searchQueries` | stringList | `[]` | Keywords for search mode, e.g. `mail merge`. |
| `maxApps` | integer | `10` | Top matches to track per search keyword. |
| `minAppRating` | number | `0` | Skip apps below this average rating. |
| `minAppReviews` | integer | `0` | Skip apps with fewer total reviews. |
| `sortBy` | select | `Newest` | `Newest` or `MostHelpful` from the server; legacy `MostRelevant`, `HighestRated` and `LowestRated` are also accepted (rating sorts are computed over the collected reviews). |
| `reviewLanguage` | select | `all` | `all` or one of 28 supported language codes. |
| `minRating` | integer | – | Lowest star rating to include (1–5). |
| `maxRating` | integer | – | Highest star rating to include (1–5). |
| `sinceDate` | string | – | ISO date or relative period (`30 days`, `2 weeks`, `6 months`). |
| `untilDate` | string | – | Latest review date, inclusive (YYYY-MM-DD). |
| `reviewKeyword` | string | – | Keep reviews containing this phrase, case-insensitive. |
| `maxReviewsPerApp` | integer | `50` | Per-app cap after filters (1–2000). |
| `maxItems` | integer | `50` | Total rows for the run (1–5000). |
| `outputMode` | select | `all` | `all`, `new` (only unseen reviews) or `changed` (new plus helpful/rating/reply changes). |
| `trackChanges` | boolean | `false` | Add `isNew`/`changeTypes` and save a snapshot while returning all rows. |
| `stateKey` | string | – | Snapshot name; use one per schedule or watchlist. Derived when blank. |
| `resetState` | boolean | `false` | Clear the snapshot before the run. |

#### How to find an App ID

Open the app in the Marketplace. The numeric part after the final slash is the App ID:

```
https://workspace.google.com/marketplace/app/mailmeteor_mail_merge_for_google_sheets/1008170693301
                                                                                       ^^^^^^^^^^^^^
```

Both that full URL and the bare `1008170693301` are accepted. If you only have the ID, the actor
resolves the listing automatically.

### Output

Every row has `recordType` `workspace_review` and these fields when the source provides them:

| Field | Meaning |
|---|---|
| `reviewId` | Marketplace review identifier. |
| `appId`, `appName`, `appUrl` | The reviewed app and its listing URL. |
| `reviewerName`, `reviewerAvatarUrl` | Public reviewer name and profile image. |
| `rating` | Star rating, 1–5. |
| `reviewText` | Written review text; omitted for rating-only reviews. |
| `reviewDate`, `reviewTimestamp` | UTC date and full ISO timestamp. |
| `helpfulCount` | Helpful votes; omitted when zero, matching earlier versions of this actor. |
| `developerReply`, `developerReplyDate`, `developerReplyAuthor`, `developerReplies` | Latest developer reply plus every reply thread entry (`replyId`, `author`, `text`, `date`, `timestamp`). |
| `reviewLanguage` | Language slice the review came from (for example `de`). |
| `appDeveloper`, `appRating`, `appReviewCount`, `appInstallCount`, `appInstallsLabel` | App context from the listing. |
| `appPricingModel`, `appIconUrl`, `appWorksWith`, `appLastUpdated` | Pricing, icon, Google products and listing-update date. |
| `searchQuery`, `appRankInSearch` | Present in search mode. |
| `isNew`, `changeTypes` | Present when monitor tracking is on. |
| `scrapedAt` | UTC timestamp of this run. |

Empty values are omitted at every level; a row never contains `null`, `""`, `[]` or `{}`.

### Monitoring new reviews

1. Set `outputMode` to `new` or `changed`.
2. Give the watchlist a memorable `stateKey`, for example `my-app-reviews`.
3. Schedule the actor daily. The first run is the baseline and returns the matching reviews.
4. Later runs load the saved review fingerprints and emit only unseen reviews (`new`), or unseen
   reviews plus reviews whose helpful count, rating or reply count moved (`changed`).

The snapshot lives in a named key-value store, so separate scheduled runs share it. It holds up to
50,000 reviews; if a very large history is trimmed, the oldest entries are dropped first.
`resetState` clears the snapshot without deleting the dataset.

### Search mode

Search ranks the Marketplace's public top-100 app index, then collects reviews for the best
keyword matches. It is a discovery shortcut, not a full catalogue search: niche add-ons that are
not in that index must be added by ID or URL in appReviews mode. The run status says when no app
matched.

### Languages and pagination

Reviews are served in 10-row pages per language. The actor requests the pages itself, follows the
language totals, deduplicates by review ID, and stops on the per-app cap. Sparse filters scan at
most `max(10, maxReviewsPerApp)` pages per language, so raise `maxReviewsPerApp` to look deeper
into the history. With `reviewLanguage: all`, it visits the supported language slices in turn, so
a single language cannot use up the whole cap. The supported list covers English, German, Spanish,
French, Portuguese (Brazil), Italian, Russian, Japanese, Korean, Chinese (Simplified and
Traditional), Indonesian, Vietnamese, Dutch, Polish, Turkish, Arabic, Hindi, Thai, Hebrew,
Ukrainian, Swedish, Danish, Finnish, Norwegian, Czech, Hungarian and Filipino.

### FAQ

**Does this need a Google login or API key?**
No. It reads the same public review data the Marketplace shows to signed-out visitors.

**Why does the app page show more ratings than I receive?**
The rating count includes every star rating, including rating-only submissions and every language.
Written reviews are also split by language. Raise `maxReviewsPerApp` and keep `reviewLanguage` on
`all` for the widest coverage.

**Can I sort by highest or lowest rating?**
The Marketplace itself only offers Newest and Most Helpful. Old saved tasks that still send
`HighestRated` or `LowestRated` keep working: the actor fetches recent reviews and sorts the
collected set by stars. The status message explains the fallback.

**Why are some reviews missing text?**
Some visitors leave only a star rating. Those rows keep the rating and omit `reviewText`.

**Are developer replies included?**
Yes. Replies appear in the public review list and are attached to their review, including the
reply author and date. A reply to a review outside the fetched window is not attached; raise
`maxReviewsPerApp` or use a recent date filter to widen the window.

**What if an app has no reviews in the chosen language?**
The run moves to the next language in `all` mode and finishes cleanly with zero rows for that
language slice. A completely empty result is reported in the status message, not as a failure.

# Actor input Schema

## `mode` (type: `string`):

Choose 'Reviews for specific apps' to watch an app list, or 'Search apps by keyword' to discover popular Marketplace apps.

## `appIds` (type: `array`):

Numeric App IDs or full Google Workspace Marketplace app URLs. Add one app per item. Example: 1008170693301 or https://workspace.google.com/marketplace/app/mailmeteor_mail_merge_for_google_sheets/1008170693301. Used by the 'Reviews for specific apps' mode.

## `searchQueries` (type: `array`):

Keywords for the 'Search apps by keyword' mode, for example 'mail merge' or 'crm'. Each keyword ranks the Marketplace's public app index; niche apps should be added by ID or URL instead.

## `maxApps` (type: `integer`):

How many top matching apps to track for each search keyword.

## `minAppRating` (type: `number`):

Skip apps rated below this value (0–5). Use 0 for no app-rating filter.

## `minAppReviews` (type: `integer`):

Skip apps with fewer total reviews than this. Use 0 for no app-review-count filter.

## `sortBy` (type: `string`):

Order in which to retrieve reviews. The Marketplace supports newest and most helpful; legacy rating sorts are computed over the collected reviews.

## `reviewLanguage` (type: `string`):

Choose a language, or 'All languages' to check every supported language slice until Max reviews per app is reached.

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

Only include reviews with this star rating or higher (1–5). Leave blank for all ratings.

## `maxRating` (type: `integer`):

Only include reviews with this star rating or lower (1–5). Leave blank for all ratings.

## `sinceDate` (type: `string`):

Only include reviews posted on or after this date. Use YYYY-MM-DD, or a period such as '30 days', '2 weeks' or '6 months'. Leave blank for all dates.

## `untilDate` (type: `string`):

Only include reviews posted on or before this date (YYYY-MM-DD). Leave blank for no end date.

## `reviewKeyword` (type: `string`):

Only include reviews whose text contains this phrase (case-insensitive). Leave blank for all review text.

## `maxReviewsPerApp` (type: `integer`):

Stop after this many matching reviews for each app (1–2000). Raise it to collect full history; the Marketplace serves 10 per page.

## `maxItems` (type: `integer`):

Maximum number of review rows to return across all apps (1–5000).

## `outputMode` (type: `string`):

Use 'Only new reviews' or 'New + changed reviews' with a state key to compare this run with the previous run.

## `trackChanges` (type: `boolean`):

In 'All matching reviews' mode, add isNew/changeTypes and save a snapshot for the next run.

## `stateKey` (type: `string`):

Name of the saved snapshot. Use a different name for each schedule or watchlist. Leave blank to derive one from the app list and review language.

## `resetState` (type: `boolean`):

Clear the saved snapshot before this run so every review is treated as new.

## Actor input object example

```json
{
  "mode": "appReviews",
  "appIds": [
    "1008170693301"
  ],
  "searchQueries": [],
  "maxApps": 10,
  "minAppRating": 0,
  "minAppReviews": 0,
  "sortBy": "Newest",
  "reviewLanguage": "all",
  "maxReviewsPerApp": 10,
  "maxItems": 3,
  "outputMode": "all",
  "trackChanges": false,
  "resetState": false
}
```

# Actor output Schema

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

Dataset containing one row per review, plus developer reply fields, app context, review language and monitor flags when enabled.

# 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 = {
    "mode": "appReviews",
    "appIds": [
        "1008170693301"
    ],
    "searchQueries": [],
    "maxApps": 10,
    "minAppRating": 0,
    "minAppReviews": 0,
    "sortBy": "Newest",
    "reviewLanguage": "all",
    "maxReviewsPerApp": 10,
    "maxItems": 3,
    "outputMode": "all",
    "trackChanges": false,
    "resetState": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/google-workspace-marketplace-review-tracker").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 = {
    "mode": "appReviews",
    "appIds": ["1008170693301"],
    "searchQueries": [],
    "maxApps": 10,
    "minAppRating": 0,
    "minAppReviews": 0,
    "sortBy": "Newest",
    "reviewLanguage": "all",
    "maxReviewsPerApp": 10,
    "maxItems": 3,
    "outputMode": "all",
    "trackChanges": False,
    "resetState": False,
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/google-workspace-marketplace-review-tracker").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 '{
  "mode": "appReviews",
  "appIds": [
    "1008170693301"
  ],
  "searchQueries": [],
  "maxApps": 10,
  "minAppRating": 0,
  "minAppReviews": 0,
  "sortBy": "Newest",
  "reviewLanguage": "all",
  "maxReviewsPerApp": 10,
  "maxItems": 3,
  "outputMode": "all",
  "trackChanges": false,
  "resetState": false
}' |
apify call dataspryva/google-workspace-marketplace-review-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataspryva/google-workspace-marketplace-review-tracker"
        }
    }
}
```

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/MCQnyePxbC4pIjM4J/builds/Vfd1p69f7LBV99TxZ/openapi.json
