{
  "data": {
    "id": "Vfd1p69f7LBV99TxZ",
    "actId": "MCQnyePxbC4pIjM4J",
    "userId": "zq8lKbpLzTjGDayPC",
    "startedAt": "2026-11-08T13:06:43.464Z",
    "finishedAt": "2026-11-08T13:06:46.819Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 3279,
      "runTimeSecs": 3.279,
      "computeUnits": 0.0036433333333333335,
      "imageSizeBytes": 318998528
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "createdByOrganizationMemberUserId": "GK9YjZRyQZVzOdoH5",
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"Google Workspace Marketplace Review Tracker Input\",\n  \"description\": \"Track public reviews, developer replies, languages and rating changes for Google Workspace Marketplace apps. Use app IDs/URLs for a watchlist, or search the public Marketplace index by keyword.\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"mode\": {\n      \"title\": \"What to track\",\n      \"type\": \"string\",\n      \"description\": \"Choose 'Reviews for specific apps' to watch an app list, or 'Search apps by keyword' to discover popular Marketplace apps.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"appReviews\",\n        \"search\"\n      ],\n      \"enumTitles\": [\n        \"Reviews for specific apps\",\n        \"Search apps by keyword\"\n      ],\n      \"default\": \"appReviews\",\n      \"prefill\": \"appReviews\",\n      \"sectionCaption\": \"What to track\"\n    },\n    \"appIds\": {\n      \"title\": \"App IDs or URLs\",\n      \"type\": \"array\",\n      \"description\": \"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.\",\n      \"editor\": \"stringList\",\n      \"default\": [\n        \"1008170693301\"\n      ],\n      \"prefill\": [\n        \"1008170693301\"\n      ]\n    },\n    \"searchQueries\": {\n      \"title\": \"Search keywords\",\n      \"type\": \"array\",\n      \"description\": \"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.\",\n      \"editor\": \"stringList\",\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"maxApps\": {\n      \"title\": \"Max apps per keyword\",\n      \"type\": \"integer\",\n      \"description\": \"How many top matching apps to track for each search keyword.\",\n      \"minimum\": 1,\n      \"maximum\": 100,\n      \"default\": 10,\n      \"prefill\": 10\n    },\n    \"minAppRating\": {\n      \"title\": \"Minimum app rating\",\n      \"type\": \"number\",\n      \"description\": \"Skip apps rated below this value (0–5). Use 0 for no app-rating filter.\",\n      \"minimum\": 0,\n      \"maximum\": 5,\n      \"default\": 0,\n      \"prefill\": 0\n    },\n    \"minAppReviews\": {\n      \"title\": \"Minimum app review count\",\n      \"type\": \"integer\",\n      \"description\": \"Skip apps with fewer total reviews than this. Use 0 for no app-review-count filter.\",\n      \"minimum\": 0,\n      \"maximum\": 1000000,\n      \"default\": 0,\n      \"prefill\": 0\n    },\n    \"sortBy\": {\n      \"title\": \"Sort reviews by\",\n      \"type\": \"string\",\n      \"description\": \"Order in which to retrieve reviews. The Marketplace supports newest and most helpful; legacy rating sorts are computed over the collected reviews.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"Newest\",\n        \"MostHelpful\",\n        \"MostRelevant\",\n        \"HighestRated\",\n        \"LowestRated\"\n      ],\n      \"enumTitles\": [\n        \"Newest first\",\n        \"Most helpful first\",\n        \"Most relevant (legacy alias for most helpful)\",\n        \"Highest rated first (computed over collected reviews)\",\n        \"Lowest rated first (computed over collected reviews)\"\n      ],\n      \"default\": \"Newest\",\n      \"prefill\": \"Newest\",\n      \"sectionCaption\": \"Review filters\"\n    },\n    \"reviewLanguage\": {\n      \"title\": \"Review language\",\n      \"type\": \"string\",\n      \"description\": \"Choose a language, or 'All languages' to check every supported language slice until Max reviews per app is reached.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"all\",\n        \"en\",\n        \"de\",\n        \"es\",\n        \"fr\",\n        \"pt-BR\",\n        \"it\",\n        \"ru\",\n        \"ja\",\n        \"ko\",\n        \"zh-CN\",\n        \"zh-TW\",\n        \"id\",\n        \"vi\",\n        \"nl\",\n        \"pl\",\n        \"tr\",\n        \"ar\",\n        \"hi\",\n        \"th\",\n        \"he\",\n        \"uk\",\n        \"sv\",\n        \"da\",\n        \"fi\",\n        \"no\",\n        \"cs\",\n        \"hu\",\n        \"fil\"\n      ],\n      \"enumTitles\": [\n        \"All languages\",\n        \"English\",\n        \"German\",\n        \"Spanish\",\n        \"French\",\n        \"Portuguese (Brazil)\",\n        \"Italian\",\n        \"Russian\",\n        \"Japanese\",\n        \"Korean\",\n        \"Chinese (Simplified)\",\n        \"Chinese (Traditional)\",\n        \"Indonesian\",\n        \"Vietnamese\",\n        \"Dutch\",\n        \"Polish\",\n        \"Turkish\",\n        \"Arabic\",\n        \"Hindi\",\n        \"Thai\",\n        \"Hebrew\",\n        \"Ukrainian\",\n        \"Swedish\",\n        \"Danish\",\n        \"Finnish\",\n        \"Norwegian\",\n        \"Czech\",\n        \"Hungarian\",\n        \"Filipino\"\n      ],\n      \"default\": \"all\",\n      \"prefill\": \"all\"\n    },\n    \"minRating\": {\n      \"title\": \"Minimum star rating\",\n      \"type\": \"integer\",\n      \"description\": \"Only include reviews with this star rating or higher (1–5). Leave blank for all ratings.\",\n      \"minimum\": 1,\n      \"maximum\": 5\n    },\n    \"maxRating\": {\n      \"title\": \"Maximum star rating\",\n      \"type\": \"integer\",\n      \"description\": \"Only include reviews with this star rating or lower (1–5). Leave blank for all ratings.\",\n      \"minimum\": 1,\n      \"maximum\": 5\n    },\n    \"sinceDate\": {\n      \"title\": \"Reviews on or after\",\n      \"type\": \"string\",\n      \"description\": \"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.\",\n      \"editor\": \"textfield\"\n    },\n    \"untilDate\": {\n      \"title\": \"Reviews on or before\",\n      \"type\": \"string\",\n      \"description\": \"Only include reviews posted on or before this date (YYYY-MM-DD). Leave blank for no end date.\",\n      \"editor\": \"textfield\"\n    },\n    \"reviewKeyword\": {\n      \"title\": \"Review text contains\",\n      \"type\": \"string\",\n      \"description\": \"Only include reviews whose text contains this phrase (case-insensitive). Leave blank for all review text.\",\n      \"editor\": \"textfield\"\n    },\n    \"maxReviewsPerApp\": {\n      \"title\": \"Max reviews per app\",\n      \"type\": \"integer\",\n      \"description\": \"Stop after this many matching reviews for each app (1–2000). Raise it to collect full history; the Marketplace serves 10 per page.\",\n      \"minimum\": 1,\n      \"maximum\": 2000,\n      \"default\": 50,\n      \"prefill\": 10\n    },\n    \"maxItems\": {\n      \"title\": \"Max reviews per run\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum number of review rows to return across all apps (1–5000).\",\n      \"minimum\": 1,\n      \"maximum\": 5000,\n      \"default\": 50,\n      \"prefill\": 3\n    },\n    \"outputMode\": {\n      \"title\": \"Monitor output\",\n      \"type\": \"string\",\n      \"description\": \"Use 'Only new reviews' or 'New + changed reviews' with a state key to compare this run with the previous run.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"all\",\n        \"new\",\n        \"changed\"\n      ],\n      \"enumTitles\": [\n        \"All matching reviews\",\n        \"Only new reviews\",\n        \"New + changed reviews\"\n      ],\n      \"default\": \"all\",\n      \"prefill\": \"all\",\n      \"sectionCaption\": \"Monitor new reviews\"\n    },\n    \"trackChanges\": {\n      \"title\": \"Track changes in All mode\",\n      \"type\": \"boolean\",\n      \"description\": \"In 'All matching reviews' mode, add isNew/changeTypes and save a snapshot for the next run.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"stateKey\": {\n      \"title\": \"Monitor name (state key)\",\n      \"type\": \"string\",\n      \"description\": \"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.\",\n      \"editor\": \"textfield\"\n    },\n    \"resetState\": {\n      \"title\": \"Reset monitor before run\",\n      \"type\": \"boolean\",\n      \"description\": \"Clear the saved snapshot before this run so every review is treated as new.\",\n      \"default\": false,\n      \"prefill\": false\n    }\n  },\n  \"required\": [\n    \"mode\"\n  ]\n}",
    "readme": "# Google Workspace Marketplace Review Tracker\n\nFollow the public review stream for Google Workspace Marketplace add-ons. Point the actor at one\nor more app IDs or app URLs, choose the review language and filters, and get a clean dataset of\nreviewer names, stars, review text, dates, helpful votes and developer replies. Schedule it with a\nstate key to receive only reviews that appeared or changed since the previous run.\n\nNo Google account, API key, cookie or proxy is needed.\n\n## What you can do\n\n| Task | How |\n|---|---|\n| Watch your app and competitors | Add each numeric App ID or full Marketplace app URL to `appIds` |\n| Discover popular apps by keyword | Set `mode` to search and add keywords to `searchQueries` |\n| Read reviews in another language | Pick a language, or keep all supported languages |\n| Find complaints | Set a maximum star rating and a review-text keyword |\n| Collect recent feedback only | Set a relative `sinceDate` such as `30 days` |\n| Alert on new or changed reviews | Use `outputMode` `new` or `changed` with a `stateKey` |\n| Re-baseline a monitor | Turn on `resetState` for one run |\n\n## Inputs\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `mode` | select | `appReviews` | `appReviews` watches the app list; `search` ranks the public Marketplace index by keyword. |\n| `appIds` | stringList | `[\"1008170693301\"]` | Numeric IDs or full app URLs. One app per item. |\n| `searchQueries` | stringList | `[]` | Keywords for search mode, e.g. `mail merge`. |\n| `maxApps` | integer | `10` | Top matches to track per search keyword. |\n| `minAppRating` | number | `0` | Skip apps below this average rating. |\n| `minAppReviews` | integer | `0` | Skip apps with fewer total reviews. |\n| `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). |\n| `reviewLanguage` | select | `all` | `all` or one of 28 supported language codes. |\n| `minRating` | integer | – | Lowest star rating to include (1–5). |\n| `maxRating` | integer | – | Highest star rating to include (1–5). |\n| `sinceDate` | string | – | ISO date or relative period (`30 days`, `2 weeks`, `6 months`). |\n| `untilDate` | string | – | Latest review date, inclusive (YYYY-MM-DD). |\n| `reviewKeyword` | string | – | Keep reviews containing this phrase, case-insensitive. |\n| `maxReviewsPerApp` | integer | `50` | Per-app cap after filters (1–2000). |\n| `maxItems` | integer | `50` | Total rows for the run (1–5000). |\n| `outputMode` | select | `all` | `all`, `new` (only unseen reviews) or `changed` (new plus helpful/rating/reply changes). |\n| `trackChanges` | boolean | `false` | Add `isNew`/`changeTypes` and save a snapshot while returning all rows. |\n| `stateKey` | string | – | Snapshot name; use one per schedule or watchlist. Derived when blank. |\n| `resetState` | boolean | `false` | Clear the snapshot before the run. |\n\n### How to find an App ID\n\nOpen the app in the Marketplace. The numeric part after the final slash is the App ID:\n\n```\nhttps://workspace.google.com/marketplace/app/mailmeteor_mail_merge_for_google_sheets/1008170693301\n                                                                                       ^^^^^^^^^^^^^\n```\n\nBoth that full URL and the bare `1008170693301` are accepted. If you only have the ID, the actor\nresolves the listing automatically.\n\n## Output\n\nEvery row has `recordType` `workspace_review` and these fields when the source provides them:\n\n| Field | Meaning |\n|---|---|\n| `reviewId` | Marketplace review identifier. |\n| `appId`, `appName`, `appUrl` | The reviewed app and its listing URL. |\n| `reviewerName`, `reviewerAvatarUrl` | Public reviewer name and profile image. |\n| `rating` | Star rating, 1–5. |\n| `reviewText` | Written review text; omitted for rating-only reviews. |\n| `reviewDate`, `reviewTimestamp` | UTC date and full ISO timestamp. |\n| `helpfulCount` | Helpful votes; omitted when zero, matching earlier versions of this actor. |\n| `developerReply`, `developerReplyDate`, `developerReplyAuthor`, `developerReplies` | Latest developer reply plus every reply thread entry (`replyId`, `author`, `text`, `date`, `timestamp`). |\n| `reviewLanguage` | Language slice the review came from (for example `de`). |\n| `appDeveloper`, `appRating`, `appReviewCount`, `appInstallCount`, `appInstallsLabel` | App context from the listing. |\n| `appPricingModel`, `appIconUrl`, `appWorksWith`, `appLastUpdated` | Pricing, icon, Google products and listing-update date. |\n| `searchQuery`, `appRankInSearch` | Present in search mode. |\n| `isNew`, `changeTypes` | Present when monitor tracking is on. |\n| `scrapedAt` | UTC timestamp of this run. |\n\nEmpty values are omitted at every level; a row never contains `null`, `\"\"`, `[]` or `{}`.\n\n## Monitoring new reviews\n\n1. Set `outputMode` to `new` or `changed`.\n2. Give the watchlist a memorable `stateKey`, for example `my-app-reviews`.\n3. Schedule the actor daily. The first run is the baseline and returns the matching reviews.\n4. Later runs load the saved review fingerprints and emit only unseen reviews (`new`), or unseen\n   reviews plus reviews whose helpful count, rating or reply count moved (`changed`).\n\nThe snapshot lives in a named key-value store, so separate scheduled runs share it. It holds up to\n50,000 reviews; if a very large history is trimmed, the oldest entries are dropped first.\n`resetState` clears the snapshot without deleting the dataset.\n\n## Search mode\n\nSearch ranks the Marketplace's public top-100 app index, then collects reviews for the best\nkeyword matches. It is a discovery shortcut, not a full catalogue search: niche add-ons that are\nnot in that index must be added by ID or URL in appReviews mode. The run status says when no app\nmatched.\n\n## Languages and pagination\n\nReviews are served in 10-row pages per language. The actor requests the pages itself, follows the\nlanguage totals, deduplicates by review ID, and stops on the per-app cap. Sparse filters scan at\nmost `max(10, maxReviewsPerApp)` pages per language, so raise `maxReviewsPerApp` to look deeper\ninto the history. With `reviewLanguage: all`, it visits the supported language slices in turn, so\na single language cannot use up the whole cap. The supported list covers English, German, Spanish,\nFrench, Portuguese (Brazil), Italian, Russian, Japanese, Korean, Chinese (Simplified and\nTraditional), Indonesian, Vietnamese, Dutch, Polish, Turkish, Arabic, Hindi, Thai, Hebrew,\nUkrainian, Swedish, Danish, Finnish, Norwegian, Czech, Hungarian and Filipino.\n\n## FAQ\n\n**Does this need a Google login or API key?**\nNo. It reads the same public review data the Marketplace shows to signed-out visitors.\n\n**Why does the app page show more ratings than I receive?**\nThe rating count includes every star rating, including rating-only submissions and every language.\nWritten reviews are also split by language. Raise `maxReviewsPerApp` and keep `reviewLanguage` on\n`all` for the widest coverage.\n\n**Can I sort by highest or lowest rating?**\nThe Marketplace itself only offers Newest and Most Helpful. Old saved tasks that still send\n`HighestRated` or `LowestRated` keep working: the actor fetches recent reviews and sorts the\ncollected set by stars. The status message explains the fallback.\n\n**Why are some reviews missing text?**\nSome visitors leave only a star rating. Those rows keep the rating and omit `reviewText`.\n\n**Are developer replies included?**\nYes. Replies appear in the public review list and are attached to their review, including the\nreply author and date. A reply to a review outside the fetched window is not attached; raise\n`maxReviewsPerApp` or use a recent date filter to widen the window.\n\n**What if an app has no reviews in the chosen language?**\nThe run moves to the next language in `all` mode and finishes cleanly with zero rows for that\nlanguage slice. A completely empty result is reported in the status message, not as a failure.\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "google-workspace-marketplace-review-tracker",
      "title": "Google Workspace Marketplace Review Tracker",
      "description": "Track public Google Workspace Marketplace reviews across multiple apps and languages, with developer replies, reviewer avatars, rating/date/keyword filters and new-or-changed monitor alerts.",
      "version": "1.1",
      "buildTag": "latest",
      "dockerfile": "./Dockerfile",
      "readme": "# Google Workspace Marketplace Review Tracker\n\nFollow the public review stream for Google Workspace Marketplace add-ons. Point the actor at one\nor more app IDs or app URLs, choose the review language and filters, and get a clean dataset of\nreviewer names, stars, review text, dates, helpful votes and developer replies. Schedule it with a\nstate key to receive only reviews that appeared or changed since the previous run.\n\nNo Google account, API key, cookie or proxy is needed.\n\n## What you can do\n\n| Task | How |\n|---|---|\n| Watch your app and competitors | Add each numeric App ID or full Marketplace app URL to `appIds` |\n| Discover popular apps by keyword | Set `mode` to search and add keywords to `searchQueries` |\n| Read reviews in another language | Pick a language, or keep all supported languages |\n| Find complaints | Set a maximum star rating and a review-text keyword |\n| Collect recent feedback only | Set a relative `sinceDate` such as `30 days` |\n| Alert on new or changed reviews | Use `outputMode` `new` or `changed` with a `stateKey` |\n| Re-baseline a monitor | Turn on `resetState` for one run |\n\n## Inputs\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `mode` | select | `appReviews` | `appReviews` watches the app list; `search` ranks the public Marketplace index by keyword. |\n| `appIds` | stringList | `[\"1008170693301\"]` | Numeric IDs or full app URLs. One app per item. |\n| `searchQueries` | stringList | `[]` | Keywords for search mode, e.g. `mail merge`. |\n| `maxApps` | integer | `10` | Top matches to track per search keyword. |\n| `minAppRating` | number | `0` | Skip apps below this average rating. |\n| `minAppReviews` | integer | `0` | Skip apps with fewer total reviews. |\n| `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). |\n| `reviewLanguage` | select | `all` | `all` or one of 28 supported language codes. |\n| `minRating` | integer | – | Lowest star rating to include (1–5). |\n| `maxRating` | integer | – | Highest star rating to include (1–5). |\n| `sinceDate` | string | – | ISO date or relative period (`30 days`, `2 weeks`, `6 months`). |\n| `untilDate` | string | – | Latest review date, inclusive (YYYY-MM-DD). |\n| `reviewKeyword` | string | – | Keep reviews containing this phrase, case-insensitive. |\n| `maxReviewsPerApp` | integer | `50` | Per-app cap after filters (1–2000). |\n| `maxItems` | integer | `50` | Total rows for the run (1–5000). |\n| `outputMode` | select | `all` | `all`, `new` (only unseen reviews) or `changed` (new plus helpful/rating/reply changes). |\n| `trackChanges` | boolean | `false` | Add `isNew`/`changeTypes` and save a snapshot while returning all rows. |\n| `stateKey` | string | – | Snapshot name; use one per schedule or watchlist. Derived when blank. |\n| `resetState` | boolean | `false` | Clear the snapshot before the run. |\n\n### How to find an App ID\n\nOpen the app in the Marketplace. The numeric part after the final slash is the App ID:\n\n```\nhttps://workspace.google.com/marketplace/app/mailmeteor_mail_merge_for_google_sheets/1008170693301\n                                                                                       ^^^^^^^^^^^^^\n```\n\nBoth that full URL and the bare `1008170693301` are accepted. If you only have the ID, the actor\nresolves the listing automatically.\n\n## Output\n\nEvery row has `recordType` `workspace_review` and these fields when the source provides them:\n\n| Field | Meaning |\n|---|---|\n| `reviewId` | Marketplace review identifier. |\n| `appId`, `appName`, `appUrl` | The reviewed app and its listing URL. |\n| `reviewerName`, `reviewerAvatarUrl` | Public reviewer name and profile image. |\n| `rating` | Star rating, 1–5. |\n| `reviewText` | Written review text; omitted for rating-only reviews. |\n| `reviewDate`, `reviewTimestamp` | UTC date and full ISO timestamp. |\n| `helpfulCount` | Helpful votes; omitted when zero, matching earlier versions of this actor. |\n| `developerReply`, `developerReplyDate`, `developerReplyAuthor`, `developerReplies` | Latest developer reply plus every reply thread entry (`replyId`, `author`, `text`, `date`, `timestamp`). |\n| `reviewLanguage` | Language slice the review came from (for example `de`). |\n| `appDeveloper`, `appRating`, `appReviewCount`, `appInstallCount`, `appInstallsLabel` | App context from the listing. |\n| `appPricingModel`, `appIconUrl`, `appWorksWith`, `appLastUpdated` | Pricing, icon, Google products and listing-update date. |\n| `searchQuery`, `appRankInSearch` | Present in search mode. |\n| `isNew`, `changeTypes` | Present when monitor tracking is on. |\n| `scrapedAt` | UTC timestamp of this run. |\n\nEmpty values are omitted at every level; a row never contains `null`, `\"\"`, `[]` or `{}`.\n\n## Monitoring new reviews\n\n1. Set `outputMode` to `new` or `changed`.\n2. Give the watchlist a memorable `stateKey`, for example `my-app-reviews`.\n3. Schedule the actor daily. The first run is the baseline and returns the matching reviews.\n4. Later runs load the saved review fingerprints and emit only unseen reviews (`new`), or unseen\n   reviews plus reviews whose helpful count, rating or reply count moved (`changed`).\n\nThe snapshot lives in a named key-value store, so separate scheduled runs share it. It holds up to\n50,000 reviews; if a very large history is trimmed, the oldest entries are dropped first.\n`resetState` clears the snapshot without deleting the dataset.\n\n## Search mode\n\nSearch ranks the Marketplace's public top-100 app index, then collects reviews for the best\nkeyword matches. It is a discovery shortcut, not a full catalogue search: niche add-ons that are\nnot in that index must be added by ID or URL in appReviews mode. The run status says when no app\nmatched.\n\n## Languages and pagination\n\nReviews are served in 10-row pages per language. The actor requests the pages itself, follows the\nlanguage totals, deduplicates by review ID, and stops on the per-app cap. Sparse filters scan at\nmost `max(10, maxReviewsPerApp)` pages per language, so raise `maxReviewsPerApp` to look deeper\ninto the history. With `reviewLanguage: all`, it visits the supported language slices in turn, so\na single language cannot use up the whole cap. The supported list covers English, German, Spanish,\nFrench, Portuguese (Brazil), Italian, Russian, Japanese, Korean, Chinese (Simplified and\nTraditional), Indonesian, Vietnamese, Dutch, Polish, Turkish, Arabic, Hindi, Thai, Hebrew,\nUkrainian, Swedish, Danish, Finnish, Norwegian, Czech, Hungarian and Filipino.\n\n## FAQ\n\n**Does this need a Google login or API key?**\nNo. It reads the same public review data the Marketplace shows to signed-out visitors.\n\n**Why does the app page show more ratings than I receive?**\nThe rating count includes every star rating, including rating-only submissions and every language.\nWritten reviews are also split by language. Raise `maxReviewsPerApp` and keep `reviewLanguage` on\n`all` for the widest coverage.\n\n**Can I sort by highest or lowest rating?**\nThe Marketplace itself only offers Newest and Most Helpful. Old saved tasks that still send\n`HighestRated` or `LowestRated` keep working: the actor fetches recent reviews and sorts the\ncollected set by stars. The status message explains the fallback.\n\n**Why are some reviews missing text?**\nSome visitors leave only a star rating. Those rows keep the rating and omit `reviewText`.\n\n**Are developer replies included?**\nYes. Replies appear in the public review list and are attached to their review, including the\nreply author and date. A reply to a review outside the fetched window is not attached; raise\n`maxReviewsPerApp` or use a recent date filter to widen the window.\n\n**What if an app has no reviews in the chosen language?**\nThe run moves to the next language in `all` mode and finishes cleanly with zero rows for that\nlanguage slice. A completely empty result is reported in the status message, not as a failure.\n",
      "input": {
        "title": "Google Workspace Marketplace Review Tracker Input",
        "description": "Track public reviews, developer replies, languages and rating changes for Google Workspace Marketplace apps. Use app IDs/URLs for a watchlist, or search the public Marketplace index by keyword.",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "mode": {
            "title": "What to track",
            "type": "string",
            "description": "Choose 'Reviews for specific apps' to watch an app list, or 'Search apps by keyword' to discover popular Marketplace apps.",
            "editor": "select",
            "enum": [
              "appReviews",
              "search"
            ],
            "enumTitles": [
              "Reviews for specific apps",
              "Search apps by keyword"
            ],
            "default": "appReviews",
            "prefill": "appReviews",
            "sectionCaption": "What to track"
          },
          "appIds": {
            "title": "App IDs or URLs",
            "type": "array",
            "description": "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.",
            "editor": "stringList",
            "default": [
              "1008170693301"
            ],
            "prefill": [
              "1008170693301"
            ]
          },
          "searchQueries": {
            "title": "Search keywords",
            "type": "array",
            "description": "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.",
            "editor": "stringList",
            "default": [],
            "prefill": []
          },
          "maxApps": {
            "title": "Max apps per keyword",
            "type": "integer",
            "description": "How many top matching apps to track for each search keyword.",
            "minimum": 1,
            "maximum": 100,
            "default": 10,
            "prefill": 10
          },
          "minAppRating": {
            "title": "Minimum app rating",
            "type": "number",
            "description": "Skip apps rated below this value (0–5). Use 0 for no app-rating filter.",
            "minimum": 0,
            "maximum": 5,
            "default": 0,
            "prefill": 0
          },
          "minAppReviews": {
            "title": "Minimum app review count",
            "type": "integer",
            "description": "Skip apps with fewer total reviews than this. Use 0 for no app-review-count filter.",
            "minimum": 0,
            "maximum": 1000000,
            "default": 0,
            "prefill": 0
          },
          "sortBy": {
            "title": "Sort reviews by",
            "type": "string",
            "description": "Order in which to retrieve reviews. The Marketplace supports newest and most helpful; legacy rating sorts are computed over the collected reviews.",
            "editor": "select",
            "enum": [
              "Newest",
              "MostHelpful",
              "MostRelevant",
              "HighestRated",
              "LowestRated"
            ],
            "enumTitles": [
              "Newest first",
              "Most helpful first",
              "Most relevant (legacy alias for most helpful)",
              "Highest rated first (computed over collected reviews)",
              "Lowest rated first (computed over collected reviews)"
            ],
            "default": "Newest",
            "prefill": "Newest",
            "sectionCaption": "Review filters"
          },
          "reviewLanguage": {
            "title": "Review language",
            "type": "string",
            "description": "Choose a language, or 'All languages' to check every supported language slice until Max reviews per app is reached.",
            "editor": "select",
            "enum": [
              "all",
              "en",
              "de",
              "es",
              "fr",
              "pt-BR",
              "it",
              "ru",
              "ja",
              "ko",
              "zh-CN",
              "zh-TW",
              "id",
              "vi",
              "nl",
              "pl",
              "tr",
              "ar",
              "hi",
              "th",
              "he",
              "uk",
              "sv",
              "da",
              "fi",
              "no",
              "cs",
              "hu",
              "fil"
            ],
            "enumTitles": [
              "All languages",
              "English",
              "German",
              "Spanish",
              "French",
              "Portuguese (Brazil)",
              "Italian",
              "Russian",
              "Japanese",
              "Korean",
              "Chinese (Simplified)",
              "Chinese (Traditional)",
              "Indonesian",
              "Vietnamese",
              "Dutch",
              "Polish",
              "Turkish",
              "Arabic",
              "Hindi",
              "Thai",
              "Hebrew",
              "Ukrainian",
              "Swedish",
              "Danish",
              "Finnish",
              "Norwegian",
              "Czech",
              "Hungarian",
              "Filipino"
            ],
            "default": "all",
            "prefill": "all"
          },
          "minRating": {
            "title": "Minimum star rating",
            "type": "integer",
            "description": "Only include reviews with this star rating or higher (1–5). Leave blank for all ratings.",
            "minimum": 1,
            "maximum": 5
          },
          "maxRating": {
            "title": "Maximum star rating",
            "type": "integer",
            "description": "Only include reviews with this star rating or lower (1–5). Leave blank for all ratings.",
            "minimum": 1,
            "maximum": 5
          },
          "sinceDate": {
            "title": "Reviews on or after",
            "type": "string",
            "description": "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.",
            "editor": "textfield"
          },
          "untilDate": {
            "title": "Reviews on or before",
            "type": "string",
            "description": "Only include reviews posted on or before this date (YYYY-MM-DD). Leave blank for no end date.",
            "editor": "textfield"
          },
          "reviewKeyword": {
            "title": "Review text contains",
            "type": "string",
            "description": "Only include reviews whose text contains this phrase (case-insensitive). Leave blank for all review text.",
            "editor": "textfield"
          },
          "maxReviewsPerApp": {
            "title": "Max reviews per app",
            "type": "integer",
            "description": "Stop after this many matching reviews for each app (1–2000). Raise it to collect full history; the Marketplace serves 10 per page.",
            "minimum": 1,
            "maximum": 2000,
            "default": 50,
            "prefill": 10
          },
          "maxItems": {
            "title": "Max reviews per run",
            "type": "integer",
            "description": "Maximum number of review rows to return across all apps (1–5000).",
            "minimum": 1,
            "maximum": 5000,
            "default": 50,
            "prefill": 3
          },
          "outputMode": {
            "title": "Monitor output",
            "type": "string",
            "description": "Use 'Only new reviews' or 'New + changed reviews' with a state key to compare this run with the previous run.",
            "editor": "select",
            "enum": [
              "all",
              "new",
              "changed"
            ],
            "enumTitles": [
              "All matching reviews",
              "Only new reviews",
              "New + changed reviews"
            ],
            "default": "all",
            "prefill": "all",
            "sectionCaption": "Monitor new reviews"
          },
          "trackChanges": {
            "title": "Track changes in All mode",
            "type": "boolean",
            "description": "In 'All matching reviews' mode, add isNew/changeTypes and save a snapshot for the next run.",
            "default": false,
            "prefill": false
          },
          "stateKey": {
            "title": "Monitor name (state key)",
            "type": "string",
            "description": "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.",
            "editor": "textfield"
          },
          "resetState": {
            "title": "Reset monitor before run",
            "type": "boolean",
            "description": "Clear the saved snapshot before this run so every review is treated as new.",
            "default": false,
            "prefill": false
          }
        },
        "required": [
          "mode"
        ]
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "Google Workspace Marketplace Review Tracker Output",
        "description": "Review rows for one or more Marketplace apps, with reviewer details, developer replies, app context and optional monitor flags. Empty fields are omitted from every record.",
        "properties": {
          "reviews": {
            "type": "string",
            "title": "Reviews",
            "description": "Dataset containing one row per review, plus developer reply fields, app context, review language and monitor flags when enabled.",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          }
        }
      },
      "defaultMemoryMbytes": 1024,
      "minMemoryMbytes": 1024,
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "views": {
            "reviews": {
              "title": "App reviews",
              "transformation": {
                "fields": [
                  "recordType",
                  "appName",
                  "reviewerName",
                  "rating",
                  "reviewDate",
                  "reviewText",
                  "helpfulCount",
                  "developerReply",
                  "isNew"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "recordType": {
                    "label": "Type",
                    "format": "text"
                  },
                  "appName": {
                    "label": "App",
                    "format": "text"
                  },
                  "reviewerName": {
                    "label": "Reviewer",
                    "format": "text"
                  },
                  "rating": {
                    "label": "Stars",
                    "format": "number"
                  },
                  "reviewDate": {
                    "label": "Date",
                    "format": "text"
                  },
                  "reviewText": {
                    "label": "Review",
                    "format": "text"
                  },
                  "helpfulCount": {
                    "label": "Helpful",
                    "format": "number"
                  },
                  "developerReply": {
                    "label": "Developer reply",
                    "format": "text"
                  },
                  "isNew": {
                    "label": "New",
                    "format": "boolean"
                  }
                }
              }
            }
          }
        }
      },
      "environmentVariables": {}
    },
    "buildNumber": "1.1.3",
    "imageDigest": "21afb3846645eb05a8cf173b9694cbb0b4f9c16f702e67dc066131c906b18e1c",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "1.1"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.0036433333333333335
    }
  }
}