# Cross-Platform Mobile App Feedback Intelligence (`obliging_persimmon_cki/cross-platform-mobile-feedback`) Actor

Compare Google Play and Apple App Store reviews to identify shared issues, Android-only and iOS-only bugs, feature requests, rating differences, and release-impact signals.

- **URL**: https://apify.com/obliging\_persimmon\_cki/cross-platform-mobile-feedback.md
- **Developed by:** [Dung Huynh](https://apify.com/obliging_persimmon_cki) (community)
- **Categories:** AI, Developer tools, Other
- **Stats:** 2 total users, 1 monthly users, 100.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 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

## Cross-Platform Mobile App Feedback Intelligence

Compare explicitly mapped Google Play and Apple App Store reviews to identify shared issues, Android-only and iOS-only findings, feature requests, rating differences, localization signals, and release-impact patterns.

### What it does

This Actor is for mobile product managers, QA and engineering teams, support teams, app publishers, ASO agencies, localization teams, and product researchers. It combines source collection with normalized analysis and cautious cross-platform comparison; it is not an automatic app matcher or a generic review scraper.

Supported public sources:

- Google Play reviews using a package ID or public URL.
- Apple App Store customer reviews using a numeric app ID or public URL.

The first release is tested with selected English and Vietnamese Google Play and Apple App Store datasets. Coverage depends on public store availability, country, language, pagination, and rate limits.

### Product mapping

Map each Android and iOS listing to one stable product identity. The Actor never assumes that similarly named apps are the same product.

```json
{
  "productId": "example-product",
  "name": "Example App",
  "googlePlayAppId": "com.example.app",
  "appleAppId": "123456789"
}
```

You can use `googlePlayUrl` and `appleAppStoreUrl` instead of IDs. Explicit IDs take precedence over URLs. Duplicate platform IDs assigned to different products are rejected. `comparePlatforms` and `releaseComparison` require both platform mappings; `rawReviews` and `feedbackAnalysis` allow one platform.

### Run modes

- `rawReviews` — collect normalized source reviews for downstream use.
- `feedbackAnalysis` — add per-review analysis and platform-level issue clusters.
- `comparePlatforms` — produce same-product shared, platform-specific, dominant, and insufficient-evidence comparisons plus a product report.
- `releaseComparison` — compare independently dated Android and iOS before/after windows.

The checked-in [sample input](sample-input.json) is a bounded live cloud smoke test using Spotify's public Google Play package ID and Apple App Store app ID. From this Actor directory, run it with:

```bash
apify call obliging_persimmon_cki/cross-platform-mobile-feedback --input-file sample-input.json --output-dataset
```

It makes one request per store, caps each platform at five reviews, enables the deterministic fallback when no provider key is configured, and keeps report generation enabled. [sample-benchmark.json](sample-benchmark.json) shows a multi-product configuration.

The Console's default input uses the same public mapping and bounded limits, so an Apify automation test can run without manually entering product IDs.

### Input controls

Use `countries`, `languages`, `ratings`, and `dateRange` to bound collection. `maxReviewsPerPlatform`, `maxPagesPerPlatform`, `requestTimeoutSecs`, and `maxRequestsPerRun` bound source work. The request cap is checked after expanding products, platforms, countries, and languages, before network collection begins.

Analysis cost is bounded by `analysis.maxReviewsToAnalyze`, `analysis.maxAttempts`, and `analysis.cacheMaxEntries`. `OPENAI_API_KEY` enables the optional native-fetch OpenAI-compatible provider; `OPENAI_MODEL` selects the model when supported. Without a key, the dependency-free deterministic fallback keeps the run operational and marks the resulting analysis accordingly.

### Output

The dataset contains normalized `review`, `reviewAnalysis`, `feedbackCluster`, `crossPlatformComparison`, `crossPlatformFeedbackReport`, `releaseComparisonReport`, `sourceDiagnostic`, and `runError` records. The output schema links the dataset, per-product reports, release reports, normalized input, source errors, and run statistics.

Key-value records include:

- `NORMALIZED_INPUT` — validated settings and explicit mappings.
- `CROSS_PLATFORM_REPORT_<productId>` and `CROSS_PLATFORM_REPORTS` — product reports.
- `CROSS_PLATFORM_RELEASE_REPORT_<productId>` and `CROSS_PLATFORM_RELEASE_REPORTS` — release reports.
- `SOURCE_ERRORS` — platform-scoped fetch failures retained for partial runs.
- `RUN_STATS` — collection, analysis, cluster, comparison, report, request, error, usage, and runtime counters.

### Reports and comparisons

Reports include platform review counts, average ratings, actionable-review counts, shared issues, Android-only issues, iOS-only issues, shared feature requests, rating/volume differences, and country/language/version insights. Platform-specific language is deliberately limited to “observed only in the collected sample.” Missing or insufficient source evidence is surfaced as warnings rather than treated as evidence of absence.

Release comparison uses separate Android and iOS release dates, non-overlapping before/after windows, staggered rollout timing, topic changes, new issues, possible regressions, and minimum-sample warnings. It is observational and does not prove that a release caused a change.

### Quality benchmark

Run `npm run benchmark:quality` for the deterministic 100-review fixture: 50 reviews per platform, 25 known shared review pairs, 10 feature-request pairs, 50 labeled platform-specific examples, mixed English/Vietnamese metadata, and staggered releases. The current fixture result is 100% analysis-schema validity, 100% cluster coherence, 100% shared precision and recall, 0% platform-specific false positives, correct dimension and release-window calculations, and no cross-product matches. The fixture provider reports an estimated $0.02 cost for one product comparison; live provider cost depends on model and review volume.

### Limitations and responsible use

- Reviews are user reports and opinions, not confirmed defects.
- Platform-specific means observed only in the collected sample, never “absent” from the other platform.
- Review availability differs by store, country, language, pagination, and public-feed behavior.
- Ratings are not necessarily comparable when source coverage differs.
- Requested store locale is not guaranteed reviewer-origin language.
- Release comparison shows correlation in bounded windows, not causation.
- AI may misclassify sarcasm, ambiguity, or mixed-language feedback.
- Validate important product, QA, support, and release decisions against source reviews and internal telemetry.

Use only public review data, respect source terms and rate limits, and do not include private or authenticated review sources.

### FAQ

**Does the Actor find matching apps automatically?** No. Supply explicit product mappings.

**Can one store fail without losing the other store’s data?** Yes. Successful reviews are retained, and scoped diagnostics, warnings, and `SOURCE_ERRORS` identify failures.

**Is an OpenAI key required?** No. It is only used for the optional provider path; the fallback is local and deterministic.

**Can I compare releases with different rollout dates?** Yes. Supply separate Android and iOS release metadata; the report includes rollout lag and separate windows.

### Roadmap

Future work may improve source pagination coverage, expand validated language fixtures, add richer confidence calibration, and support additional public feedback sources. Automatic app matching, private sources, ticket creation, competitor discovery, rankings, revenue estimation, and generated developer replies are outside this Actor’s scope.

No publication or pricing changes are performed automatically.

# Actor input Schema

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

Choose raw collection, per-platform analysis, cross-platform comparison, or release comparison.

## `products` (type: `array`):

Map each canonical product to one or both store app IDs or URLs. Apps are never matched automatically by name.

## `countries` (type: `array`):

Two-letter storefront/country filters.

## `languages` (type: `array`):

Two- or three-letter language filters.

## `ratings` (type: `array`):

Review star ratings to include.

## `dateRange` (type: `object`):

Optional bounded collection window.

## `maxReviewsPerPlatform` (type: `integer`):

Bound applied per mapped store platform.

## `requestTimeoutSecs` (type: `integer`):

Maximum seconds allowed for each public store request.

## `maxPagesPerPlatform` (type: `integer`):

Maximum Apple RSS pages fetched for each mapped platform request.

## `maxRequestsPerRun` (type: `integer`):

Hard cap on expanded product, platform, country, and language source requests.

## `includeDeveloperReplies` (type: `boolean`):

Preserve public developer replies where a source exposes them.

## `includeReviewText` (type: `boolean`):

Preserve original review text in raw output.

## `analysis` (type: `object`):

Shared analysis and clustering options.

## `comparison` (type: `object`):

Cross-platform matching thresholds and report dimensions.

## `aggregation` (type: `object`):

Cluster and report output limits.

## `daysBefore` (type: `integer`):

Release comparison window before each platform release.

## `daysAfter` (type: `integer`):

Release comparison window after each platform release.

## `minimumReleaseReviews` (type: `integer`):

Minimum reviews per release window before release differences are marked sufficient.

## `debug` (type: `boolean`):

Enable additional local diagnostic logging.

## Actor input object example

```json
{
  "mode": "comparePlatforms",
  "products": [
    {
      "productId": "spotify",
      "name": "Spotify",
      "googlePlayAppId": "com.spotify.music",
      "appleAppId": "324684580"
    }
  ],
  "countries": [
    "US"
  ],
  "languages": [
    "en"
  ],
  "ratings": [
    1,
    2,
    3,
    4,
    5
  ],
  "maxReviewsPerPlatform": 5,
  "requestTimeoutSecs": 30,
  "maxPagesPerPlatform": 1,
  "maxRequestsPerRun": 2,
  "includeDeveloperReplies": false,
  "includeReviewText": true,
  "daysBefore": 14,
  "daysAfter": 14,
  "minimumReleaseReviews": 5,
  "debug": false
}
```

# 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("obliging_persimmon_cki/cross-platform-mobile-feedback").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("obliging_persimmon_cki/cross-platform-mobile-feedback").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 obliging_persimmon_cki/cross-platform-mobile-feedback --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,obliging_persimmon_cki/cross-platform-mobile-feedback"
        }
    }
}

```

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/tIfWWepak0ilc7HZh/builds/Wd0pF7HaQtCbsnsar/openapi.json
