# Shopify App Detector & Theme Detector — Store Lookup (`parallelstudio/shopify-store-tech-detector`) Actor

Qualify Shopify prospects and track competitors: paste store URLs and see the theme and version, 90 named apps (Klaviyo, Judge.me, Yotpo, ReCharge) plus app blocks, pixels, BNPL and product count. trackChanges flags apps added or removed since your last run. $0.01 per URL, CSV/JSON.

- **URL**: https://apify.com/parallelstudio/shopify-store-tech-detector.md
- **Developed by:** [Parallel Studio](https://apify.com/parallelstudio) (community)
- **Categories:** E-commerce, Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.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 App Detector & Theme Detector — Store Tech Stack

**Shopify app detector** and **theme detector** in one Actor: paste store URLs and learn which are on Shopify, which theme (and version) they run, and which apps and pixels they use. Answers *"what apps does a Shopify store use?"* and works as a bulk **Shopify store lookup**. CSV/JSON for agencies, app developers, and competitor research.

**Who it's for:** Shopify agencies, app developers and ecommerce researchers who need to know which theme and apps a list of stores uses, at $0.01 per store URL.

### Detects

- Shopify yes/no, shop domain, **theme name, version, theme-store ID**
- **90 apps** across reviews, email/SMS, loyalty, subscriptions, BNPL/wallets (Apple Pay, Google Pay, Shop Pay), search, page builders, chat, analytics/pixels (incl. Reddit, LinkedIn, Twitter), affiliates, back-in-stock, FOMO, and UGC — e.g. Klaviyo, Judge.me, Yotpo, Okendo, ReCharge, Gorgias, Attentive, Ordergroove, Bazaarvoice, Back in Stock, PushOwl, Dynamic Yield, Elevar, Triple Whale
- **Long-tail apps beyond the catalog**: every Online Store 2.0 app block / app embed (`shopify://apps/<handle>`) and theme app extension on the page is listed by handle in `appBlocks`; the ones not already named in `apps` go to `otherAppBlocks`, so niche apps still show up
- Currency, country, locale, product count (via public products.json), social links

### Use cases

- Shopify **agencies and app developers** qualifying prospects ("stores on Dawn without a reviews app")
- Competitor teardowns and theme market research

### Input

| Field | Meaning |
|---|---|
| startUrls | Store URLs or bare domains, one per line (e.g. `allbirds.com`). One row and $0.01 per URL, including non-Shopify sites and URLs that can't be read |
| includeProductCount | `true` (default) counts products via the store's public `/products.json`, when robots.txt allows it |
| respectRobots | `true` (default) checks each store's robots.txt first; a disallowed store returns a row with `error: "robots.txt disallows"` |
| trackChanges | `true` compares each store with this actor's previous run in your account and adds `appsAdded`, `appsRemoved`, `themeChanged`, `changed` (default `false`) |

### Example input

```json
{
  "startUrls": [
    "https://www.allbirds.com",
    "https://www.brooklinen.com",
    "https://www.deathwishcoffee.com"
  ],
  "includeProductCount": true,
  "respectRobots": true,
  "trackChanges": false
}
```

`trackChanges` (optional, default `false`): compare each store with the previous run and add change fields; see the FAQ.

### Example output (real record from the 2026-10-12 cloud run)

```json
{
  "url": "https://www.allbirds.com",
  "isShopify": true,
  "error": null,
  "finalUrl": "https://www.allbirds.com/",
  "title": "Allbirds: Comfortable, Sustainable Shoes & Apparel",
  "theme": "allbirds-theme",
  "themeVersion": "1.231.12",
  "themeStoreId": null,
  "shopDomain": "weareallbirds.myshopify.com",
  "currency": "USD",
  "country": "US",
  "locale": "en-US",
  "apps": [
    "Yotpo",
    "Attentive",
    "Google Analytics",
    "Elevar"
  ],
  "socials": [
    "https://www.instagram.com/allbirds",
    "http://pinterest.com/weareallbirds",
    "https://www.facebook.com/weareallbirds",
    "https://twitter.com/allbirds",
    "https://www.tiktok.com/@weareallbirds",
    "https://www.youtube.com/channel/UCnGErLCau5qNJ0Xwe6uEyTw"
  ],
  "productCount": 692,
  "productCountCapped": false
}
```

### Measured coverage (2026-10-14 local probe)

Eight live Shopify storefronts (Allbirds, Gymshark, Brooklinen, Death Wish Coffee, ColourPop, Glossier, Ruggable, Tentree): **8/8** detected as Shopify, **6/8** returned a theme name, and new detectors fired as expected (Apple Pay on 7, Back in Stock on 4, Dynamic Yield on 2, plus Ordergroove, Bazaarvoice, Recart, Refersion, PushOwl, Fomo, Optimizely on individual stores).

**App-block probe (2026-10-14, 4 stores):** handles found on 3 of 4 storefronts, adding 5 apps the 90-app catalog doesn't name: `redo` (Allbirds), `sitemap-noindex-pro-seo` (Gymshark), `checkmate`, `onetrust-consent-management`, `watchlist` (Brooklinen).

### FAQ

**What apps does a Shopify store use?** Add the store URL and the Actor returns the apps it can see in the public storefront HTML (reviews, email/SMS, loyalty, subscriptions, BNPL, search, page builders, chat, analytics pixels).

**How do I find out which Shopify theme a store uses?** The `theme`, `themeVersion` and `themeStoreId` fields come from the theme metadata Shopify embeds in the storefront.

**Can I do a Shopify store lookup in bulk?** Yes. Pass a list of URLs in `startUrls`; each store is one result row, exportable as CSV, JSON or Excel.

**What if a store uses an app you don't recognize?** Check `otherAppBlocks`. Online Store 2.0 themes print a comment around every app block and app embed with the app's handle (for example `redo` or `onetrust-consent-management`), and theme app extensions load from `cdn.shopify.com/extensions/...`. The Actor lists those handles even when the app isn't in the named catalog. A handle is the developer's app slug, usually close to but not always identical to the brand name.

**Is a site on Shopify at all?** `isShopify` tells you, and `shopDomain` gives the store's myshopify.com domain when exposed.

**Is the store headless?** `headless: true` means the site is on Shopify but hides both the theme metadata and the public `/products.json` feed, which is what Hydrogen and other custom front ends do. In that case `productCount` is `null` (not 0) and `productCountNote` says why. In a 2026-10-18 local run, Ruggable and Chubbies came back `headless: true`, while Allbirds (692 products), Brooklinen (512) and Death Wish Coffee (147) returned full counts. If a later page of `/products.json` fails even after a retry (for example a rate limit), `productCount` is a lower bound and `productCountNote` says so, so a big drop between two checks is never silently a fetch error.

**Can I monitor stores for app changes?** Yes. Set `trackChanges` to `true` and schedule the Actor (for example weekly). Each store is compared with its snapshot from the previous run, saved in the named key-value store `shopify-tech-detector-state` in your account, and each row gains `previousCheckedAt`, `firstSeen`, `appsAdded`, `appsRemoved`, `appBlocksAdded`, `appBlocksRemoved`, `themeChanged`, `previousTheme`, `previousThemeVersion` and `changed`. Rows with an `error` don't overwrite the snapshot and have these fields set to `null` (except `previousCheckedAt`). Each URL is still charged $0.01 per check. Example input:

```json
{"startUrls":["https://www.allbirds.com"],"trackChanges":true}
```

**How do I get the results into Google Sheets, my CRM or Slack?** Every run saves a dataset you can download as CSV, Excel or JSON, or read through the Apify API. To automate it, put the Actor on an Apify schedule (for example weekly with `trackChanges: true`) and connect one of Apify's integrations (Google Sheets, Slack, email, Zapier, Make or a webhook) so new rows, or only the stores where `changed` is `true`, land where your team works.

**Limits:** apps loaded only after user interaction, or installed purely server-side, won't be detected. Headless (Hydrogen) stores may not expose a theme or a product count.

### Pricing

Pay per event: **$0.01 per store** analyzed, meaning one result row per URL in `startUrls`. Every row is charged, including URLs that turn out not to be Shopify (`isShopify: false`) and URLs that couldn't be read (robots.txt disallows it, or the fetch failed; the reason is in `error`). 100 URLs cost $1.00. Remove duplicates and dead domains from your list first to avoid paying for them.

What common jobs cost at $0.01 per store:

- Check one store's apps and theme: $0.01.
- Weekly `trackChanges` watch on 10 competitor stores: $0.10 a week, about $0.43 a month.
- Weekly `trackChanges` watch on 50 stores: $0.50 a week, about $2.17 a month.
- One-time pass over a 1,000-URL prospect list: $10.00.

### Notes

Reads only public storefront pages and respects robots.txt by default. Headless (Hydrogen) storefronts may not expose a theme. Built for prospect research — learn more about [Shopify themes](https://themes.shopify.com/?utm_source=apify\&utm_medium=listing\&utm_campaign=shopify-store-tech-detector).

### Related actors

Other public-data Actors from parallelstudio:

- [Minneapolis building permits since 2016: contractor, valuation, address, ward, neighborhood](https://apify.com/parallelstudio/twin-cities-building-permits) ($0.004/permit)
- [Federal contract awards from USAspending.gov by state, NAICS, agency or company, plus recompete leads](https://apify.com/parallelstudio/usaspending-contract-awards) ($0.004/award)
- [CPSC and FDA food, drug and device recalls in one schema, plus opt-in NHTSA vehicle recalls](https://apify.com/parallelstudio/us-product-recalls-unified) ($0.003/recall)

# Actor input Schema

## `startUrls` (type: `array`):

Store URLs or domains, one per line. Each URL returns one row and is charged $0.01, including non-Shopify sites and URLs that can't be read.

## `includeProductCount` (type: `boolean`):

Count products via /products.json

## `respectRobots` (type: `boolean`):

Respect robots.txt

## `trackChanges` (type: `boolean`):

Compares each store to the previous run of this actor in your account and adds appsAdded/appsRemoved/themeChanged/changed fields. Schedule it weekly to monitor competitors. Each URL is still charged $0.01 per check.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.allbirds.com",
    "https://www.brooklinen.com",
    "https://www.deathwishcoffee.com"
  ],
  "includeProductCount": true,
  "respectRobots": true,
  "trackChanges": false
}
```

# Actor output Schema

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

All records from the default dataset (JSON/CSV/Excel via the dataset API).

# 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 = {
    "startUrls": [
        "https://www.allbirds.com",
        "https://www.brooklinen.com",
        "https://www.deathwishcoffee.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("parallelstudio/shopify-store-tech-detector").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 = { "startUrls": [
        "https://www.allbirds.com",
        "https://www.brooklinen.com",
        "https://www.deathwishcoffee.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("parallelstudio/shopify-store-tech-detector").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 '{
  "startUrls": [
    "https://www.allbirds.com",
    "https://www.brooklinen.com",
    "https://www.deathwishcoffee.com"
  ]
}' |
apify call parallelstudio/shopify-store-tech-detector --silent --output-dataset

```

## MCP server setup

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

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/frIRJV6kb8CIm6KWo/builds/KemV0PBXG9WA8XExP/openapi.json
