# Shopify App Store Keyword Rank Tracker & Scraper (`carmentara/shopify-app-intel`) Actor

Track your Shopify app's keyword rankings and competitors in App Store search daily. Also scrapes app details, pricing plans, reviews and categories.

- **URL**: https://apify.com/carmentara/shopify-app-intel.md
- **Developed by:** [Carmentara OU](https://apify.com/carmentara) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 app details

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

### Track your Shopify app's keyword rankings in the App Store

**Shopify App Store Scraper** tells you where your app and your competitors rank in **Shopify App Store search** for the keywords merchants type, such as `email marketing`, `upsell` or `abandoned cart`. Run it on a daily schedule and you get a rank history for App Store SEO (ASO): what moved, by how many places, and when.

The same Actor also scrapes **app details and pricing plans**, **app reviews** and **category rankings** from apps.shopify.com. You don't need a Shopify account, a Partner login or an API key.

- 🔎 **Keyword ranks**: the organic position of any app for each keyword, with the change since your last run
- 🎯 **Tracked apps**: one row per keyword × app for your app and the competitors you name, including "not found in the top N"
- 📈 **Category rankings**: the apps in a category in order, with rating, review count and rank change
- 🧩 **Apps and pricing plans**: name, developer, rating, review count, every plan and price, categories, features, languages, integrations, launch date, Built for Shopify badge
- ⭐ **Reviews**: newest reviews with rating, date, text, store name, country, time using the app and the developer's reply
- 📤 Export to CSV, Excel, JSON or Google Sheets, or pull the results through the API

### Who uses it

- **Shopify app developers and founders**: check every morning where your app ranks for your 5 to 20 most important keywords, and see whether a listing change helped.
- **App marketers (App Store SEO / ASO)**: see which competitor apps rank above you for each keyword, and who moved up after a launch.
- **Competitor research**: track competitors' positions, pricing plans and new reviews in one dataset.
- **Agencies and analysts**: build ranked shortlists of apps in a category with real ratings, review counts and prices.

Shopify's Partner Dashboard reports installs and revenue, but it doesn't show your organic position in App Store search. This Actor fills that gap from the public search results.

### How to track keyword rankings

1. [Create a free Apify account](https://console.apify.com/sign-up).
2. Open **Shopify App Store Scraper** and set **Mode** to `keyword-ranks`.
3. Add your **Search keywords**.
4. Under **Your / competitor apps to track**, add your app's handle and a few competitors. The handle is the last part of the app URL: `apps.shopify.com/omnisend` → `omnisend`. Full app URLs work too.
5. Turn on **Only output tracked apps** if you only need those positions. It's the cheapest setup: one row per keyword × app.
6. Click **Start**, then **Save as a new task**.
7. On the task, click **Schedule** and run it once a day. Each run compares positions with the previous run, so `rankChange` shows the daily movement and the run datasets add up to your rank history.

`rankChange` is positive when an app moved up. For example, `previousPosition: 7` and `position: 4` gives `rankChange: 3`.

### Input examples

**Keyword ranks: track your app and competitors (cheapest)**

```json
{
  "mode": "keyword-ranks",
  "keywords": ["email marketing", "sms marketing", "abandoned cart"],
  "targetAppHandles": ["omnisend", "klaviyo-email-marketing"],
  "onlyTargetApps": true,
  "maxResultsPerKeyword": 48
}
```

`maxResultsPerKeyword` sets how deep each search is scanned (24 is the first page, up to 240). If an app isn't found within that depth, its row says `"found": false`.

**Keyword ranks: the full top 10 for each keyword, plus your tracked apps**

```json
{
  "mode": "keyword-ranks",
  "keywords": ["email marketing", "abandoned cart"],
  "targetAppHandles": ["omnisend", "klaviyo-email-marketing"],
  "maxResultsPerKeyword": 10
}
```

**Apps and pricing plans**

```json
{ "mode": "apps", "appHandles": ["omnisend"], "onlyNew": false }
```

**Category rankings**

```json
{ "mode": "category-rankings", "category": "marketing-and-conversion-marketing-email-marketing", "maxItems": 3 }
```

The category slug is the part after `apps.shopify.com/categories/` in the category page URL.

**Reviews**

```json
{ "mode": "reviews", "appHandles": ["omnisend"], "maxReviewsPerApp": 2, "onlyNew": false }
```

### Output examples

Every row has a `mode`, a `timestamp` and one block of data. The **Output** tab shows each mode as its own table. These are real rows from test runs on 4 October 2026.

**Keyword ranks: a tracked app (`rowType: "target"`), second run of the day**

```json
{
  "mode": "keyword-ranks",
  "timestamp": "2026-10-04T14:50:14.907Z",
  "keywordRank": {
    "keyword": "email marketing",
    "rowType": "target",
    "position": 2,
    "previousPosition": 2,
    "rankChange": 0,
    "page": 1,
    "pagePosition": 2,
    "isSponsored": false,
    "handle": "omnisend",
    "name": "Omnisend Email Marketing & SMS",
    "rating": 4.7,
    "reviews": 3182,
    "pricingText": "Free plan available",
    "builtForShopify": false,
    "isTarget": true,
    "found": true,
    "sponsoredSlots": [],
    "scannedResults": 24,
    "totalResults": 3996,
    "url": "https://apps.shopify.com/omnisend",
    "searchUrl": "https://apps.shopify.com/search?q=email+marketing"
  }
}
```

**Keyword ranks: a tracked app that isn't in the scanned results**

```json
{ "mode": "keyword-ranks", "timestamp": "2026-10-04T14:50:14.763Z", "keywordRank": { "keyword": "abandoned cart", "rowType": "target", "position": null, "previousPosition": null, "rankChange": null, "page": null, "pagePosition": null, "isSponsored": false, "handle": "omnisend", "name": null, "rating": null, "reviews": null, "pricingText": null, "builtForShopify": null, "isTarget": true, "found": false, "sponsoredSlots": [], "scannedResults": 48, "totalResults": 4129, "url": "https://apps.shopify.com/omnisend", "searchUrl": "https://apps.shopify.com/search?q=abandoned+cart" } }
```

Without **Only output tracked apps**, you also get one `rowType: "result"` row for every app in the scanned results, in order, with the same fields (`found` and `sponsoredSlots` are `null` on those rows).

**Apps and pricing plans** (feature and integration lists trimmed)

```json
{
  "mode": "apps",
  "timestamp": "2026-10-04T14:49:45.151Z",
  "app": {
    "name": "Omnisend Email Marketing & SMS",
    "handle": "omnisend",
    "developer": "Omnisend",
    "rating": 4.7,
    "reviewCount": 3182,
    "pricingPlans": [
      { "name": "FREE", "price": 0, "currency": null, "billingInterval": null, "trialDays": null, "isFreePlan": true },
      { "name": "STANDARD", "price": 16, "currency": "USD", "billingInterval": "monthly", "trialDays": null, "isFreePlan": false },
      { "name": "PRO", "price": 59, "currency": "USD", "billingInterval": "monthly", "trialDays": null, "isFreePlan": false }
    ],
    "categories": ["Email marketing", "SMS marketing"],
    "features": ["Email campaigns", "SMS campaigns", "Push notifications"],
    "builtForShopify": false,
    "languages": ["English"],
    "launchDate": "2014-03-10",
    "integrations": ["Checkout", "Shopify Flow", "Aftership"],
    "url": "https://apps.shopify.com/omnisend",
    "pricingChanged": null
  }
}
```

**Category rankings** (first run, so `rankChange` is `null`)

```json
{ "mode": "category-rankings", "timestamp": "2026-10-04T14:49:57.314Z", "ranking": { "category": "marketing-and-conversion-marketing-email-marketing", "searchKeyword": null, "rank": 1, "handle": "klaviyo-email-marketing", "rating": 4.7, "reviews": 3349, "name": "Klaviyo: Email Marketing & SMS", "developer": "Klaviyo", "rankChange": null } }
```

**Reviews**

```json
{ "mode": "reviews", "timestamp": "2026-10-04T14:49:26.583Z", "review": { "handle": "omnisend", "rating": 5, "date": "2026-10-02", "text": "Best email & sms app.", "storeName": "MADE BY SOCIETY", "storeCountry": "Romania", "timeUsingApp": "12 months", "developerReply": null, "url": "https://apps.shopify.com/omnisend/reviews?sort_by=newest" } }
```

### How much does it cost?

You pay per row of results. There's no monthly fee, and platform usage isn't charged separately.

| What you get | Price | Example |
|---|---|---|
| Keyword rank row (one app's position for one keyword) | $0.002 | 10 keywords × 3 tracked apps = 30 rows = **$0.06 per run** |
| App details (one app with all plans and fields) | $0.002 | 1,000 apps = **$2** |
| Ranking row (one ranked app in category-rankings mode) | $0.003 | a top 24 category = **$0.072** |
| Review | $0.0005 | 1,000 reviews = **$0.50** |
| Run start | $0.00005 per run at the default 512 MB | |

**Daily keyword tracking example:** 10 keywords × 3 apps with **Only output tracked apps** on is 30 rows a day, so about $1.80 a month. Apify's free plan includes $5 of platform usage every month, which covers that.

Without **Only output tracked apps**, every scanned app is a row as well. For example, a full first page (24 results) for 10 keywords is 240 result rows plus your tracked-app rows.

Use **Max PPE charge (USD)** to cap what one run can cost. The run stops pushing results when it reaches the cap.

### Scheduling tip: build a rank history

- Save your keyword-ranks input as a **task** and add a daily **Schedule** (for example `0 7 * * *` with your timezone). See [Apify schedules](https://docs.apify.com/platform/schedules).
- Each run's dataset is one day's snapshot. Collect them with the [Apify API](https://docs.apify.com/api/v2) or the Python client, or send them to Google Sheets, Slack or a webhook through Apify's [integrations](https://docs.apify.com/platform/integrations).
- Keep the same keyword spelling every day. `previousPosition` and `rankChange` are stored per keyword in the key-value store named in **Delta store name**. If you run two different setups for the same keyword, give each task its own **Delta store name** so their comparisons don't mix.
- Daily is enough for most apps, and it keeps the cost predictable.

### Integrations

- **Schedules**: run daily or weekly for rankings, pricing changes and new reviews.
- **API and clients**: start runs and fetch results with the [Apify API](https://docs.apify.com/api/v2) or the [Python client](https://docs.apify.com/api/client/python). Code samples are on the API tab.
- **Zapier, Make, n8n, Google Sheets, Slack**: send rank changes, new reviews or pricing changes where your team works.
- **Webhooks**: trigger your own workflow when a run finishes.
- **AI agents (MCP)**: connect through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) so an AI assistant can look up apps, reviews and rankings.

### Limitations

- **Sponsored (Ad) placements are usually empty.** The Actor flags ads (`isSponsored`, `sponsoredSlots`) when Shopify shows them, but Shopify doesn't show ads to the servers Apify runs on, so in practice `sponsoredSlots` is `[]` and there are no ad rows. Organic positions are not affected: they are counted without ads.
- **Positions are what a logged-out visitor sees.** Shopify may personalize or localize results, so a logged-in merchant in another country can see a slightly different order.
- **Rank change needs a previous run.** `previousPosition` and `rankChange` are `null` on the first run for a keyword, and when an app wasn't found in the previous run.
- **Scan depth.** An app is only found within **Results per keyword** (up to 240). Tracked apps outside that depth come back with `"found": false`.
- **Reviews and pricing deltas.** With **Only new (delta)** on, reviews mode returns only reviews you haven't received yet, so a repeat run can return 0 rows. `pricingChanged` is only filled in once there is a previous run to compare with.
- **Shopify markup changes.** The Actor reads public pages. If Shopify changes its pages, a mode can break until we update the parser. Open an issue and we'll fix it.

### FAQ

**How do I track my Shopify app's keyword ranking?**
Use `keyword-ranks` mode with your keywords and your app handle in **Your / competitor apps to track**, turn on **Only output tracked apps**, and schedule it daily. Each row tells you the position, the previous position and the change.

**Can I track competitor app rankings?**
Yes. Add competitors' handles next to yours. You get one row per keyword × app, so you can see who ranks above you and who moved.

**What does `position` mean?**
The organic position in Shopify App Store search results for that keyword, counted from 1 across pages, with ads left out. `page` and `pagePosition` tell you where the app appeared on the page.

**Is it a full App Store SEO (ASO) tool?**
It gives you the data: daily positions, competitors and rank changes in a dataset you own. It doesn't suggest keywords or rewrite your listing.

**How deep does it search?**
24 results (the first page) by default, up to 240 with **Results per keyword**.

**What about category rankings?**
Use `category-rankings` mode with a category slug. You get each app's rank in that category, plus `rankChange` from the second run on.

**Do I need a Shopify account or API key?**
No.

**Is it legal to scrape the Shopify App Store?**
The Actor only reads public pages that anyone can open without logging in. It doesn't access merchant accounts or private data. Reviews include the store name and country as published on Shopify. You're responsible for how you use the data, especially personal data under GDPR or similar laws. If you're unsure, ask a legal advisor.

**How do I cap the cost?**
Set **Max PPE charge (USD)**, or use **Only output tracked apps** in keyword-ranks mode, **Max items** in category-rankings mode, and **Max reviews per app** in reviews mode.

### Support

Found a bug or need another field? Open an issue on the **Issues** tab and the Carmentara team will get back to you.

# Actor input Schema

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

Scrape app details, category/search rankings snapshot, keyword rank tracking, or app reviews.

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

keyword-ranks mode: Shopify App Store search keywords to track (e.g. 'email marketing').

## `targetAppHandles` (type: `array`):

keyword-ranks mode (optional): app handles or app URLs. Adds one row per keyword x app with its organic position, ad placements and rank change.

## `onlyTargetApps` (type: `boolean`):

keyword-ranks mode: output only the rows for target apps (cheapest way to track your positions).

## `maxResultsPerKeyword` (type: `integer`):

keyword-ranks mode: organic (non-ad) results to scan per keyword. 24 = first page.

## `includeSponsored` (type: `boolean`):

keyword-ranks mode: also output sponsored (Ad) placements, flagged isSponsored.

## `appUrls` (type: `array`):

Full app URLs (apps.shopify.com/...). Used in apps or reviews mode.

## `appHandles` (type: `array`):

App handles like 'klaviyo-email-marketing'. Used in apps or reviews mode.

## `searchKeyword` (type: `string`):

Keyword for search results (apps or category-rankings modes).

## `category` (type: `string`):

Category slug from apps.shopify.com/categories/... (category-rankings or apps).

## `onlyNew` (type: `boolean`):

Use KV delta store to only return new reviews, flag pricing changes, and include rank changes.

## `deltaStoreName` (type: `string`):

Name of the key-value store for deltas (allowed chars: a-zA-Z0-9!-\_.'()).

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

Limit apps in apps mode or ranking items in category-rankings mode.

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

Reviews mode: maximum number of reviews to output per app.

## `maxPpeChargeUSD` (type: `number`):

Cap spend from Actor.charge PPE events. The actor stops when reached.

## `useApifyProxy` (type: `boolean`):

Route requests through Apify Proxy (RESIDENTIAL group).

## `proxyCountryCode` (type: `string`):

E.g. US, GB, DE. Applies only when proxy is enabled.

## `maxConcurrency` (type: `integer`):

Maximum number of pages fetched in parallel.

## `requestIntervalMs` (type: `integer`):

Delay before each request in milliseconds (polite crawling; doubled on retries in rankings/reviews modes).

## Actor input object example

```json
{
  "mode": "apps",
  "keywords": [
    "email marketing",
    "upsell"
  ],
  "onlyTargetApps": false,
  "maxResultsPerKeyword": 24,
  "includeSponsored": true,
  "appHandles": [
    "klaviyo-email-marketing",
    "shopify-messaging"
  ],
  "onlyNew": true,
  "deltaStoreName": "shopify-app-store-intel-delta",
  "maxItems": 5,
  "maxReviewsPerApp": 100,
  "maxPpeChargeUSD": 1,
  "useApifyProxy": false,
  "maxConcurrency": 2,
  "requestIntervalMs": 1500
}
```

# Actor output Schema

## `dataset` (type: `string`):

All results (apps, rankings or reviews) are stored in the default dataset.

# 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": [
        "email marketing",
        "upsell"
    ],
    "appHandles": [
        "klaviyo-email-marketing",
        "shopify-messaging"
    ],
    "onlyNew": false,
    "maxItems": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("carmentara/shopify-app-intel").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": [
        "email marketing",
        "upsell",
    ],
    "appHandles": [
        "klaviyo-email-marketing",
        "shopify-messaging",
    ],
    "onlyNew": False,
    "maxItems": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("carmentara/shopify-app-intel").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": [
    "email marketing",
    "upsell"
  ],
  "appHandles": [
    "klaviyo-email-marketing",
    "shopify-messaging"
  ],
  "onlyNew": false,
  "maxItems": 5
}' |
apify call carmentara/shopify-app-intel --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,carmentara/shopify-app-intel"
        }
    }
}
```

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/seaxzOONE3VL8Owbj/builds/yvM4CDKT6Q81rLe4V/openapi.json
