# Shopify Store Analyzer — Apps, Catalog & Teardown (AI) (`noniner/shopify-store-analyzer`) Actor

Analyze any Shopify store: detect the apps it runs, measure its catalog size and price range from the public products.json, and get an AI store teardown with maturity and fit scoring.

- **URL**: https://apify.com/noniner/shopify-store-analyzer.md
- **Developed by:** [Fredrik Hansson](https://apify.com/noniner) (community)
- **Categories:** E-commerce, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $100.00 / 1,000 store analyzeds

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

## Shopify Store Analyzer — Apps, Catalog & Teardown (AI)

**Point it at any Shopify store and get the whole picture in one record.** This Actor detects whether a store runs on **Shopify**, fingerprints the **apps it has installed** (reviews, subscriptions, SMS, email, upsell, loyalty, support, search, mobile app), measures its **catalog size and price range** straight from the store's **public `products.json`**, and uses OpenAI to write an **AI store teardown** — a summary, its positioning, an estimated maturity level, concrete DTC signals, and an optional **fit score** against whatever you sell to Shopify merchants.

You bring a list of store domains. It hands back a prospect-ready teardown per store.

***

### The flow

```
1. Give store domains          2. Detect + read the store            3. Get a finished teardown
   (gymshark.com,          →      Shopify? which apps?          →      apps · catalog size · price
    allbirds.com, ...)             products.json catalog                range · AI teardown · fit score
```

1. **Paste store domains or URLs** into `domains` — one per line.
2. For each store the Actor **fetches the homepage** (detects Shopify vs other platforms + fingerprints installed apps), then **pulls the store's public `products.json`** to measure the catalog.
3. The **AI layer** reads the hard signals and returns a grounded teardown — plus a **fit score** if you describe what you sell.

***

### What you get per store

For every store, the Actor returns:

1. **Platform detection** — `isShopify` (true/false) and `platform` ("Shopify", or a best-guess "WooCommerce" / "BigCommerce" / "Wix" / "Squarespace" / "Magento" / "Other" / null). It reads `cdn.shopify.com` / `cdn/shop/` markers, `Shopify.*` JS globals, and `x-shopify-*` / `x-sorting-hat-shopid` response headers.
2. **Installed apps (`apps`)** — a fingerprinted list of `{ name, category }` for ~25 Shopify-ecosystem apps and martech: **Klaviyo, Recharge, Appstle, Bold, Loox, Judge.me, Yotpo, Okendo, Stamped, Gorgias, Rebuy, ReConvert, Attentive, Postscript, Smile.io, LoyaltyLion, Tapcart, Octane AI, Privy, Justuno, Searchanise, Fast Simon, Zendesk, Tidio** and Shopify checkout signals. Categories are `Reviews / Subscriptions / SMS / Email / Upsell / Loyalty / Support / Search / MobileApp / …`.
3. **Catalog stats from the public `products.json`** — `productCount` (approx; `productCountCapped` flags when there are likely more), `priceRange` `{ min, max, avg, currency }` computed across all variants, `topProductTypes`, `vendors`, `collectionsCount` (from `/collections.json`), and `createdSpan` (earliest/latest product `created_at` → catalog freshness).
4. **`theme`** — the Shopify theme name, when the store exposes it.

Then the **AI layer** (OpenAI `gpt-4o-mini`, fast and low-cost) adds:

- **`storeSummary`** — one sentence on what the store is.
- **`positioning`** — one sentence on how it positions itself.
- **`estimatedMaturity`** — `new` / `growing` / `established` / `null`, inferred from catalog size, app stack and product age.
- **`dtcSignals`** — short, concrete observations (e.g. `"runs Klaviyo + Loox"`, `"250+ products"`, `"subscription model via Recharge"`).
- **`fitScore`** (0–100) + **`fitReason`** — only when you set `yourOffering`. The reason is **grounded in the apps present or missing** (e.g. *"no subscription app detected → strong fit for a subscriptions tool"*). It never names an app that wasn't actually detected.

***

### Three ways people use it

- **Shopify app vendor prospecting** — want to **detect Shopify apps** across a list of stores and find merchants who are *missing* your category? Set `yourOffering` and the fit score surfaces the stores with the clearest gap ("no reviews app", "no subscription app"), each with the reason spelled out.
- **DTC competitive analysis** — **analyze a competitor's Shopify store** end to end: how big is their catalog, what price band do they play in, which reviews / email / SMS / upsell apps power their funnel, and how mature does the operation look.
- **Ecommerce market research** — profile a whole segment of DTC brands at once: catalog sizes, price ranges, app adoption and maturity, all in one dataset ready for a spreadsheet or BI tool.

***

### Input

| Field | Type | Notes |
|---|---|---|
| `domains` | array | **Required.** Store domains or URLs, one per line (the domain is extracted). |
| `yourOffering` | string | Optional. What you sell to Shopify merchants. Enables the `fitScore` + `fitReason`. |
| `maxProducts` | integer | Cap products pulled per store for catalog stats. Default `250`. |
| `maxResults` | integer | Max stores to analyze. One pay-per-event charge per store. Default `100`. |
| `maxConcurrency` | integer | Stores processed in parallel. Default `5`. |
| `model` | string | Override the OpenAI model. Default `gpt-4o-mini`. |

#### Minimal input example

```json
{
  "domains": ["gymshark.com", "allbirds.com"],
  "yourOffering": "We sell a subscription-billing app for Shopify"
}
```

***

### Output example

```json
{
  "domain": "gymshark.com",
  "website": "https://gymshark.com",
  "isShopify": true,
  "platform": "Shopify",
  "productsAccessible": true,
  "productCount": 250,
  "productCountCapped": true,
  "priceRange": { "min": 8, "max": 100, "avg": 49.79, "currency": null },
  "topProductTypes": ["Womens>Apparel>Leggings", "Mens>Apparel>SS Tops", "Womens>Apparel>Sports Bras"],
  "vendors": ["Gymshark"],
  "collectionsCount": 250,
  "createdSpan": { "earliest": "2017-03-02T10:00:00Z", "latest": "2026-09-30T12:00:00Z" },
  "apps": [
    { "name": "Zendesk", "category": "Support" },
    { "name": "Shopify Shop Pay", "category": "Checkout" }
  ],
  "theme": "Hydra 1.15.0",
  "storeSummary": "Gymshark is a Shopify-based fitness apparel brand with a diverse product range.",
  "positioning": "Sells high-quality fitness apparel for men and women.",
  "estimatedMaturity": "established",
  "dtcSignals": ["250+ products", "average price of 49.79", "runs Zendesk for support"],
  "fitScore": 80,
  "fitReason": "no subscription app detected -> strong fit for a subscriptions tool."
}
```

If a store has locked its `products.json`, it comes back with `productsAccessible: false` and empty catalog stats — the platform/app detection and AI teardown still run, and the store still counts as analyzed.

***

### Pay-per-event pricing

This Actor uses **pay-per-event** billing with a single event:

| Event | Price | Charged when |
|---|---|---|
| `store-analyzed` | $0.10 | Once per store analyzed (platform, installed apps, catalog size, price range and AI teardown). |

The Actor logs its OpenAI token usage and the estimated AI cost at the end of every run, so the event price always stays safely above the model cost (a teardown runs around $0.0001–$0.0002 on `gpt-4o-mini`).

***

### How we read the catalog

Catalog stats come **only** from the store's **own public `products.json` and `collections.json`** endpoints — the same JSON a browser can request. There is **no login, no checkout, no scraping trickery**: we page through `products.json?limit=250&page=N` (capped), read prices off the public variants, and tally product types and vendors. Stores that have locked those endpoints simply return `productsAccessible: false`.

***

### Setup

The AI teardown calls the OpenAI API. Set the environment variable / secret **`OPENAI_API_KEY`** on the Actor. Without it, **platform detection, app fingerprinting and catalog stats still run and ship** — only `storeSummary`, `positioning`, `estimatedMaturity`, `dtcSignals`, `fitScore` and `fitReason` are left empty.

***

### Use it from an AI agent (Apify MCP server)

This Actor is available through the [Apify MCP server](https://mcp.apify.com), so AI agents (Claude, ChatGPT, or anything that speaks MCP) can call it as a tool — hand it a list of store `domains` (and optionally `yourOffering`), and read back the teardowns — with no custom integration code.

***

### Run it locally

```bash
npm install
## put your input in storage/key_value_stores/default/INPUT.json
export OPENAI_API_KEY=sk-...   # optional, enables the AI teardown
apify run -p
```

***

### Chain it

**This Actor is a building block in the No Niner ecommerce suite.** Wire it to the next step with no code in the **Integrations** tab (trigger: *Run succeeded* → start the next Actor), or run them in sequence.

- ⬇️ Next: [Product Catalog Extractor](https://apify.com/noniner/product-catalog-extractor) — pull the full catalog from the stores you flagged.
- ⬇️ Then: [DTC Brand Teardown](https://apify.com/noniner/dtc-brand-teardown) — turn store + catalog + tech into a full battlecard.

***

### Related actors

- [Product Catalog Extractor](https://apify.com/noniner/product-catalog-extractor) — Pull a store's full product catalog into a clean, structured dataset.
- [DTC Brand Teardown](https://apify.com/noniner/dtc-brand-teardown) — A deeper AI teardown of a DTC brand's site, offer and funnel.
- [B2B Tech Stack Detector](https://apify.com/noniner/b2b-tech-stack-detector) — Fingerprint the full technology stack behind any website.
- [AI Price Intelligence](https://apify.com/noniner/ai-price-intelligence) — Track and compare competitor pricing across stores.

***

Built by the No Niner team.

# Actor input Schema

## `domains` (type: `array`):

Shopify store domains or URLs (the domain is extracted). One per line. Optional if you supply a datasetId for chaining.

## `yourOffering` (type: `string`):

Describe the app or service you sell to Shopify merchants. If set, each store gets a fit score (0-100) and a reason grounded in the apps it is / isn't running.

## `maxProducts` (type: `integer`):

Cap how many products to pull from each store's public products.json when computing catalog stats.

## `maxResults` (type: `integer`):

Max stores to analyze. One pay-per-event charge per store analyzed.

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

How many stores to process in parallel.

## `model` (type: `string`):

Override the model (default gpt-4o-mini).

## `datasetId` (type: `string`):

Optional. Read the URLs/domains from a previous Actor run's dataset — for no-code chaining via the Integrations tab.

## `datasetField` (type: `string`):

Which dataset field holds the URL/domain. Leave blank to auto-detect (url, website, domain, pageUrl, companyUrl, link).

## Actor input object example

```json
{
  "domains": [
    "gymshark.com",
    "allbirds.com"
  ],
  "maxProducts": 250,
  "maxResults": 100,
  "maxConcurrency": 5
}
```

# Actor output Schema

## `stores` (type: `string`):

All analyzed store records 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 = {
    "domains": [
        "gymshark.com",
        "allbirds.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("noniner/shopify-store-analyzer").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 = { "domains": [
        "gymshark.com",
        "allbirds.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("noniner/shopify-store-analyzer").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 '{
  "domains": [
    "gymshark.com",
    "allbirds.com"
  ]
}' |
apify call noniner/shopify-store-analyzer --silent --output-dataset

```

## MCP server setup

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

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/EWkoewt81k3pc46mo/builds/ojkRWw4qywVzksxWE/openapi.json
