# Shopify Merchant Scraper — Ad Pixels & Brand Data (`scrapier/shopify-merchant-scraper`) Actor

Shopify Merchant Scraper extracts merchant and brand data, including store details, advertising pixels, technologies, social profiles, contact information, and ecommerce signals. Discover Shopify brands, analyze marketing stacks, and build targeted merchant lists for research and prospecting.

- **URL**: https://apify.com/scrapier/shopify-merchant-scraper.md
- **Developed by:** [Scrapier](https://apify.com/scrapier) (community)
- **Categories:** Automation, Lead generation, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### Shopify Merchant Scraper — Ad Pixels & Brand Data

Shopify Merchant Scraper — Ad Pixels & Brand Data turns a list of Shopify storefront URLs into one structured row per store: the full merchant-contact lead sheet (email, phone, seven social platforms, catalogue size, currency) plus two feature blocks unique to this variant — a homepage-embedded ad and analytics pixel registry, and a brand-identity signal block built from Organization structured data, the store's real theme identity, and a shop-ID integrity cross-check. Every response is structured JSON, ready to pass to an LLM, load into a CRM, or feed a monitoring pipeline. No Shopify account or login is required.

***

### 🧭 What is Shopify Merchant Scraper — Ad Pixels & Brand Data?

It's a bulk Shopify storefront analyzer: you supply a list of store URLs, and it returns one enriched lead row per store — no query, no search, no crawling beyond the homepage and a handful of well-known public paths. It combines the base merchant-lead dataset (contacts, socials, catalogue size, commerce configuration) with this variant's own extraction: the storefront's marketing/ad-tech pixel registry and its brand-identity signals. No Shopify account, API key, or app installation is required — every field is parsed from HTML and JSON the storefront already serves publicly.

- 🏪 Verified merchant identity, contact channels, and 7-platform social detection
- 📦 Authoritative catalogue size and commerce configuration from `/meta.json`
- 📡 A raw ad/analytics pixel registry (`adPixels[]`) — ids and hosts only, never a guessed vendor name
- 🎨 Organization structured-data brand signals (logo, official social/press links, telephone, area served)
- 🎨 Real installed-theme identity and a shop-ID cross-check between two independent homepage/JSON sources
- 🚦 An explicit `storefrontStatus` gate instead of a silent, all-null row on closed or blocked stores

***

### 📊 What data can you get with Shopify Merchant Scraper — Ad Pixels & Brand Data?

Every run returns one row per storefront, built from six groups of fields:

| Result Type | Extracted Fields | Primary Use Case |
| --- | --- | --- |
| Merchant lead sheet | `storeName`, `merchantName`, `domain`, `url`, `email`, `phone`, `facebook`, `instagram`, `twitter`, `tiktok`, `youtube`, `pinterest`, `linkedin`, `socialPlatformCount`, `hasEmail`, `hasPhone`, `leadQuality` | B2B prospecting and outreach list building |
| Storefront commerce profile | `productCount`, `publishedCollectionsCount`, `currency`, `moneyFormat`, `myshopifyDomain`, `merchantDescription`, `merchantCity`, `merchantProvince`, `shipsToCountries`, `acceptedCardBrands`, `offersShopPayInstallments` | Market sizing, catalogue and geography research |
| Theme & app tech stack | `themeName`, `themeVersion`, `themeRole`, `installedApps`, `installedAppsCount`, `themeAppExtensions`, `appProxyHandles`, `appCount` | Competitive tech-stack audits |
| Ad & analytics pixel registry | `adPixelCount`, `adPixels[]` (`pixelId`, `pixelType`, `apiClientId`, `privacyPurposes`, `configHost`) | Martech / ad-tech competitive research |
| Brand-identity signals | `brandLogoUrl`, `brandSameAs`, `brandTelephone`, `brandAreaServed`, `shopId`, `shopIdMatch` | Brand audits, entity verification |
| Run metadata | `storefrontStatus`, `scrapedAt` | Run auditing and data freshness |

#### 📡 Ad & Analytics Pixel Registry and Brand-Identity Signals

This is the feature set that separates this variant from a plain Shopify lead scraper. `adPixels[]` is parsed straight from the storefront's own `webPixelsConfigList` — the same registry the store itself loads to fire its marketing and analytics tags. Each entry carries `pixelId`, `pixelType`, the numeric `apiClientId`, the pixel's declared `privacyPurposes[]`, and `configHost` — a real hostname the Actor extracts from the pixel's own configuration blob (with Shopify's own infrastructure hosts filtered out). No public mapping from `apiClientId` to a vendor brand name exists, so this Actor never guesses one — you get the raw, verifiable ids instead. The brand-identity block runs alongside it: `brandLogoUrl`, `brandSameAs`, `brandTelephone`, and `brandAreaServed` come from the homepage's `Organization`-typed JSON-LD, and `shopId` / `shopIdMatch` cross-check the shop ID embedded in the homepage's pixel loader against the ID in `/meta.json`.

```json
{
  "adPixelCount": 2,
  "adPixels": [
    { "pixelId": "gid://shopify/WebPixel/123", "pixelType": "APP", "apiClientId": 580111, "privacyPurposes": ["ANALYTICS", "MARKETING"], "configHost": "webhooks.fivetran.com" },
    { "pixelId": "gid://shopify/WebPixel/456", "pixelType": "CUSTOM", "apiClientId": null, "privacyPurposes": ["ANALYTICS"], "configHost": null }
  ],
  "brandLogoUrl": "https://cdn.shopify.com/s/files/1/0554/9812/files/logo.png",
  "brandSameAs": ["https://www.instagram.com/kyliecosmetics/", "https://www.facebook.com/KylieCosmetics/"],
  "shopId": 12345678,
  "shopIdMatch": true
}
```

⚠️ `brandLogoUrl`, `brandSameAs`, `brandTelephone`, and `brandAreaServed` are only populated on storefronts that actually publish `Organization`-typed structured data — an empty result on these fields means the store didn't publish it, not that the Actor missed it.

#### 🏪 Verified Merchant Lead Sheet

The base of every row is the same merchant-lead sheet the underlying Shopify Merchant Scraper produces: real merchant name, `myshopify.com` domain, description, city/province, currency, and money format — all read from the storefront's own `/meta.json`, which also supplies `productCount` as an authoritative published-product count rather than a paginated `products.json` figure. Contact email and phone are pulled from the homepage plus four known contact paths, and social links are detected across seven platforms. `leadQuality` is a deterministic, non-AI label derived from `hasEmail`, `hasPhone`, and `socialPlatformCount`.

***

### 💡 Why not build this yourself?

Shopify does not expose a public API endpoint for pulling another merchant's ad-pixel registry or brand-identity data by domain. Both the Admin API and the Storefront API require an access token issued from inside the target store's own admin — either through a custom app installed by that store's owner, or through the `storefrontAccessTokenCreate` mutation called with that store's Admin credentials (confirmed on Shopify's developer docs as of 2026-08-15). There is no equivalent for a third party researching a store it doesn't own.

That leaves homepage HTML and the handful of public JSON endpoints (`/meta.json`, the embedded `webPixelsConfigList`, `Organization` JSON-LD, `Shopify.theme`) as the only real signal source — and each of them is theme-dependent, changes shape between Shopify theme versions, and can start returning 403/429 responses under sustained request volume. Building and maintaining regex- and JSON-shape-tolerant parsers for all of that, plus a proxy-escalation strategy for blocked requests, across thousands of storefronts running different themes, is the maintenance burden this Actor exists to absorb.

***

### 🔍 What's the difference between a Shopify lead scraper and an ad-pixel & brand-data scraper?

A plain Shopify lead scraper stops at contact and commerce data: email, phone, socials, product count, currency. It tells you a store exists and how to reach it, but nothing about how the brand actually markets itself. This Actor returns the same lead sheet plus two additional layers a plain lead scraper omits entirely: the storefront's own ad/analytics pixel registry, arriving in `adPixels[]`, and its brand-identity signals, arriving in the `brand*`, `theme*`, and `shopId*` fields. If your workflow only needs a contact list, toggle `includeAdPixels` and `includeBrandIdentity` off and this Actor behaves like the plain lead sheet. If you need to know what tracking and analytics stack a brand runs, or verify its official brand identity in bulk, those two toggles are what a contact-only scraper can't give you.

***

### 🚀 How to scrape Shopify storefronts with Shopify Merchant Scraper — Ad Pixels & Brand Data

1. Open **Shopify Merchant Scraper — Ad Pixels & Brand Data** on its Apify Store listing and click **Try for free** (or **Run** if you already have it in your Console).
2. Paste storefront URLs into **`targetStores`** — bulk paste, upload a file, or pipe results from another Actor.
3. Set **`maxStorefronts`**, **`requestConcurrency`**, and **`requestPaceSeconds`** to fit the run size and how politely you want to hit each store.
4. Toggle **`includeAdPixels`** / **`includeBrandIdentity`** off if you only need the base lead sheet, and leave **`proxyConfiguration`** on its default — it escalates automatically only if a store starts blocking requests.
5. Click **Start** and read rows from the **Output** tab as JSON, CSV, or Excel, or pull them programmatically with `apify_client`.

#### 📦 How to run multiple storefronts in one job

`targetStores` accepts an array of URLs directly, a file upload, or a piped output from another Actor — there's no separate batch mode to configure. `maxStorefronts` (1–10,000) caps how many of the URLs you supplied are actually processed, and `requestConcurrency` (1–50) controls how many storefronts are worked on in parallel within that run.

***

### ⬇️ Input

`targetStores` accepts a plain list of storefront URLs — no query syntax, no filters beyond the list itself and how many/how fast to process. Every parameter below is optional; the schema declares no required fields, but the run produces zero rows if you leave both URL fields empty.

| Parameter | Required | Type | Constraints | Description |
| --- | --- | --- | --- | --- |
| `targetStores` | No | array | `editor: stringList` | Shopify storefront URLs to pull ad-pixel and brand-identity data from (e.g. `https://kyliecosmetics.com/`). Bulk paste, upload a list, or pipe from another actor. |
| `startUrls` | No | array | `editor: stringList` | Base-actor-compatible alias for `targetStores`. A plain `startUrls` array from an older integration still works here — leave empty and use `targetStores` instead. |
| `maxStorefronts` | No | integer | min `1`, max `10000`, prefill `100` | Hard cap on how many storefronts from the list will be processed. Use this to keep small test runs cheap. |
| `maxItems` | No | integer | min `1`, max `10000`, default `100` | Base-actor-compatible alias for `maxStorefronts`. |
| `requestConcurrency` | No | integer | min `1`, max `50`, prefill `10` | How many storefronts to process in parallel. |
| `concurrency` | No | integer | min `1`, max `50`, default `10` | Base-actor-compatible alias for `requestConcurrency`. |
| `requestPaceSeconds` | No | number | min `0`, max `10`, prefill `0.5` | Polite delay inserted between requests made to the same storefront. |
| `requestDelay` | No | number | min `0`, max `10`, default `0.5` | Base-actor-compatible alias for `requestPaceSeconds`. |
| `includeAdPixels` | No | boolean | default `true` | Parse the storefront's homepage-embedded pixel registry (ad/analytics tracking tags) into `adPixels[]` — raw client IDs, pixel type, and privacy purposes only. Never a guessed vendor name. |
| `includeBrandIdentity` | No | boolean | default `true` | Extract Organization structured data (logo, official social/press links), the storefront's real theme identity, and a shop-ID integrity cross-check into the `brand*` / `theme*` / `shopId*` fields. |
| `proxyConfiguration` | No | object | `editor: proxy`, default `{"useApifyProxy": false}` | Use Apify Proxy, custom proxy URLs, or no proxy. |

For each alias pair (`targetStores`/`startUrls`, `maxStorefronts`/`maxItems`, `requestConcurrency`/`concurrency`, `requestPaceSeconds`/`requestDelay`), the first field in the pair wins whenever both are supplied.

#### Example input

```json
{
  "targetStores": [
    "https://kyliecosmetics.com/",
    "https://www.allbirds.com/",
    "https://www.gymshark.com/"
  ],
  "maxStorefronts": 100,
  "requestConcurrency": 10,
  "requestPaceSeconds": 0.5,
  "includeAdPixels": true,
  "includeBrandIdentity": true,
  "proxyConfiguration": { "useApifyProxy": false }
}
```

**Common pitfall:** `maxStorefronts` only trims the list you supplied — it does not discover additional stores. If you set `maxStorefronts` to 500 but only give 20 URLs, the run still produces 20 rows, not 500. Also, URLs without a scheme are auto-prefixed with `https://`, and duplicate URLs in the list are silently deduplicated before processing.

***

### ⬆️ Output

Every run's results land in the Actor's Apify dataset in the same 46-key schema on every row, exportable as JSON, CSV, Excel, or XML from the Output tab, or pulled programmatically via the API or `apify_client`. Fields that couldn't be found are returned as `null` (or an empty array for list fields) rather than omitted — the schema shape never changes between rows.

⚠️ Every processed storefront is charged under the `row_result` event, including unreachable, password-protected, or no-catalogue stores that return a mostly-null row — there's no separate uncharged error/accounting event, so `maxStorefronts` doubles as a cost cap.

#### 📋 Scraped results

```json
[
  {
    "storeName": "Kylie Cosmetics by Kylie Jenner | Kylie Jenner Fragrances | Kylie Skin",
    "merchantName": "Kylie Cosmetics",
    "domain": "kyliecosmetics.com",
    "url": "https://kyliecosmetics.com/",
    "storefrontStatus": "open",
    "email": "customerservice@kyliecosmetics.com",
    "phone": "1-877-916-6128",
    "facebook": "https://www.facebook.com/KylieCosmetics/",
    "instagram": "https://www.instagram.com/kyliecosmetics/",
    "twitter": "https://twitter.com/kyliecosmetics",
    "tiktok": null,
    "youtube": null,
    "pinterest": null,
    "linkedin": null,
    "socialPlatformCount": 3,
    "hasEmail": true,
    "hasPhone": true,
    "leadQuality": "high",
    "productCount": 238,
    "publishedCollectionsCount": 226,
    "currency": "USD",
    "moneyFormat": "${{amount}}",
    "myshopifyDomain": "kylie-cosmetics.myshopify.com",
    "merchantDescription": "Shop Kylie Cosmetics by Kylie Jenner.",
    "merchantCity": "Calabasas",
    "merchantProvince": "CA",
    "shipsToCountries": ["US", "CA", "GB"],
    "acceptedCardBrands": ["visa", "mastercard", "american_express"],
    "offersShopPayInstallments": true,
    "themeName": "KYLIE",
    "themeVersion": "12.1.0",
    "themeRole": "main",
    "installedApps": ["klaviyo", "yotpo"],
    "installedAppsCount": 2,
    "themeAppExtensions": ["klaviyo"],
    "appProxyHandles": ["yotpo"],
    "appCount": 2,
    "adPixelCount": 2,
    "adPixels": [
      { "pixelId": "gid://shopify/WebPixel/123", "pixelType": "APP", "apiClientId": 580111, "privacyPurposes": ["ANALYTICS", "MARKETING"], "configHost": "webhooks.fivetran.com" },
      { "pixelId": "gid://shopify/WebPixel/456", "pixelType": "CUSTOM", "apiClientId": null, "privacyPurposes": ["ANALYTICS"], "configHost": null }
    ],
    "brandLogoUrl": "https://cdn.shopify.com/s/files/1/0554/9812/files/logo.png",
    "brandSameAs": ["https://www.instagram.com/kyliecosmetics/", "https://www.facebook.com/KylieCosmetics/"],
    "brandTelephone": null,
    "brandAreaServed": "US",
    "shopId": 12345678,
    "shopIdMatch": true,
    "scrapedAt": "2026-08-15T10:03:57.462Z"
  },
  {
    "storeName": "Allbirds | Sustainable Shoes & Apparel",
    "merchantName": "Allbirds, Inc.",
    "domain": "www.allbirds.com",
    "url": "https://www.allbirds.com/",
    "storefrontStatus": "open",
    "email": "help@allbirds.com",
    "phone": null,
    "facebook": "https://www.facebook.com/allbirds/",
    "instagram": "https://www.instagram.com/allbirds/",
    "twitter": null,
    "tiktok": "https://www.tiktok.com/@allbirds",
    "youtube": null,
    "pinterest": null,
    "linkedin": null,
    "socialPlatformCount": 3,
    "hasEmail": true,
    "hasPhone": false,
    "leadQuality": "medium",
    "productCount": 84,
    "publishedCollectionsCount": 41,
    "currency": "USD",
    "moneyFormat": "${{amount}}",
    "myshopifyDomain": "allbirds.myshopify.com",
    "merchantDescription": null,
    "merchantCity": null,
    "merchantProvince": null,
    "shipsToCountries": ["US"],
    "acceptedCardBrands": ["visa", "mastercard", "amex", "discover"],
    "offersShopPayInstallments": true,
    "themeName": "Allbirds",
    "themeVersion": "4.3.2",
    "themeRole": "main",
    "installedApps": ["gorgias"],
    "installedAppsCount": 1,
    "themeAppExtensions": [],
    "appProxyHandles": ["gorgias"],
    "appCount": 1,
    "adPixelCount": 1,
    "adPixels": [
      { "pixelId": "gid://shopify/WebPixel/789", "pixelType": "APP", "apiClientId": 165719, "privacyPurposes": ["ANALYTICS"], "configHost": "connect.facebook.net" }
    ],
    "brandLogoUrl": null,
    "brandSameAs": [],
    "brandTelephone": null,
    "brandAreaServed": null,
    "shopId": 21398765,
    "shopIdMatch": null,
    "scrapedAt": "2026-08-15T10:04:12.108Z"
  },
  {
    "storeName": null,
    "merchantName": null,
    "domain": "example-locked-store.myshopify.com",
    "url": "https://example-locked-store.myshopify.com/",
    "storefrontStatus": "password_protected",
    "email": null,
    "phone": null,
    "facebook": null,
    "instagram": null,
    "twitter": null,
    "tiktok": null,
    "youtube": null,
    "pinterest": null,
    "linkedin": null,
    "socialPlatformCount": 0,
    "hasEmail": false,
    "hasPhone": false,
    "leadQuality": "unqualified",
    "productCount": null,
    "publishedCollectionsCount": null,
    "currency": null,
    "moneyFormat": null,
    "myshopifyDomain": null,
    "merchantDescription": null,
    "merchantCity": null,
    "merchantProvince": null,
    "shipsToCountries": [],
    "acceptedCardBrands": [],
    "offersShopPayInstallments": null,
    "themeName": null,
    "themeVersion": null,
    "themeRole": null,
    "installedApps": [],
    "installedAppsCount": 0,
    "themeAppExtensions": [],
    "appProxyHandles": [],
    "appCount": 0,
    "adPixelCount": 0,
    "adPixels": [],
    "brandLogoUrl": null,
    "brandSameAs": [],
    "brandTelephone": null,
    "brandAreaServed": null,
    "shopId": null,
    "shopIdMatch": null,
    "scrapedAt": "2026-08-15T10:04:30.775Z"
  }
]
```

***

### 🎯 How can I use the data extracted with Shopify Merchant Scraper — Ad Pixels & Brand Data?

- 📡 **Ad-tech and martech researchers:** compare `adPixels[]` across a niche's storefronts to see which analytics and marketing platforms brands actually load, not what their marketing pages claim.
- 🎯 **B2B prospecting and sales teams:** filter rows on `hasEmail`, `hasPhone`, and `leadQuality` to build an outreach list of storefronts with confirmed contact channels.
- 🤖 **AI engineers and LLM developers:** call the Actor from an agent, pass the returned JSON straight into a prompt as grounding context, and let the model reason over verified merchant and tech-stack data instead of guessing.
- 📊 **Market researchers and competitive-intelligence teams:** join `themeName`, `installedApps`, and `productCount` across a competitor set to map catalogue size and tech-stack adoption in one pass.

***

### 📈 How do you monitor ad-pixel and brand-identity changes over time?

Tracking a brand's marketing stack over time means re-running the same storefront list on a schedule and diffing the fields that actually change: `adPixels[]` and `adPixelCount` when a store adds or drops a tracking pixel, `installedApps[]` / `installedAppsCount` when it installs or removes an app, and `themeName` / `themeVersion` when it redesigns its storefront. `brandSameAs[]` and `brandLogoUrl` shift far less often, but are worth including in the diff for brand-identity audits.

The practical loop: run the Actor on a fixed list of storefronts, store the dataset from that run, run it again on the same list later, and compare row-by-row on `domain`. A new entry in `adPixels[]` with a `configHost` you haven't seen before, or a changed `themeVersion`, is your alert signal — everything else in the row acts as the join key and context for that change.

This Actor has no built-in diffing or scheduling of its own. To automate the loop, use Apify's **Schedule** feature (Console → Schedules) to run it on a cron interval against the same `targetStores` list, then compare each run's dataset to the previous one in your own pipeline or downstream tool.

***

### 🔌 Integrate Shopify Merchant Scraper — Ad Pixels & Brand Data and automate your workflow

Shopify Merchant Scraper — Ad Pixels & Brand Data works with any language or tool that can send an HTTP request, and with the official `apify_client` SDKs for Python and JavaScript.

#### 🐍 REST API with Python

```python
import requests

ACTOR_ID = "<your-actor-id-or-username~actor-name>"
TOKEN = "<APIFY_API_TOKEN>"

resp = requests.post(
    f"https://api.apify.com/v2/acts/%7BACTOR_ID%7D/run-sync-get-dataset-items",
    params={"token": TOKEN},
    json={
        "targetStores": ["https://kyliecosmetics.com/"],
        "maxStorefronts": 50,
        "includeAdPixels": True,
        "includeBrandIdentity": True,
    },
)
rows = resp.json()
for row in rows:
    print(row["domain"], row["storefrontStatus"], row["adPixelCount"])
```

#### ⏰ Scheduled monitoring and delivery

Use Apify's **Schedule** feature in the Console to run this Actor on a recurring cron interval against a fixed `targetStores` list without writing any code. Combine it with Apify's run/dataset webhooks to notify your own system when a scheduled run finishes, or pull the latest dataset items on demand via the API or `apify_client`.

***

### ⚖️ Is it legal to scrape Shopify storefronts?

Yes — this Actor collects only data a storefront already publishes publicly: homepage HTML, the `/meta.json` endpoint, embedded JSON-LD, and the pixel registry the store itself loads for every visitor. Nothing requires authentication or bypasses access controls; password-protected stores are flagged as `password_protected`, not bypassed.

The data returned here is business and product data — merchant identity, catalogue metrics, and a store's own marketing/tech-stack configuration — not personal profiles of individuals, so GDPR's personal-data framework generally does not attach to it. The applicable considerations are each storefront's own terms of service and, in some jurisdictions, database-rights protections over the compiled data. Where a row includes a business contact email or phone number, using it for outreach may still fall under regional anti-spam or marketing-consent rules (e.g. CAN-SPAM, CASL) independent of scraping legality. Consult your legal team before bulk storage or commercial use of the output.

***

### ❓ Frequently asked questions

#### Does this Actor require a Shopify account or API credentials?

No. It reads homepage HTML and public JSON endpoints (`/meta.json`, the embedded pixel registry, JSON-LD) that any visitor's browser already loads — no login, app installation, or API token for the target store is needed.

#### How many storefronts can I process in one run?

`maxStorefronts` (or its alias `maxItems`) accepts 1–10,000, defaulting to 100. That cap only trims the list you supply — it never expands your output beyond the number of URLs you provided in `targetStores`/`startUrls`.

#### Does the ad-pixel registry tell me which vendor each pixel belongs to?

No — and it deliberately doesn't guess. There's no public mapping from a pixel's `apiClientId` to a vendor brand name, so this Actor ships the raw `pixelId`, `pixelType`, `apiClientId`, `privacyPurposes[]`, and any real hostname (`configHost`) it can extract from the pixel's own configuration, rather than fabricating a vendor label.

#### How often are the brand-identity fields populated?

`brandLogoUrl`, `brandSameAs`, `brandTelephone`, and `brandAreaServed` only populate when a storefront publishes `Organization`-typed JSON-LD structured data. A `null`/empty result on these fields means the store didn't publish that data — not that the Actor failed to find it.

#### What happens on a closed or password-protected store?

`storefrontStatus` returns `password_protected`, `unreachable`, or `no_public_catalogue` instead of a silent, all-null row, so you can filter these out downstream without guessing why a row is empty.

#### Are all processed storefronts charged, even ones that return no data?

Yes. Every storefront the Actor attempts is pushed to the dataset and charged under the `row_result` event, including unreachable or password-protected stores — there's no separate uncharged error event. Set `maxStorefronts` deliberately if you're testing against an unfamiliar list.

#### How do I monitor a brand's ad-tech and theme changes over time?

Run the Actor on the same `targetStores` list on a recurring Apify Schedule, and diff each new run's `adPixels[]`, `installedApps[]`, and `themeVersion` against the previous run's dataset. A new `configHost` or a version bump is your change signal.

#### Does this Actor work with Claude, ChatGPT, and AI agent frameworks?

It isn't published as an MCP server. It's callable as a standard HTTP endpoint through the Apify API or `apify_client`, so any agent framework that can make an HTTP request can call it, pass a query, and ground its next answer on the returned JSON.

#### Can I run this without managing proxies myself?

Yes. By default the Actor makes direct requests with no proxy. If a storefront starts returning blocked responses (status codes like 403, 429, or 503, or a connection failure), it automatically escalates to Apify's datacenter proxy group and then to residential proxies, staying on residential for the rest of that request's retries once escalated — you only need to enable Apify Proxy in `proxyConfiguration` if you want it available from the start.

***

### 💬 Your feedback

Found a bug, or need a field this Actor doesn't extract yet? Use the Issues tab on this Actor's Apify Store page, or message the developer directly through Apify Console — that's the fastest way to reach the Scrapier team and get it looked at.

# Actor input Schema

## `targetStores` (type: `array`):

Shopify storefront URLs to pull ad-pixel and brand-identity data from (e.g. `https://kyliecosmetics.com/`). Bulk paste, upload a list, or pipe from another actor.

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

Base-actor-compatible alias for `targetStores`. A plain `startUrls` array from an older integration still works here — leave empty and use `targetStores` above instead.

## `maxStorefronts` (type: `integer`):

Hard cap on how many storefronts from the list will be processed. Use this to keep small test runs cheap.

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

Base-actor-compatible alias for `maxStorefronts`.

## `requestConcurrency` (type: `integer`):

How many storefronts to process in parallel.

## `concurrency` (type: `integer`):

Base-actor-compatible alias for `requestConcurrency`.

## `requestPaceSeconds` (type: `number`):

Polite delay inserted between requests made to the same storefront.

## `requestDelay` (type: `number`):

Base-actor-compatible alias for `requestPaceSeconds`.

## `includeAdPixels` (type: `boolean`):

Parse the storefront's homepage-embedded pixel registry (ad/analytics tracking tags) into `adPixels[]` — raw client IDs, pixel type, and privacy purposes only. Never a guessed vendor name.

## `includeBrandIdentity` (type: `boolean`):

Extract Organization structured data (logo, official social/press links), the storefront's real theme identity, and a shop-id integrity cross-check into the `brand*` / `theme*` / `shopId*` fields.

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

Use Apify Proxy, custom proxy URLs, or no proxy.

## Actor input object example

```json
{
  "targetStores": [
    "https://kyliecosmetics.com/"
  ],
  "maxStorefronts": 100,
  "maxItems": 100,
  "requestConcurrency": 10,
  "concurrency": 10,
  "requestPaceSeconds": 0.5,
  "requestDelay": 0.5,
  "includeAdPixels": true,
  "includeBrandIdentity": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped items in the Actor's 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 = {
    "targetStores": [
        "https://kyliecosmetics.com/"
    ],
    "maxStorefronts": 100,
    "requestConcurrency": 10,
    "requestPaceSeconds": 0.5,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapier/shopify-merchant-scraper").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 = {
    "targetStores": ["https://kyliecosmetics.com/"],
    "maxStorefronts": 100,
    "requestConcurrency": 10,
    "requestPaceSeconds": 0.5,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapier/shopify-merchant-scraper").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 '{
  "targetStores": [
    "https://kyliecosmetics.com/"
  ],
  "maxStorefronts": 100,
  "requestConcurrency": 10,
  "requestPaceSeconds": 0.5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call scrapier/shopify-merchant-scraper --silent --output-dataset

```

## MCP server setup

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

```

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/zTZvKuJXwbqQXV0ep/builds/L791IaNvp71rhzLqL/openapi.json
