# ASO Audit: App Store & Google Play Listing Check (`ruesandora/mobile-app-store-audit`) Actor

Audit App Store and Google Play listings in one run: ASO score with the top 5 fixes, star distribution (Google Play), version recency, rating trend between your runs and a side-by-side comparison with competitor apps. Numbers only, no review text. No API keys.

- **URL**: https://apify.com/ruesandora/mobile-app-store-audit.md
- **Developed by:** [Rues Forum](https://apify.com/ruesandora) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

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

## What's an Apify Actor?

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

## Mobile App Store Audit: ASO, ratings and competitors (App Store + Google Play)

Audit App Store and Google Play listings in one run. For each app you get an **ASO score (0-100)** with the **5 most valuable fixes**, the **star distribution** (Google Play only), version recency, the **rating trend since your last run** and an optional **side-by-side comparison** with competitor apps. Numbers only: no review text, no reviewer names. No API keys, no login.

### What does it do?

Paste your apps and optionally up to 4 competitors. For each app the Actor reads the public Google Play page or, for the App Store, Apple's official public iTunes Lookup API (no store page is scraped) and returns one dataset row. A final summary row is also saved as `SUMMARY`.

### Input

| Field | Description | Default |
|---|---|---|
| `apps` | 1-50 apps: App Store URL or numeric ID, Google Play URL or package name (mix freely) | required |
| `competitors` | 0-4 competitor apps, audited like yours and added to the comparison | empty |
| `country` | Two-letter store country (`us`, `gb`, `tr`, `de` ...). An App Store URL's own country wins | `us` |
| `language` | `en` or `tr` (recommendations and Play page language) | `en` |
| `compare` | Add a side-by-side comparison when 2 or more apps are read | `true` |
| `keepHistory` | Save one small snapshot per app in your own account so the next run shows the trend | `true` |

```json
{ "apps": ["https://apps.apple.com/us/app/facebook/id284882215", "com.spotify.music"], "competitors": [], "country": "us", "language": "en" }
```

### Output (one row per app)

- `platform`, `title`, `developer`, `category`, `country`, `url`
- `aso`: `score`, `coveragePct`, `topRecommendations[]` (check, points lost, advice), `checks[]`, `metadata`, `media`, `privacy`, `localization`, `website`
- `ratings`: average and count; on Google Play also the star distribution, five-star and negative share. The App Store does not publish a star distribution through its public API, so these stay `null` for iOS apps.
- `version`: current version, last update, days since update, current-version rating (App Store)
- `trend`: change since your previous run
- `installs` (Google Play), `notes[]`, `error`
- A `comparison` row: metrics per app and the leader per metric. A `summary` row.

Fields the store does not publish are `null` ("unknown"). For App Store apps this also covers subtitle, privacy labels and preview video, which the public Lookup API does not return: those checks are left out of the score. The Actor never guesses.

### Pricing (pay per event)

See the Pricing tab. One event per app that could be read, plus one event for the comparison (once per run). Apps that cannot be read are not charged. You can set a maximum cost per run and the Actor stops when it is reached.

### FAQ

**Is the score an official store ranking?** No. It is a listing-quality score based on public best practice. It does not predict your rank.

**Does it read reviews?** No. Review texts and reviewer names are never requested or stored.

**Where is the history kept?** In a named key-value store (`app-rating-history`) in your own Apify account. Only numbers are saved.

### Limits and politeness

1-50 apps per run, plus 1 comparison. One request per host every 1.5 seconds, so large runs take a little longer. The Actor respects `robots.txt` and identifies itself with its own User-Agent. No personal data is collected.

Full report: https://ruesandora.com

### Known limits (honest notes)

- Google Play has no official API. The page layout can change; if a field cannot be found it is `null` and the check is left out of the score (coverage shows how much of the score was measurable). If the page itself cannot be read the app is an error row and is not charged.
- Play: version and screenshot count are not read. App Store: no star distribution, subtitle, privacy labels or preview video.
- Comparison uses up to 5 apps: your apps first, completed with competitors.
- Apps and competitors together are capped at 50 per run.

# Actor input Schema

## `apps` (type: `array`):

App Store URL or numeric ID (e.g. 284882215), Google Play URL or package name (e.g. com.spotify.music).

## `competitors` (type: `array`):

Optional. Audited like your apps and added to the side-by-side comparison.

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

Two-letter store country, e.g. us, gb, tr, de. An App Store URL's own country wins.

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

Language of the recommendations and of the Google Play page.

## `compare` (type: `boolean`):

When on and at least 2 apps are read, one side-by-side comparison of the first 5 apps is added (separate event).

## `keepHistory` (type: `boolean`):

Saves one small snapshot per app (rating, count, version, star counts where available) in the key-value store "app-rating-history" of your own account, so the next run can show the trend. Turn off for a one-off check.

## Actor input object example

```json
{
  "apps": [
    "https://apps.apple.com/us/app/facebook/id284882215",
    "com.spotify.music"
  ],
  "country": "us",
  "language": "en",
  "compare": true,
  "keepHistory": true
}
```

# Actor output Schema

## `results` (type: `string`):

Audit rows pushed to the default dataset. Views: overview, comparison.

## `summary` (type: `string`):

Run summary JSON stored as the SUMMARY record in the default key-value store.

# 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 = {
    "apps": [
        "https://apps.apple.com/us/app/facebook/id284882215",
        "com.spotify.music"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ruesandora/mobile-app-store-audit").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 = { "apps": [
        "https://apps.apple.com/us/app/facebook/id284882215",
        "com.spotify.music",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("ruesandora/mobile-app-store-audit").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 '{
  "apps": [
    "https://apps.apple.com/us/app/facebook/id284882215",
    "com.spotify.music"
  ]
}' |
apify call ruesandora/mobile-app-store-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ruesandora/mobile-app-store-audit"
        }
    }
}
```

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/tyh5W7cEqZei7OeZD/builds/nHBdGmF72f3CHzhHR/openapi.json
