# App Store & Google Play Keyword Rank Tracker (ASO) (`kirozhang/aso-keyword-rank-tracker`) Actor

Track where your apps and competitors rank for any keyword on the App Store and Google Play, in any country. Daily rank history, top-10 movers, new competitors and rank-drop alerts to Slack or a webhook, plus a shareable report.

- **URL**: https://apify.com/kirozhang/aso-keyword-rank-tracker.md
- **Developed by:** [Kiro Zhang](https://apify.com/kirozhang) (community)
- **Categories:** SEO tools, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 keyword checks

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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

## App Store & Google Play Keyword Rank Tracker (ASO)

Track **where your apps and your competitors rank for any keyword** on the **App Store** and **Google Play**, in any country – every day, with **rank history, top-10 movers, new competitors and rank-drop alerts** to Slack or a webhook. A lightweight, pay-per-use alternative to ASO tools that cost $50+/month.

- ✅ **Both stores, any country**: `us`, `gb`, `de`, `jp`, `br`… – ranks are checked per country.
- ✅ Track **your apps and competitors** by URL, App Store id, package name – or just the app name.
- ✅ **App Store ranks up to #200**, Google Play ranks in the top ~30 shown for the keyword.
- ✅ **Top apps per keyword** (name, developer, rating, rating count, price, genre) – instant keyword research.
- ✅ **Changes since the last run**: rank gains and drops, apps entering or leaving the top 10, **new competitors in the top 5**.
- ✅ **Visibility score** (0–100) per app across all keywords, plus top-3 / top-10 counts.
- ✅ **Slack / webhook alerts** and an optional fixed **report link** with the rank matrix.

### Who uses it

| You are | You get |
|---|---|
| **Indie developers** | Daily ranks for your 20 keywords in your top markets for a few dollars a month. |
| **ASO & growth teams** | Rank movements after metadata updates and competitor launches, in Slack. |
| **Agencies** | One shareable rank report per client app. |
| **Market researchers** | Who owns a keyword in each country – top apps, ratings and prices. |

### How to use it

1. Add **keywords** (one per line).
2. Add **your apps and competitors** – `https://apps.apple.com/us/app/streaks/id963034692`, `id963034692`, `https://play.google.com/store/apps/details?id=com.habitnow`, `com.habitnow`, or an app name such as `Habitica` (matched on both stores).
3. Pick the stores and countries, then schedule the run daily.

```json
{
    "keywords": ["habit tracker", "daily planner", "routine"],
    "apps": ["id963034692", "com.habitnow", "Habitica"],
    "platforms": ["appstore", "googleplay"],
    "countries": ["us", "gb", "de"],
    "rankChangeAlert": 3,
    "slackWebhookUrl": "https://hooks.slack.com/services/…"
}
```

### Output

One row per keyword × store × country:

```json
{
    "keyword": "habit tracker",
    "platform": "googleplay",
    "country": "us",
    "resultsChecked": 30,
    "ranks": { "com.habitnow": 2, "org.isoron.uhabits": 1, "Habitica": 5 },
    "bestTrackedRank": 1,
    "tracked": [
        { "app": "com.habitnow", "name": "HabitNow Daily Routine Planner", "rank": 2, "previousRank": 8, "change": 6, "bestRank": 2, "inTop10": true }
    ],
    "topApps": [
        { "rank": 1, "appId": "org.isoron.uhabits", "name": "Loop Habit Tracker", "developer": "Álinson S Xavier", "rating": 4.72, "price": 0, "currency": "USD", "url": "https://play.google.com/store/apps/details?id=org.isoron.uhabits" }
    ],
    "enteredTop10": [],
    "leftTop10": [],
    "alerts": ["HabitNow Daily Routine Planner climbed 8 → 2 for \"habit tracker\" (Google Play US)"]
}
```

`change` is positive when the app moved up, `"new"` when it started ranking and `"lost"` when it dropped out of the results. `OUTPUT` has one overview per app (visibility score, top 3, top 10, average rank, keywords up / down) and every alert.

### Pricing

| Event | Price |
|---|---|
| Keyword check (1 keyword × 1 store × 1 country, all tracked apps and top apps included) | **$3.00 per 1,000 checks** ($2.50 on Gold and higher Apify plans) |

Example: 20 keywords on both stores in 2 countries, checked daily = 80 checks/day ≈ **$7.20 / month**. The Apify free plan runs up to 10 keyword checks per run.

### FAQ

**How accurate are the ranks?** App Store ranks come from Apple's public search API, which follows App Store search closely; the live App Store can differ by a few places because it is personalized. Google Play ranks are read from the public search page for the chosen country and language.

**Why is my Google Play app not ranked?** Google Play shows about 30 apps per keyword. Apps below that are reported as `null` (not in the visible results).

**Can I track iPad or Mac apps?** The App Store search covers iPhone apps (most universal apps are included).

**Is it legal?** The Actor reads public store search results only and collects no personal data.

# Actor input Schema

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

Search keywords to track, one per line, e.g. <code>habit tracker</code>, <code>budget planner</code>.

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

Optional. Apps whose rank you want for every keyword: App Store URL or id (<code>https://apps.apple.com/us/app/streaks/id963034692</code>, <code>id963034692</code>), Google Play URL or package name (<code>com.habitnow</code>), or an app name to match on both stores. Leave empty for keyword research only (top apps per keyword).

## `platforms` (type: `array`):

Which stores to search.

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

2-letter country codes, e.g. <code>us</code>, <code>gb</code>, <code>de</code>, <code>jp</code>. Ranks are checked separately for each country.

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

Language code for Google Play results (hl), e.g. <code>en</code>, <code>de</code>, <code>ja</code>.

## `topResults` (type: `integer`):

How many top-ranking apps (name, developer, rating, price) to include in each row – your competitive landscape.

## `appStoreDepth` (type: `integer`):

How many App Store results to scan for your apps' ranks (max 200). Google Play shows about 30 results per keyword.

## `rankChangeAlert` (type: `integer`):

Positions. A tracked app that drops (or climbs) by at least this many places since the last run is listed in the alerts and notification.

## `trackingId` (type: `string`):

Optional. A stable name for this set of apps and keywords (e.g. <code>my-app-us</code>). Runs with the same name share rank history. Default: derived from the input.

## `slackWebhookUrl` (type: `string`):

Optional. A Slack <a href="https://api.slack.com/messaging/webhooks" target="_blank">Incoming Webhook</a> URL (https://hooks.slack.com/services/…). After a run you get one summary message in that channel. Stored encrypted.

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

Optional. Any https endpoint (Make, Zapier, n8n, a Microsoft Teams workflow or your own server). Receives one JSON POST per run with counts, items and the report link. Stored encrypted.

## `notifyOn` (type: `string`):

When the Slack / webhook message is sent.

## `publicReport` (type: `boolean`):

Off by default. When on, the HTML report (rank matrix, alerts, visibility score) is kept at one fixed link per Tracking name (OUTPUT.reportUrl) – share it with your team or a client. Anyone with the link can open it.

## `proxyConfiguration` (type: `object`):

Apify Proxy (datacenter) is used by default.

## Actor input object example

```json
{
  "keywords": [
    "habit tracker",
    "daily routine"
  ],
  "apps": [
    "id963034692",
    "com.habitnow",
    "org.isoron.uhabits"
  ],
  "platforms": [
    "appstore",
    "googleplay"
  ],
  "countries": [
    "us"
  ],
  "language": "en",
  "topResults": 10,
  "appStoreDepth": 200,
  "rankChangeAlert": 3,
  "notifyOn": "alerts",
  "publicReport": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `ranks` (type: `string`):

No description

## `report` (type: `string`):

No description

## `summary` (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 = {
    "keywords": [
        "habit tracker",
        "daily routine"
    ],
    "apps": [
        "id963034692",
        "com.habitnow",
        "org.isoron.uhabits"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kirozhang/aso-keyword-rank-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 = {
    "keywords": [
        "habit tracker",
        "daily routine",
    ],
    "apps": [
        "id963034692",
        "com.habitnow",
        "org.isoron.uhabits",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("kirozhang/aso-keyword-rank-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 '{
  "keywords": [
    "habit tracker",
    "daily routine"
  ],
  "apps": [
    "id963034692",
    "com.habitnow",
    "org.isoron.uhabits"
  ]
}' |
apify call kirozhang/aso-keyword-rank-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kirozhang/aso-keyword-rank-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/sIwlvhC16Ag8u2C7o/builds/PCTBO4lOBpzOJIFJ1/openapi.json
