{
  "data": {
    "id": "oBQgMB7gXFOEwAqxQ",
    "actId": "CgKsnMw12cLfPQ8Bk",
    "userId": "EMm4UhWinN76trbOb",
    "startedAt": "2026-08-10T01:44:05.981Z",
    "finishedAt": "2026-08-10T01:44:55.815Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 49783,
      "runTimeSecs": 49.783,
      "computeUnits": 0.055314444444444444,
      "imageSizeBytes": 537528832
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"🧩 Shopify Store Intelligence — Catalog, Apps & Reviews\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"store_urls\": {\n      \"title\": \"Shopify Store URLs\",\n      \"type\": \"array\",\n      \"description\": \"Paste one or more Shopify storefront URLs (for example https://allbirds.com). Works with custom domains and *.myshopify.com URLs.\",\n      \"editor\": \"stringList\",\n      \"prefill\": [\n        \"https://allbirds.com\"\n      ],\n      \"minItems\": 1,\n      \"maxItems\": 100\n    },\n    \"extract_level\": {\n      \"title\": \"Data to Extract\",\n      \"type\": \"string\",\n      \"description\": \"Choose the data depth:\\n- Basic: product catalog only\\n- Standard: product catalog + installed apps\\n- Full: product catalog + installed apps + reviews\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"basic\",\n        \"standard\",\n        \"full\"\n      ],\n      \"enumTitles\": [\n        \"Basic — catalog only\",\n        \"Standard — catalog + apps\",\n        \"Full — catalog + apps + reviews\"\n      ],\n      \"default\": \"standard\"\n    },\n    \"max_products_per_store\": {\n      \"title\": \"Max Products Per Store\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum products to extract per store. Set 0 for unlimited; unlimited runs can take longer and cost more.\",\n      \"editor\": \"number\",\n      \"default\": 250,\n      \"minimum\": 0,\n      \"maximum\": 100000\n    },\n    \"products_collection_filter\": {\n      \"title\": \"Filter by Collection (optional)\",\n      \"type\": \"string\",\n      \"description\": \"Only extract products from one collection handle (for example sneakers or new-arrivals). Leave empty for the full catalog.\",\n      \"sectionCaption\": \"Advanced options\",\n      \"sectionDescription\": \"Optional controls for collection filtering, variant-level rows, review limits, parallel runs, proxy routing, and troubleshooting logs.\",\n      \"editor\": \"textfield\",\n      \"default\": \"\"\n    },\n    \"include_variants\": {\n      \"title\": \"Include Product Variants\",\n      \"type\": \"boolean\",\n      \"description\": \"Output one row per variant (size/color/SKU) instead of one row per product.\",\n      \"default\": false\n    },\n    \"max_reviews_per_product\": {\n      \"title\": \"Max Reviews Per Product (Full only)\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum reviews to extract per product in Full mode.\",\n      \"editor\": \"number\",\n      \"default\": 20,\n      \"minimum\": 1,\n      \"maximum\": 500\n    },\n    \"max_concurrent_stores\": {\n      \"title\": \"Concurrent Stores (multi-store mode)\",\n      \"type\": \"integer\",\n      \"editor\": \"number\",\n      \"description\": \"Number of stores scraped in parallel. Higher = faster but more memory.\",\n      \"default\": 3,\n      \"minimum\": 1,\n      \"maximum\": 10\n    },\n    \"use_residential_proxy\": {\n      \"title\": \"Use Residential Proxy (advanced)\",\n      \"type\": \"boolean\",\n      \"description\": \"Keep off for most stores. Enable only when a store blocks datacenter traffic or is protected by anti-bot tools.\",\n      \"default\": false\n    },\n    \"debug_mode\": {\n      \"title\": \"Debug Mode\",\n      \"type\": \"boolean\",\n      \"description\": \"Enable verbose logs for troubleshooting.\",\n      \"default\": false\n    }\n  },\n  \"required\": [\n    \"store_urls\"\n  ]\n}",
    "readme": "# Shopify Scraper API for Products, Installed Apps & Reviews\n\n> **Turn any Shopify store URL into structured products, installed-app signals, and publicly accessible reviews from supported providers.**\n\nChoose Basic, Standard, or Full mode, process up to 100 stores per run, and keep products, store summaries, detected apps, and reviews in separate datasets.\n\n<a href=\"https://apify.com/kazkn/shopify-scraper-apps-spy?fpr=8fp2od\">\n  <img src=\"https://raw.githubusercontent.com/Boo-n/shopify-scraper-apps-spy/main/assets/shopify-readme-hero-neon.png\" width=\"760\" alt=\"Shopify product pages, app scripts, and review widgets transformed into clean product, store summary, detected app, and review datasets\" />\n</a>\n\n> **Built for B2B SaaS lead generation, DTC competitive intelligence, agency tech audits, and Shopify product research.**\n\n<table style=\"width:100%;max-width:760px;border-collapse:collapse;table-layout:fixed\">\n<tr>\n<td colspan=\"4\" style=\"padding:10px 14px;background:#07110D;border:none;border-radius:4px 4px 0 0\">\n<span style=\"color:#F3F7EF;font-size:14px;font-weight:700;letter-spacing:0.5px\">KazKN · Data intelligence suite</span>\n<span style=\"color:#BED08F;font-size:13px\">&nbsp;&nbsp;&bull;&nbsp;&nbsp;Shopify intelligence, CRE listings, Crexi search, Vinted arbitrage</span>\n</td>\n</tr>\n<tr>\n<td style=\"padding:10px 12px;border:1px solid #B8C7A8;background:#DDF2B3;border-right:none;border-top:none;vertical-align:top;width:25%;overflow-wrap:anywhere\">\n<span><img src=\"https://images.apifyusercontent.com/16bujimlKPVXa0HDiFaYXdv9pr5wzmU5oAlQmqx2wro/rs:fill:76:76/cb:1/aHR0cHM6Ly9hcGlmeS1pbWFnZS11cGxvYWRzLXByb2QuczMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20vRU1tNFVoV2luTjc2dHJiT2ItYWN0b3ItQ2dLc25NdzEyY0xmUFE4QmstOW9xdGthaHMySi1DYXB0dXJlX2RfZV9jcmFuXzIwMjYtMDUtMDFfYV9fMTcuMzcuMDcuanBlZw.webp\" width=\"20\" height=\"20\" style=\"vertical-align:middle;border-radius:4px\" alt=\"Shopify Apps Spy\"> &nbsp;<a href=\"https://apify.com/kazkn/shopify-scraper-apps-spy?fpr=8fp2od\" style=\"color:#2F5B19;text-decoration:none;font-weight:700;font-size:13px\">Shopify Apps Spy</a></span><br>\n<span style=\"color:#2F5B19;font-size:11px;font-weight:600\">&#10148; You are here</span>\n</td>\n<td style=\"background:#F3F7EF;padding:10px 12px;border:1px solid #B8C7A8;border-right:none;border-top:none;vertical-align:top;width:25%;overflow-wrap:anywhere\">\n<span><img src=\"https://images.apifyusercontent.com/p0274x4YcnV6tpq7RySfCrO01PZNvBqu-vPqIVtWQDg/rs:fill:76:76/cb:1/aHR0cHM6Ly9hcGlmeS1pbWFnZS11cGxvYWRzLXByb2QuczMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20vRU1tNFVoV2luTjc2dHJiT2ItYWN0b3ItUm5HTk1jVjN2OEFUaFIzYUEtaTNFM3dkMHhYZC1DaGF0R1BUX0ltYWdlXzZfbWFpXzIwMjZfXzE5XzU5XzI3LnBuZw.webp\" width=\"20\" height=\"20\" style=\"vertical-align:middle;border-radius:4px\" alt=\"CRE Intelligence\"> &nbsp;<a href=\"https://apify.com/kazkn/commercial-real-estate-brokerage-intel?fpr=8fp2od\" style=\"color:#17351D;text-decoration:none;font-weight:700;font-size:13px\">CRE Intelligence</a></span><br>\n<span style=\"color:#5B665B;font-size:11px\">LoopNet + Crexi · broker data</span>\n</td>\n<td style=\"background:#F3F7EF;padding:10px 12px;border:1px solid #B8C7A8;border-right:none;border-top:none;vertical-align:top;width:25%;overflow-wrap:anywhere\">\n<span><img src=\"https://images.apifyusercontent.com/JljmsVBsqZbvcsxNEaKFoAEl3VN9PR5oVoT3KxNbBnE/rs:fill:76:76/cb:1/aHR0cHM6Ly9hcGlmeS1pbWFnZS11cGxvYWRzLXByb2QuczMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20vRU1tNFVoV2luTjc2dHJiT2ItYWN0b3ItT2tRNjRFaDJtY0dqWVZPU24tS2ZuWDVhcXd5ei1DcmV4aV9sb2dvLnBuZw.webp\" width=\"20\" height=\"20\" style=\"vertical-align:middle;border-radius:4px\" alt=\"Crexi Scraper\"> &nbsp;<a href=\"https://apify.com/kazkn/crexi-search-actor?fpr=8fp2od\" style=\"color:#17351D;text-decoration:none;font-weight:700;font-size:13px\">Crexi Scraper</a></span><br>\n<span style=\"color:#5B665B;font-size:11px\">Sale + lease · market or URL</span>\n</td>\n<td style=\"background:#F3F7EF;padding:10px 12px;border:1px solid #B8C7A8;border-top:none;vertical-align:top;width:25%;overflow-wrap:anywhere\">\n<span><img src=\"https://images.apifyusercontent.com/bmk5660gpsQw7MPFxAKCn_GfgjpNZhq9utrqOxrlAaw/rs:fill:76:76/cb:1/aHR0cHM6Ly9hcGlmeS1pbWFnZS11cGxvYWRzLXByb2QuczMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20vRU1tNFVoV2luTjc2dHJiT2ItYWN0b3ItNFVBUHJ3WmIxWE9sa0NKS0stcGhxNm1Db1FvZy12aW50ZWRfbG9nby5wbmc.webp\" width=\"20\" height=\"20\" style=\"vertical-align:middle;border-radius:4px\" alt=\"Vinted Smart Scraper\"> &nbsp;<a href=\"https://apify.com/kazkn/vinted-smart-scraper?fpr=8fp2od\" style=\"color:#17351D;text-decoration:none;font-weight:700;font-size:13px\">Vinted Smart</a></span><br>\n<span style=\"color:#5B665B;font-size:11px\">Cross-market arbitrage</span>\n</td>\n</tr>\n</table>\n\n### Copy to your AI assistant\n\nUse `kazkn/shopify-scraper-apps-spy` on Apify to extract Shopify product catalogs, store summaries, detected storefront apps, and publicly accessible reviews from Yotpo, Judge.me, Stamped, Okendo, or Loox when available. Basic mode returns products, Standard adds app detection, and Full adds supported reviews.\n\n```json\n{\n  \"store_urls\": [\n    \"https://allbirds.com\"\n  ],\n  \"extract_level\": \"standard\",\n  \"max_products_per_store\": 100,\n  \"include_variants\": false,\n  \"max_concurrent_stores\": 1,\n  \"use_residential_proxy\": false\n}\n```\n\n```python\nfrom apify_client import ApifyClient\n\nclient = ApifyClient(\"TOKEN\")\n\nrun_input = {\n    \"store_urls\": [\"https://allbirds.com\"],\n    \"extract_level\": \"standard\",\n    \"max_products_per_store\": 100,\n    \"include_variants\": False,\n    \"max_concurrent_stores\": 1,\n    \"use_residential_proxy\": False,\n}\n\nrun = client.actor(\"kazkn/shopify-scraper-apps-spy\").call(run_input=run_input)\ndefault_dataset_id = run[\"defaultDatasetId\"]\nproducts = client.dataset(default_dataset_id).list_items().items\n\nprint(products)\n```\n\nFull Actor specification: [`GET /v2/acts/kazkn~shopify-scraper-apps-spy/builds/default`](https://api.apify.com/v2/acts/kazkn~shopify-scraper-apps-spy/builds/default) with `Authorization: Bearer TOKEN`.\n\n**Best for:** Shopify lead qualification, competitor catalog research, installed-app intelligence, agency tech-stack audits, public review analysis, CSV exports, and API workflows.\n\n**Explore on Apify:** [Run Actor](https://apify.com/kazkn/shopify-scraper-apps-spy?fpr=8fp2od) · [Input](https://apify.com/kazkn/shopify-scraper-apps-spy/input-schema?fpr=8fp2od) · [Output](https://apify.com/kazkn/shopify-scraper-apps-spy/output-schema?fpr=8fp2od) · [Pricing](https://apify.com/kazkn/shopify-scraper-apps-spy/pricing?fpr=8fp2od) · [API](https://apify.com/kazkn/shopify-scraper-apps-spy/api/python?fpr=8fp2od) · [Examples](https://apify.com/kazkn/shopify-scraper-apps-spy/examples?fpr=8fp2od) · [Support](https://apify.com/kazkn/shopify-scraper-apps-spy/issues/open?fpr=8fp2od)\n\n## 🔍 What does this Shopify scraper do?\n\nBuilt for B2B SaaS lead-gen, DTC competitive intel, and agency tech audits. **No login. No API key. No proxy required for most stores.**\n\nIt turns any Shopify URL into structured intelligence in **under 30 seconds**.\n\nYou simply:\n\n* paste one or more Shopify URLs (custom domain or `*.myshopify.com`)\n* pick an extraction level (Basic, Standard, or Full)\n* click Run\n* export results as JSON, CSV, or Excel\n\nThe actor extracts:\n\n* 🛍️ **Full product catalog** — title, handle, vendor, type, tags, description, prices, variants, images, inventory signals\n* 🧩 **Detected apps** — Klaviyo, Recharge, Yotpo, Judge.me, Privy, Gorgias, Algolia, Okendo, Iterable, Bloomreach, Braze, Smile.io, LoyaltyLion, Weglot, Rebuy, Shogun, PageFly, Hotjar, GTM, Facebook Pixel, TikTok Pixel, and 30+ more\n* ⭐ **Reviews** from Yotpo, Judge.me, Stamped, Okendo, Loox (Full mode)\n* 🏷️ **Store metadata** — name, currency, country, myshopify domain, total products\n\n---\n\n## 🎬 Video Tutorial — See It in Action\n\n[![Shopify Apps Spy + Product Scraper Tutorial](https://img.youtube.com/vi/jxpSVYvZBFw/maxresdefault.jpg)](https://youtu.be/jxpSVYvZBFw)\n\n▶️ Watch the full tutorial — from a Shopify store URL to apps + products + reviews in under 3 minutes.\n\n*(🇫🇷 [Tutoriel français](https://youtu.be/JVnUpT7mjMw) · 🇩🇪 [Auf Deutsch](https://youtu.be/ujS8P1hpMTI) · 🇪🇸 [En español](https://youtu.be/pUiu2Usvpb0))*\n\n---\n\n## 🎯 Who is this Shopify scraper for?\n\n* 🤖 **B2B SaaS founders** targeting Shopify merchants — enrich your outbound list with installed-apps data nobody else has\n* 📊 **DTC operators and analysts** — snapshot competitor catalogs, watch what apps they install or churn, compare regional storefronts\n* 🛍️ **Dropshippers** — explore catalogs, prices, variants, apps, and reviews for product research\n* 🏪 **Agencies** — deliver clean tech-stack audits to your Shopify clients in minutes instead of hours\n\n---\n\n## ⚡ Why use this Shopify scraper?\n\n* 🧩 **Tech stack detection nobody else has** — the unique value vs the 8 other [Shopify scrapers on Apify Store](https://apify.com/store?search=shopify)\n* 🌍 **Multi-region tested** — US, UK, EU, France, Italy, Spain, Germany all validated end-to-end\n* 🚀 **Sub-30s per store** — scrapes 250 products + apps + reviews faster than any browser-based competitor\n* 💰 **Transparent event pricing** — $0.003 per extracted product; start, store, app-analysis, and review events are shown below\n* 🛡️ **Zero browser** — pure HTTP + JSON; the current default run allocation is 4 GB\n* ✅ **Sitemap fallback** — if a store disables [`/products.json`](https://shopify.dev/docs/api/ajax/section/product), the actor automatically reads the sitemap\n* 📦 **Real-time dataset** — products stream into your dataset as they're extracted, no batch wait\n* 🔁 **Batch up to 100 stores** in a single run\n\n> 💡 If you only need products without apps detection, use any commodity [Shopify scraper](https://apify.com/store?search=shopify). If you want the **stack intel**, this is the only actor that gives it to you.\n\n---\n\n## 🚀 How to scrape Shopify products in 3 steps\n\nSetting up 🧩 Shopify Apps Spy + Product Scraper takes **less than a minute**:\n\n1. Open the actor on [Apify Console](https://console.apify.com/actors/kazkn~shopify-scraper-apps-spy) and paste one or more **Shopify store URLs** in the input field (custom domain like `https://allbirds.com` or any `*.myshopify.com`).\n2. Pick an **Extraction Level** that matches what you need:\n   * **Basic** — products only\n   * **Standard** (default) — products + tech stack detection\n   * **Full** — Standard + reviews from [Yotpo](https://www.yotpo.com), [Judge.me](https://judge.me), [Stamped](https://stamped.io), [Okendo](https://www.okendo.com), [Loox](https://loox.io)\n3. Click **Run** — then download your dataset from the **Storage** tab as JSON, CSV, or Excel.\n\n> 💡 **Pro tip:** filter by collection handle to scrape only `/collections/sneakers` or any specific catalog slice instead of the whole store.\n\n### Input example\n\n```json\n{\n  \"store_urls\": [\n    \"https://allbirds.com\",\n    \"https://glossier.com\",\n    \"https://magicspoon.com\"\n  ],\n  \"extract_level\": \"full\",\n  \"max_products_per_store\": 250,\n  \"max_reviews_per_product\": 20,\n  \"max_concurrent_stores\": 3,\n  \"use_residential_proxy\": false\n}\n```\n\n> 💡 Set `use_residential_proxy: true` only when you scrape Cloudflare-protected stores like Tesla Shop or Manscaped. Datacenter proxy is enough for 98% of Shopify stores. Learn more about [Apify Proxy](https://docs.apify.com/platform/proxy).\n\n---\n\n## 🧩 Detected apps catalog (50+ apps, growing)\n\nThe detector spots the entire installed tech stack of any Shopify by running a library of regex patterns on the home page and one product page HTML.\n\n| Category | Detected apps |\n|---|---|\n| ⭐ **Reviews** | [Yotpo](https://www.yotpo.com) · [Judge.me](https://judge.me) · [Loox](https://loox.io) · [Stamped](https://stamped.io) · [Okendo](https://www.okendo.com) · [Reviews.io](https://www.reviews.io) · [Trustpilot](https://www.trustpilot.com) · Shopify legacy reviews |\n| 📧 **Email marketing** | [Klaviyo](https://www.klaviyo.com) · [Mailchimp](https://mailchimp.com) · [Omnisend](https://www.omnisend.com) · [Drip](https://www.drip.com) · **[Iterable](https://iterable.com)** · **[Bloomreach Engagement](https://www.bloomreach.com/en/products/engagement)** · **[Braze](https://www.braze.com)** |\n| 🎯 **Popups / opt-in** | [Privy](https://www.privy.com) · [Justuno](https://www.justuno.com) · [OptiMonk](https://www.optimonk.com) |\n| 🔁 **Subscriptions** | [Recharge](https://rechargepayments.com) · [Bold Subscriptions](https://boldcommerce.com/subscriptions) · [Appstle](https://appstle.com) |\n| 🎁 **Loyalty / rewards** | [Smile.io](https://smile.io) · [Yotpo Loyalty (Swell)](https://www.yotpo.com/platform/loyalty) · [LoyaltyLion](https://loyaltylion.com) |\n| 💬 **Live chat / helpdesk** | [Gorgias](https://www.gorgias.com) · [Tidio](https://www.tidio.com) · [Intercom](https://www.intercom.com) · [Zendesk](https://www.zendesk.com) · [Drift](https://www.drift.com) |\n| 🔎 **Search** | [Algolia](https://www.algolia.com) · [Searchanise](https://searchanise.io) · [Klevu](https://www.klevu.com) |\n| 🎨 **Page builders** | [Shogun](https://getshogun.com) · [PageFly](https://pagefly.io) · [GemPages](https://gempages.net) · [Zipify](https://zipify.com) |\n| 🌐 **Currency / i18n** | Currency Converter Plus · [Weglot](https://www.weglot.com) · [LangShop](https://langshop.app) |\n| 🛒 **Upsell / cart** | [ReConvert](https://www.reconvert.io) · [Bold Upsell](https://boldcommerce.com/upsell-cross-sell) · In Cart Upsell · [Rebuy](https://www.rebuyengine.com) |\n| 📈 **Analytics / pixels** | [Hotjar](https://www.hotjar.com) · [GTM](https://tagmanager.google.com) · [GA4](https://analytics.google.com) · [Facebook Pixel](https://www.facebook.com/business/help/952192354843755) · [TikTok Pixel](https://ads.tiktok.com) · [Pinterest Tag](https://help.pinterest.com/en/business/article/install-the-pinterest-tag) · [Snapchat Pixel](https://businesshelp.snapchat.com/s/article/pixel-direct-implementation) |\n\n> 💡 Don't see an app you care about? The patterns library is open — open an issue with a link to a store using it and I add the regex within 24h.\n\n---\n\n## 💰 Pricing\n\n🧩 Shopify Apps Spy + Product Scraper uses **pay-per-event** pricing. You only pay for what you actually extract:\n\n| Event | When it fires | Price |\n|---|---|---|\n| **Actor start** | Per charged GB at the start of a run | $0.05 / GB |\n| **Store analyzed** | Once per Shopify store with products | $0.01 |\n| **Product extracted** | Per product row pushed | $0.003 |\n| **Apps detected** | Per store at Standard or higher | $0.10 |\n| **Review extracted** | Per review row pushed | $0.001 |\n\n* The current default run allocation is **4 GB**, so actor start can charge **$0.20 per run** before store, product, app, or review events.\n* Apify platform usage is included in the event prices above.\n* Set `Max Total Charge USD` on every run to cap your spend\n\n### 💸 Real cost examples\n\nAll examples use one 4 GB run, therefore include a $0.20 actor-start charge. Apify platform usage is included in the event prices.\n\n* **Basic catalog — 1 store, 250 products:** $0.20 start + $0.01 store + (250 × $0.003 products) = **$0.96** in events.\n* **Standard tech-stack scan — 100 stores, 1 product each:** $0.20 start + (100 × $0.01 stores) + (100 × $0.003 products) + (100 × $0.10 app analysis) = **$11.50** in events.\n* **Full audit — 5 stores, 100 products and 10 reviews per product:** $0.20 start + (5 × $0.01 stores) + (500 × $0.003 products) + (5 × $0.10 app analysis) + (5,000 × $0.001 reviews) = **$7.25** in events.\n\nCompare to [PPSPY](https://www.ppspy.com) ($24/month), [Koala Inspector](https://koalainspector.com) ($9.99/month), [Charm.io](https://charm.io) ($299/month), [Shophunter](https://shophunter.io) ($99/month) — and none of them give you bulk API access or installed-apps data.\n\nLearn more about [Apify pricing](https://apify.com/pricing).\n\n---\n\n## 📦 Output format\n\nThe actor writes each output type to a separate run dataset so Apify tabs and CSV exports stay clean:\n\n* **Products** (default dataset) — one flat row per product, optimized for CSV / Sheets exports\n* **Store summary** — one row per store with metadata, counts, review diagnostics, and run health\n* **Apps detected** — one row per store with the detected Shopify app stack\n* **Reviews** — one row per review in Full mode, empty when no supported review provider is found\n\nExport any section to JSON / CSV / Excel / [Google Sheets](https://apify.com/integrations/google-sheets) / [Airtable](https://apify.com/integrations/airtable) / [Slack](https://apify.com/integrations/slack) / any [Apify integration](https://apify.com/integrations).\n\n> **Reviews note** — if the Reviews dataset is empty, check `reviews_status`, `reviews_products_probed`, and `review_providers_tried` in Store summary. The actor reports why reviews were not emitted instead of filling the Reviews tab with unrelated rows.\n\n### Products dataset\n\nOne row per product (or per variant if `include_variants: true`).\n\n```json\n{\n  \"store_url\": \"https://allbirds.com\",\n  \"store_domain\": \"allbirds.com\",\n  \"store_platform\": \"shopify\",\n  \"scraped_at\": \"2026-04-30T22:15:30Z\",\n  \"extract_level\": \"standard\",\n\n  \"product_id\": 7894123456,\n  \"product_handle\": \"wool-runner-mizzles-natural-white\",\n  \"product_title\": \"Wool Runner Mizzles - Natural White\",\n  \"product_url\": \"https://allbirds.com/products/wool-runner-mizzles-natural-white\",\n  \"product_type\": \"Sneakers\",\n  \"vendor\": \"Allbirds\",\n  \"tags\": \"wool, waterproof\",\n  \"description_text\": \"Plain text description\",\n\n  \"price\": 135.0,\n  \"price_min\": 135.0,\n  \"price_max\": 135.0,\n  \"compare_at_price\": null,\n  \"currency\": \"USD\",\n  \"available\": true,\n  \"available_variant_count\": 8,\n  \"total_variant_count\": 12,\n\n  \"image_urls\": \"https://cdn.shopify.com/...jpg | https://cdn.shopify.com/...jpg\",\n  \"main_image\": \"https://cdn.shopify.com/...jpg\",\n  \"image_count\": 6,\n\n  \"store_name\": \"Allbirds\",\n  \"myshopify_domain\": \"allbirds-2.myshopify.com\",\n  \"low_stock_message\": null,\n  \"in_stock_count\": null,\n  \"viewing_now_widget\": false,\n  \"recent_purchases\": false\n}\n```\n\n> **Variants** — `total_variant_count` and `available_variant_count` are always present. If a product has multiple flavors / sizes / colors (e.g. an energy drink with 5 flavors), set `include_variants: true` in the input to get one row per variant with per-SKU price, availability, and option labels (size, color, flavor, etc.) on top of the per-product summary.\n\n### Store summary dataset\n\nOne row per scraped store with store metadata, product counts, variant counts, and review diagnostics in Full mode.\n\n```json\n{\n  \"store_url\": \"https://magicspoon.com\",\n  \"store_domain\": \"magicspoon.com\",\n  \"myshopify_domain\": \"magicspoon-cereal.myshopify.com\",\n  \"store_name\": \"Magic Spoon\",\n  \"currency\": \"USD\",\n  \"country\": \"US\",\n  \"extract_level\": \"standard\",\n  \"detected_at\": \"2026-04-30T22:15:30Z\",\n  \"reviews_apps\": [\"okendo\"],\n  \"email_marketing\": [\"klaviyo\"],\n  \"subscriptions\": [\"recharge\"],\n  \"page_builder\": [\"shogun\"],\n  \"upsell\": [\"rebuy\"],\n  \"analytics\": [\"google_tag_manager\"],\n  \"all_apps_raw\": [\"okendo\", \"klaviyo\", \"recharge\", \"shogun\", \"rebuy\", \"google_tag_manager\"],\n  \"detected_count\": 6,\n  \"product_count\": 250,\n  \"in_stock_product_count\": 231,\n  \"total_variant_count\": 412,\n  \"row_count_pushed\": 250,\n  \"review_count\": 0,\n  \"reviews_status\": \"no_supported_review_app_detected\",\n  \"reviews_products_probed\": 100,\n  \"review_providers_tried\": [\"yotpo\", \"judgeme\", \"stamped\", \"okendo\", \"loox\"]\n}\n```\n\n### Apps detected dataset\n\nOne row per store in Standard and Full modes.\n\n```json\n{\n  \"store_url\": \"https://magicspoon.com\",\n  \"store_domain\": \"magicspoon.com\",\n  \"store_name\": \"Magic Spoon\",\n  \"myshopify_domain\": \"magicspoon-cereal.myshopify.com\",\n  \"detected_at\": \"2026-04-30T22:15:30Z\",\n  \"reviews_apps\": [\"okendo\"],\n  \"email_marketing\": [\"klaviyo\"],\n  \"subscriptions\": [\"recharge\"],\n  \"analytics\": [\"google_tag_manager\"],\n  \"all_apps_raw\": [\"okendo\", \"klaviyo\", \"recharge\", \"google_tag_manager\"],\n  \"detected_count\": 4\n}\n```\n\n### Reviews dataset\n\nOne row per review with normalized provider-agnostic fields. Emitted only at `extract_level: 'full'`.\n\n```json\n{\n  \"store_domain\": \"glossier.com\",\n  \"product_id\": 9576351138037,\n  \"product_handle\": \"spring-pinks\",\n  \"review_id\": \"yotpo_12345\",\n  \"provider\": \"yotpo\",\n  \"rating\": 5,\n  \"title\": \"Best lip balm ever\",\n  \"body\": \"I wear them every day...\",\n  \"author_name\": \"Sarah J.\",\n  \"author_verified\": true,\n  \"created_at\": \"2026-03-12T08:00:00Z\",\n  \"helpful_count\": 14,\n  \"images\": [\"https://cdn.yotpo.com/...\"]\n}\n```\n\n## 💡 Tips for scraping Shopify efficiently\n\n* 📈 **Batch multiple stores** in a single run — the actor runs them in parallel\n* 🌐 **Multi-region brands** — pass `https://allbirds.com`, `https://allbirds.eu`, `https://allbirds.co.uk` to compare regional storefronts (different stacks, different currencies)\n* 🛡️ **Hit a 403?** Toggle `Use Residential Proxy` for Cloudflare-protected stores ([Apify Proxy docs](https://docs.apify.com/platform/proxy))\n* 🔄 **Schedule weekly runs** with [Apify Scheduler](https://apify.com/schedules) to track product changes and price drops over time\n* 🪝 **Push to Sheets, Slack, Airtable** via [Apify integrations](https://apify.com/integrations) — no glue code needed\n* 🤖 **Run from any AI agent** ([Claude](https://claude.ai), [Cursor](https://cursor.com), [Windsurf](https://codeium.com/windsurf)) using the [Apify MCP server](https://apify.com/apify/actors-mcp-server)\n\n---\n\n## 🌍 Supported Shopify markets and stores\n\n🧩 Shopify Apps Spy + Product Scraper works on **any [Shopify](https://www.shopify.com) storefront worldwide** — custom domain, `*.myshopify.com`, regional subdomains, [Shopify Plus](https://www.shopify.com/plus).\n\n✅ Empirically tested on stores from these countries before publishing:\n\n🇺🇸 United States · 🇬🇧 United Kingdom · 🇪🇺 European Union · 🇫🇷 France · 🇩🇪 Germany · 🇮🇹 Italy · 🇪🇸 Spain\n\nThe endpoint we use ([`/products.json`](https://shopify.dev/docs/api/ajax/section/product)) is a public, version-less Shopify spec that has been stable since 2014. **Country, currency, and language do not affect detection** — the actor handles every Shopify storefront identically.\n\n---\n\n## 🧭 When to use Shopify Apps Spy + Product Scraper vs alternatives\n\nUse **🧩 Shopify Apps Spy + Product Scraper** if you want:\n\n* The only [Apify Shopify scraper](https://apify.com/store?search=shopify) with **installed-apps detection**\n* Catalog + apps + reviews in one run\n* Sub-30s per store, batchable up to 100\n* Pay-per-event with no subscription\n\nUse **[PPSPY](https://www.ppspy.com)** ($24/month) or **[Charm.io](https://charm.io)** ($299/month) if you prefer:\n\n* A polished web UI without API access\n* Flat monthly pricing instead of usage-based\n\nUse **a generic [web scraper](https://apify.com/apify/web-scraper)** if you only need:\n\n* Single-product scraping with custom selectors\n* No Shopify-specific data model\n\n> 💡 Product extraction is billed at $0.003 per row. Total event cost also includes the run-start, store, and optional app-analysis and review events described in the pricing table.\n\n---\n\n## 🔗 Part of the KazKN ecosystem\n\nThis actor is part of the [KazKN](https://apify.com/kazkn) family of scrapers and MCP servers on Apify:\n\n* [🧩 Shopify Apps Spy + Product Scraper](https://apify.com/kazkn/shopify-scraper-apps-spy) — this actor\n* [Vinted Smart Scraper — Cross-Country Price Comparison](https://apify.com/kazkn/vinted-smart-scraper) — full Vinted intelligence across 26 markets\n* [⚡ Vinted Turbo Scraper](https://apify.com/kazkn/vinted-turbo-scraper) — fastest Vinted URL-to-dataset workflow\n* [Vinted MCP Server](https://apify.com/kazkn/vinted-mcp-server) — connect any AI agent ([Claude](https://claude.ai), [Cursor](https://cursor.com), [Windsurf](https://codeium.com/windsurf)) to Vinted data\n* [App Store Scraper for Localization Gaps](https://apify.com/kazkn/apple-app-store-localization-scraper) — find US apps missing French, German, Spanish localizations\n* [GPT Crawler MCP](https://apify.com/kazkn/gpt-crawler-mcp) — turn any website into a clean knowledge file for [ChatGPT](https://chatgpt.com), [Claude](https://claude.ai), or [RAG](https://www.anthropic.com/news/contextual-retrieval) pipelines\n\n---\n\n## ❓ Frequently asked questions\n\n### Is scraping Shopify legal?\n\nYes. The [`/products.json`](https://shopify.dev/docs/api/ajax/section/product) endpoint is a public, official [Shopify](https://www.shopify.com) feature documented by Shopify and consumed by [Google Shopping](https://shopping.google.com) for indexing. The actor does not bypass authentication, does not interact with Shopify's Admin API, and does not collect any buyer personal data. Read more on the [Apify legal blog](https://blog.apify.com/is-web-scraping-legal/).\n\n### Can you scrape Shopify products without an API key?\n\nYes. The actor uses only the public [storefront `/products.json` endpoint](https://shopify.dev/docs/api/ajax/section/product) — no app install, no [OAuth](https://shopify.dev/docs/apps/auth/oauth), no API key.\n\n### Does Shopify have an API?\n\nTwo: the [Admin API](https://shopify.dev/docs/api/admin) (requires OAuth + a per-store install — not used here) and the public [storefront `/products.json` endpoint](https://shopify.dev/docs/api/ajax/section/product) (used here).\n\n### How many products can I extract per store?\n\nUp to 100,000 per store, paginated 250 at a time. Realistic Shopify catalogs have 50–10,000 products.\n\n### What if a store disables `/products.json`?\n\nThe actor automatically falls back to `sitemap_products_1.xml` and pulls each product via `/products/{handle}.json`. About 2 % of [Shopify Plus](https://www.shopify.com/plus) stores disable both — they show up as a graceful \"no products fetched\" record with diagnostic info.\n\n### Does the actor work on Shopify Plus stores?\n\nYes — most of the validation set is [Shopify Plus](https://www.shopify.com/plus) (Allbirds, Magic Spoon, Glossier, Kith, Princess Polly, Pinko, Aspesi, PDPaola).\n\n### How does the apps detector work?\n\nIt fetches the home page HTML and one product page HTML, then runs a library of regex patterns against the combined markup. Detection signals include CDN URLs, JavaScript globals, custom HTML attributes, and inline configuration objects.\n\n### How accurate is the apps detection?\n\nVery high recall on apps that ship visible front-end widgets ([Yotpo](https://www.yotpo.com), [Judge.me](https://judge.me), [Recharge](https://rechargepayments.com), [Klaviyo](https://www.klaviyo.com), [Privy](https://www.privy.com), [Gorgias](https://www.gorgias.com), [Algolia](https://www.algolia.com), [Okendo](https://www.okendo.com)). Lower recall on stores that lazy-load apps via SPAs or use a heavily customized headless theme (e.g. Gymshark, Bombas). The detector reports actual reality — never fabricates apps.\n\n### What review providers are supported?\n\n[Yotpo](https://www.yotpo.com), [Judge.me](https://judge.me), [Stamped](https://stamped.io), [Okendo](https://www.okendo.com), and [Loox](https://loox.io). The crawler picks the first provider the apps detector flagged for the store, or falls through the list until one returns reviews.\n\n### Can I scrape multi-region brands?\n\nYes. Pass each storefront URL separately (e.g. `https://allbirds.com`, `https://allbirds.eu`, `https://allbirds.co.uk`) and the actor reports the local currency in the product and store summary outputs, then treats each storefront as an independent run.\n\n### What about Cloudflare-protected stores?\n\nSome stores ([Tesla Shop](https://shop.tesla.com), [Manscaped](https://www.manscaped.com)) front their storefront with [Cloudflare](https://www.cloudflare.com). Toggle **Use Residential Proxy** on those — the actor routes through [Apify's residential pool](https://apify.com/proxy/residential).\n\n### Can I filter by collection?\n\nYes — set `Filter by Collection` to a collection handle (e.g. `sneakers`, `new-arrivals`) and the actor restricts the scrape to that collection only.\n\n### Can I run this on a schedule?\n\nYes — schedule runs in [Apify Scheduler](https://apify.com/schedules) with any cadence (hourly, daily, weekly). Export to webhook, [Google Sheets](https://apify.com/integrations/google-sheets), [S3](https://apify.com/integrations/aws-s3), [BigQuery](https://apify.com/integrations/google-bigquery), or any [Apify integration](https://apify.com/integrations).\n\n### Is data validated before being pushed?\n\nYes — every product, store summary, and review is validated against a [Zod](https://zod.dev) schema before being pushed. Invalid rows are logged and skipped, never stored.\n\n### What's the typical run time?\n\nStandard level: 5–10 seconds per store on a single product page (250 products), parallelized across stores. 20 stores in standard level finishes in ~45 seconds in cloud benchmarks.\n\n### What's the memory footprint?\n\nThe current default run allocation is 4 GB. Actor start is charged at $0.05 per charged GB, so this allocation can bill $0.20 before result events. See [Apify resource pricing](https://apify.com/pricing).\n\n### What if the URL isn't a Shopify store?\n\nThe actor returns a diagnostic record with `error: \"not_a_shopify_store\"`, the signals it checked, and the HTTP status code. **You are never charged for non-Shopify URLs**.\n\n### How is this different from a generic scraper?\n\nGeneric scrapers like [Apify Web Scraper](https://apify.com/apify/web-scraper) extract one product at a time, do not understand Shopify's variants/collections/inventory model, and can't detect installed apps. This actor is purpose-built for Shopify with regex patterns tuned for the apps detection use case.\n\n### Can I use this from an AI agent?\n\nYes — connect any [MCP-compatible AI agent](https://modelcontextprotocol.io) ([Claude](https://claude.ai), [Cursor](https://cursor.com), [Windsurf](https://codeium.com/windsurf)) via the [Apify MCP server](https://apify.com/apify/actors-mcp-server). The agent can call this actor as a tool.\n\n### Can you add a specific app to the detector?\n\nYes — the patterns library is regex-based. Open an issue with a link to a store using the app and I'll add the regex.\n\n---\n\n## ⚖️ Is it legal to scrape Shopify?\n\nThe [`/products.json`](https://shopify.dev/docs/api/ajax/section/product) endpoint is public and documented by [Shopify](https://www.shopify.com). The actor does not bypass authentication, respects rate limits, and does not collect buyer personal data.\n\nNote that personal data is protected by [GDPR](https://gdpr.eu) in the EU and other regulations worldwide. Do not scrape personal data unless you have a legitimate reason. If unsure, consult your lawyers. Suggested reading: [Is web scraping legal? — Apify Blog](https://blog.apify.com/is-web-scraping-legal/).\n",
    "changelog": "# Changelog\n\nAll notable changes to **Shopify Apps Spy + Product Scraper** are documented here.\nThis project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\nThe Apify build numbers track each deployment to the Apify Store; the version\nnumbers below reflect functional changes visible to users.\n\n---\n\n## [1.2.4] — 2026-06-24\n\n### Fixed\n- Split actor output into separate run-scoped datasets for Products, Store summary, Apps detected, and Reviews so Apify Console sections no longer display unrelated rows.\n- Flattened product rows for cleaner CSV exports: tags and image URLs are now string fields, while nested app/store metadata and raw HTML were removed from the Products dataset.\n- Added focused dataset schemas for each output tab and updated the README output examples.\n\n---\n\n## [1.2.3] — 2026-06-24\n\n### Fixed\n- Improved app detection for Shopify App Extension script URLs, including Shopify Inbox, Smile.io, and Free Gifts widgets.\n- Added a dedicated **Apps detected** dataset view in Apify Console.\n- Added review diagnostics to `store_summary` so Full mode explains whether reviews were found, no supported review app was detected, or providers were tried with no results.\n\n---\n\n## [1.2.2] — 2026-06-24\n\n### Fixed\n- Fixed Apify proxy session IDs for hyphenated Shopify domains such as `kbeauty-cosmetics.com`, which previously stopped the run before scraping began.\n- Automatically infers the collection filter when users paste a Shopify `/collections/...` URL and leave the advanced collection filter empty.\n\n---\n\n## [1.2.1] — 2026-06-24\n\n### Changed\n- Moved optional input controls into a collapsible **Advanced options** section in Apify Console, starting at collection filtering and including variants, review limits, concurrency, proxy, and debug settings.\n\n---\n\n## [1.2.0] — 2026-06-24\n\n### Fixed\n- Hardened store URL validation to reject non-public hosts, private IPs, localhost, ports, and unsupported protocols before any request is made.\n- Preserved extended app categories (`sms_marketing`, `pricing_ab_testing`, `cookie_consent`, `geo_region`) inside product-level `apps_detected` rows.\n- Fixed `store_summary.review_count` so multi-store runs report the current store's reviews instead of the global run counter.\n- Restored `npm test` with focused Node regression tests and refreshed vulnerable transitive dependencies.\n- Removed the unsupported placeholder tier from the public input and output contract. Active modes are now `basic`, `standard`, and `full`.\n- Updated output schema, dataset views, and README wording to match the default-dataset `record_type` output.\n\n---\n\n## [1.1.0] — 2026-05-26\n\n### Fixed (critical — actor was returning only the store domain instead of products)\n- **`Insufficient permissions for the dataset` hung the run when the actor was called via the Apify API or by any user other than the actor owner.** Apify runs every public actor under a `LIMITED_PERMISSIONS` token that can write to the run's default dataset but cannot open globally-named datasets like `apps` or `reviews`. The previous code called `Actor.openDataset('apps')` which hung indefinitely under that token, freezing the run after the first store and leaving the dataset effectively empty (just an error/domain record). The actor now writes every row to the default dataset only, tagged with a `record_type` field so the output stays filterable.\n- Anti-bot block detection (Cloudflare Bot Fight Mode, Akamai, PerimeterX, Datadome) — datacenter IPs sometimes get a 403 from anti-bot, which the previous code misreported as `not_a_shopify_store`. The actor now distinguishes \"blocked by anti-bot\" from \"not a Shopify store\" and auto-retries with a residential proxy on the first block. If the block persists, the diagnostic record now includes an actionable `next_steps` array (whitelist Apify IPs in Cloudflare, disable Bot Fight Mode for `/products.json`, etc.).\n\n### Added\n- `record_type` field on every dataset record (`product` / `apps` / `reviews`). Filter the default dataset by this field instead of opening separate named datasets.\n- `proxy_tier_used` field in diagnostic records (`datacenter` / `residential_fallback`) so users can see exactly which network path succeeded.\n- Anti-bot signal codes in the `signals` array (`anti_bot_cloudflare`, `anti_bot_akamai`, etc.) for downstream filtering.\n- 4-second timeout on every `Actor.charge()` call so a hung billing endpoint can never freeze the run.\n\n### Changed\n- **Output structure.** All records now flow through the default dataset. Existing scripts that read from the `apps` and `reviews` named datasets need to switch to `dataset.filter(r => r.record_type === 'apps')` etc. on the default dataset.\n- **`include_variants: true` now emits one row per variant** (matching the README contract) instead of a nested `variants[]` array on a single product row. Each variant row carries the full product fields plus per-variant `variant_id`, `variant_title`, `sku`, `option1/2/3`, variant-level `price`, `compare_at_price`, `available`, and `main_image` (variant featured image when available). Verified on `aplusnutri.com`: the product \"Équilibre et bien-être au quotidien\" now correctly produces 5 rows (Limonade framboise / Pastèque fraîche / Cerise gourmande / Orange douce / Piña colada).\n- **Revenue placeholder row** (emitted at `extract_level: 'pro'`) moved from the named `revenue` dataset to the default dataset with `record_type: 'revenue'`. Same LIMITED_PERMISSIONS rationale.\n\n### Added (apps detection coverage — major expansion)\n- **30+ new detectors** across 4 new categories:\n  - **Analytics**: Microsoft Clarity, Segment, Mixpanel\n  - **Pricing / AB testing** (new category): Intelligems, Visually.io, Dexter\n  - **SMS marketing** (new category): Attentive, Postscript, Emotive\n  - **Bundles / Upsell**: Kaching Bundles, Bundler, FastBundle\n  - **Geo / Region** (new category): Boostymark Region Block, Shopify Geolocation\n  - **Cookie consent** (new category): Axeptio, Iubenda, Cookiebot, OneTrust, Termly, Shopify Privacy Banner\n  - **Live chat extended**: Shopify Inbox, Re:amaze, Crisp, Freshchat\n  - **Currency / i18n extended**: Multi Currency Converter, Bagging\n- Verified on `aplusnutri.com`: detection went from 1 app (klaviyo only) to 6 apps across 6 categories — Klaviyo, Microsoft Clarity, Intelligems, Kaching Bundles, Boostymark Region Block, Shopify Privacy Banner.\n\n### Added (Apify Console UI)\n- **4 dedicated dataset views** for clean per-type rendering in Apify Console:\n  - **All records** — universal columns with `record_type` first for sort/filter\n  - **📦 Products** — image, title, variant_title, sku, price, currency, availability, vendor, link\n  - **🧩 Apps detected** — one row per store, columns per category (email/SMS/reviews/subs/popups/loyalty/chat/upsell/search/analytics/pricing_ab/consent/geo/page_builder/i18n)\n  - **⭐ Reviews** — store, product, provider, rating, body, author, date\n  - **💰 Revenue** — placeholder until the model lands\n\n---\n\n## [1.0.2] — 2026-05-05\n\n### Added\n- 4-language video tutorials (EN / FR / DE / ES) embedded in README and on Apify Store\n- `examples/` folder with 5 runnable code samples covering ICP qualification, app market-share research, cold-outreach personalization, cURL quickstart, and Zapier/Make.com integration\n- README badges (Apify Run, MIT License, YouTube Tutorial)\n- \"Video Tutorial\" section in README + Apify Store, mirroring the format used on the Vinted Turbo Scraper actor\n\n### Changed\n- Renamed actor from \"Shopify Product Scraper - Apps Spy + Reviews\" to **\"Shopify Apps Spy + Product Scraper\"** to lead with the differentiated apps-detection feature while keeping the product-scraper SEO term\n- Aligned `.actor/actor.json` title and `.actor/README.md` with the new name\n\n---\n\n## [1.0.0] — 2026-04-30\n\n### Added\n- Apps detection across 150+ Shopify apps (email/SMS, reviews, subscriptions, popups, search, loyalty, ad pixels)\n- Product catalog extraction via the official `/products.json` endpoint\n- Reviews extraction at `extract_level: full` for Yotpo, Judge.me, Stamped, Okendo, Loox, Junip, Reviews.io, Rebuy\n- Pay-per-event pricing: $0.003/store, $0.0005/product, $0.001/apps_detected, $0.0003/review\n- 4 extract levels: `basic`, `standard`, `full`, `pro`\n- JSON / CSV / Excel / RSS export\n- Free $5 monthly credit covers ≈1,500 stores at standard tier\n\n### Performance\n- Polite concurrency of 5 simultaneous requests scans 1,000 stores in ~25 minutes\n- No proxy required for the vast majority of stores\n- No login, no API key, no headless browser\n\n---\n\n## Roadmap\n\n- **MCP server mode** — query the actor directly from Claude desktop / Cursor (in line with the existing [Vinted MCP Server](https://apify.com/kazkn/vinted-mcp-server) and [GPT Crawler MCP](https://apify.com/kazkn/gpt-crawler-mcp))\n- **Theme detection** — useful for agency outbound (Shopify 2.0 vs vintage themes vs custom)\n- **More detectors** — every \"this is missing\" issue gets a 15-minute add. Open an issue to request one.\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "shopify-scraper-apps-spy",
      "title": "🧩 Shopify Apps Spy + Product Scraper",
      "version": "1.2",
      "buildTag": "latest",
      "minMemoryMbytes": 256,
      "maxMemoryMbytes": 1024,
      "environmentVariables": {
        "NODE_OPTIONS": "--max-old-space-size=768"
      },
      "dockerfile": "../Dockerfile",
      "readme": "# Shopify Scraper API for Products, Installed Apps & Reviews\n\n> **Turn any Shopify store URL into structured products, installed-app signals, and publicly accessible reviews from supported providers.**\n\nChoose Basic, Standard, or Full mode, process up to 100 stores per run, and keep products, store summaries, detected apps, and reviews in separate datasets.\n\n<a href=\"https://apify.com/kazkn/shopify-scraper-apps-spy?fpr=8fp2od\">\n  <img src=\"https://raw.githubusercontent.com/Boo-n/shopify-scraper-apps-spy/main/assets/shopify-readme-hero-neon.png\" width=\"760\" alt=\"Shopify product pages, app scripts, and review widgets transformed into clean product, store summary, detected app, and review datasets\" />\n</a>\n\n> **Built for B2B SaaS lead generation, DTC competitive intelligence, agency tech audits, and Shopify product research.**\n\n<table style=\"width:100%;max-width:760px;border-collapse:collapse;table-layout:fixed\">\n<tr>\n<td colspan=\"4\" style=\"padding:10px 14px;background:#07110D;border:none;border-radius:4px 4px 0 0\">\n<span style=\"color:#F3F7EF;font-size:14px;font-weight:700;letter-spacing:0.5px\">KazKN · Data intelligence suite</span>\n<span style=\"color:#BED08F;font-size:13px\">&nbsp;&nbsp;&bull;&nbsp;&nbsp;Shopify intelligence, CRE listings, Crexi search, Vinted arbitrage</span>\n</td>\n</tr>\n<tr>\n<td style=\"padding:10px 12px;border:1px solid #B8C7A8;background:#DDF2B3;border-right:none;border-top:none;vertical-align:top;width:25%;overflow-wrap:anywhere\">\n<span><img src=\"https://images.apifyusercontent.com/16bujimlKPVXa0HDiFaYXdv9pr5wzmU5oAlQmqx2wro/rs:fill:76:76/cb:1/aHR0cHM6Ly9hcGlmeS1pbWFnZS11cGxvYWRzLXByb2QuczMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20vRU1tNFVoV2luTjc2dHJiT2ItYWN0b3ItQ2dLc25NdzEyY0xmUFE4QmstOW9xdGthaHMySi1DYXB0dXJlX2RfZV9jcmFuXzIwMjYtMDUtMDFfYV9fMTcuMzcuMDcuanBlZw.webp\" width=\"20\" height=\"20\" style=\"vertical-align:middle;border-radius:4px\" alt=\"Shopify Apps Spy\"> &nbsp;<a href=\"https://apify.com/kazkn/shopify-scraper-apps-spy?fpr=8fp2od\" style=\"color:#2F5B19;text-decoration:none;font-weight:700;font-size:13px\">Shopify Apps Spy</a></span><br>\n<span style=\"color:#2F5B19;font-size:11px;font-weight:600\">&#10148; You are here</span>\n</td>\n<td style=\"background:#F3F7EF;padding:10px 12px;border:1px solid #B8C7A8;border-right:none;border-top:none;vertical-align:top;width:25%;overflow-wrap:anywhere\">\n<span><img src=\"https://images.apifyusercontent.com/p0274x4YcnV6tpq7RySfCrO01PZNvBqu-vPqIVtWQDg/rs:fill:76:76/cb:1/aHR0cHM6Ly9hcGlmeS1pbWFnZS11cGxvYWRzLXByb2QuczMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20vRU1tNFVoV2luTjc2dHJiT2ItYWN0b3ItUm5HTk1jVjN2OEFUaFIzYUEtaTNFM3dkMHhYZC1DaGF0R1BUX0ltYWdlXzZfbWFpXzIwMjZfXzE5XzU5XzI3LnBuZw.webp\" width=\"20\" height=\"20\" style=\"vertical-align:middle;border-radius:4px\" alt=\"CRE Intelligence\"> &nbsp;<a href=\"https://apify.com/kazkn/commercial-real-estate-brokerage-intel?fpr=8fp2od\" style=\"color:#17351D;text-decoration:none;font-weight:700;font-size:13px\">CRE Intelligence</a></span><br>\n<span style=\"color:#5B665B;font-size:11px\">LoopNet + Crexi · broker data</span>\n</td>\n<td style=\"background:#F3F7EF;padding:10px 12px;border:1px solid #B8C7A8;border-right:none;border-top:none;vertical-align:top;width:25%;overflow-wrap:anywhere\">\n<span><img src=\"https://images.apifyusercontent.com/JljmsVBsqZbvcsxNEaKFoAEl3VN9PR5oVoT3KxNbBnE/rs:fill:76:76/cb:1/aHR0cHM6Ly9hcGlmeS1pbWFnZS11cGxvYWRzLXByb2QuczMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20vRU1tNFVoV2luTjc2dHJiT2ItYWN0b3ItT2tRNjRFaDJtY0dqWVZPU24tS2ZuWDVhcXd5ei1DcmV4aV9sb2dvLnBuZw.webp\" width=\"20\" height=\"20\" style=\"vertical-align:middle;border-radius:4px\" alt=\"Crexi Scraper\"> &nbsp;<a href=\"https://apify.com/kazkn/crexi-search-actor?fpr=8fp2od\" style=\"color:#17351D;text-decoration:none;font-weight:700;font-size:13px\">Crexi Scraper</a></span><br>\n<span style=\"color:#5B665B;font-size:11px\">Sale + lease · market or URL</span>\n</td>\n<td style=\"background:#F3F7EF;padding:10px 12px;border:1px solid #B8C7A8;border-top:none;vertical-align:top;width:25%;overflow-wrap:anywhere\">\n<span><img src=\"https://images.apifyusercontent.com/bmk5660gpsQw7MPFxAKCn_GfgjpNZhq9utrqOxrlAaw/rs:fill:76:76/cb:1/aHR0cHM6Ly9hcGlmeS1pbWFnZS11cGxvYWRzLXByb2QuczMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20vRU1tNFVoV2luTjc2dHJiT2ItYWN0b3ItNFVBUHJ3WmIxWE9sa0NKS0stcGhxNm1Db1FvZy12aW50ZWRfbG9nby5wbmc.webp\" width=\"20\" height=\"20\" style=\"vertical-align:middle;border-radius:4px\" alt=\"Vinted Smart Scraper\"> &nbsp;<a href=\"https://apify.com/kazkn/vinted-smart-scraper?fpr=8fp2od\" style=\"color:#17351D;text-decoration:none;font-weight:700;font-size:13px\">Vinted Smart</a></span><br>\n<span style=\"color:#5B665B;font-size:11px\">Cross-market arbitrage</span>\n</td>\n</tr>\n</table>\n\n### Copy to your AI assistant\n\nUse `kazkn/shopify-scraper-apps-spy` on Apify to extract Shopify product catalogs, store summaries, detected storefront apps, and publicly accessible reviews from Yotpo, Judge.me, Stamped, Okendo, or Loox when available. Basic mode returns products, Standard adds app detection, and Full adds supported reviews.\n\n```json\n{\n  \"store_urls\": [\n    \"https://allbirds.com\"\n  ],\n  \"extract_level\": \"standard\",\n  \"max_products_per_store\": 100,\n  \"include_variants\": false,\n  \"max_concurrent_stores\": 1,\n  \"use_residential_proxy\": false\n}\n```\n\n```python\nfrom apify_client import ApifyClient\n\nclient = ApifyClient(\"TOKEN\")\n\nrun_input = {\n    \"store_urls\": [\"https://allbirds.com\"],\n    \"extract_level\": \"standard\",\n    \"max_products_per_store\": 100,\n    \"include_variants\": False,\n    \"max_concurrent_stores\": 1,\n    \"use_residential_proxy\": False,\n}\n\nrun = client.actor(\"kazkn/shopify-scraper-apps-spy\").call(run_input=run_input)\ndefault_dataset_id = run[\"defaultDatasetId\"]\nproducts = client.dataset(default_dataset_id).list_items().items\n\nprint(products)\n```\n\nFull Actor specification: [`GET /v2/acts/kazkn~shopify-scraper-apps-spy/builds/default`](https://api.apify.com/v2/acts/kazkn~shopify-scraper-apps-spy/builds/default) with `Authorization: Bearer TOKEN`.\n\n**Best for:** Shopify lead qualification, competitor catalog research, installed-app intelligence, agency tech-stack audits, public review analysis, CSV exports, and API workflows.\n\n**Explore on Apify:** [Run Actor](https://apify.com/kazkn/shopify-scraper-apps-spy?fpr=8fp2od) · [Input](https://apify.com/kazkn/shopify-scraper-apps-spy/input-schema?fpr=8fp2od) · [Output](https://apify.com/kazkn/shopify-scraper-apps-spy/output-schema?fpr=8fp2od) · [Pricing](https://apify.com/kazkn/shopify-scraper-apps-spy/pricing?fpr=8fp2od) · [API](https://apify.com/kazkn/shopify-scraper-apps-spy/api/python?fpr=8fp2od) · [Examples](https://apify.com/kazkn/shopify-scraper-apps-spy/examples?fpr=8fp2od) · [Support](https://apify.com/kazkn/shopify-scraper-apps-spy/issues/open?fpr=8fp2od)\n\n## 🔍 What does this Shopify scraper do?\n\nBuilt for B2B SaaS lead-gen, DTC competitive intel, and agency tech audits. **No login. No API key. No proxy required for most stores.**\n\nIt turns any Shopify URL into structured intelligence in **under 30 seconds**.\n\nYou simply:\n\n* paste one or more Shopify URLs (custom domain or `*.myshopify.com`)\n* pick an extraction level (Basic, Standard, or Full)\n* click Run\n* export results as JSON, CSV, or Excel\n\nThe actor extracts:\n\n* 🛍️ **Full product catalog** — title, handle, vendor, type, tags, description, prices, variants, images, inventory signals\n* 🧩 **Detected apps** — Klaviyo, Recharge, Yotpo, Judge.me, Privy, Gorgias, Algolia, Okendo, Iterable, Bloomreach, Braze, Smile.io, LoyaltyLion, Weglot, Rebuy, Shogun, PageFly, Hotjar, GTM, Facebook Pixel, TikTok Pixel, and 30+ more\n* ⭐ **Reviews** from Yotpo, Judge.me, Stamped, Okendo, Loox (Full mode)\n* 🏷️ **Store metadata** — name, currency, country, myshopify domain, total products\n\n---\n\n## 🎬 Video Tutorial — See It in Action\n\n[![Shopify Apps Spy + Product Scraper Tutorial](https://img.youtube.com/vi/jxpSVYvZBFw/maxresdefault.jpg)](https://youtu.be/jxpSVYvZBFw)\n\n▶️ Watch the full tutorial — from a Shopify store URL to apps + products + reviews in under 3 minutes.\n\n*(🇫🇷 [Tutoriel français](https://youtu.be/JVnUpT7mjMw) · 🇩🇪 [Auf Deutsch](https://youtu.be/ujS8P1hpMTI) · 🇪🇸 [En español](https://youtu.be/pUiu2Usvpb0))*\n\n---\n\n## 🎯 Who is this Shopify scraper for?\n\n* 🤖 **B2B SaaS founders** targeting Shopify merchants — enrich your outbound list with installed-apps data nobody else has\n* 📊 **DTC operators and analysts** — snapshot competitor catalogs, watch what apps they install or churn, compare regional storefronts\n* 🛍️ **Dropshippers** — explore catalogs, prices, variants, apps, and reviews for product research\n* 🏪 **Agencies** — deliver clean tech-stack audits to your Shopify clients in minutes instead of hours\n\n---\n\n## ⚡ Why use this Shopify scraper?\n\n* 🧩 **Tech stack detection nobody else has** — the unique value vs the 8 other [Shopify scrapers on Apify Store](https://apify.com/store?search=shopify)\n* 🌍 **Multi-region tested** — US, UK, EU, France, Italy, Spain, Germany all validated end-to-end\n* 🚀 **Sub-30s per store** — scrapes 250 products + apps + reviews faster than any browser-based competitor\n* 💰 **Transparent event pricing** — $0.003 per extracted product; start, store, app-analysis, and review events are shown below\n* 🛡️ **Zero browser** — pure HTTP + JSON; the current default run allocation is 4 GB\n* ✅ **Sitemap fallback** — if a store disables [`/products.json`](https://shopify.dev/docs/api/ajax/section/product), the actor automatically reads the sitemap\n* 📦 **Real-time dataset** — products stream into your dataset as they're extracted, no batch wait\n* 🔁 **Batch up to 100 stores** in a single run\n\n> 💡 If you only need products without apps detection, use any commodity [Shopify scraper](https://apify.com/store?search=shopify). If you want the **stack intel**, this is the only actor that gives it to you.\n\n---\n\n## 🚀 How to scrape Shopify products in 3 steps\n\nSetting up 🧩 Shopify Apps Spy + Product Scraper takes **less than a minute**:\n\n1. Open the actor on [Apify Console](https://console.apify.com/actors/kazkn~shopify-scraper-apps-spy) and paste one or more **Shopify store URLs** in the input field (custom domain like `https://allbirds.com` or any `*.myshopify.com`).\n2. Pick an **Extraction Level** that matches what you need:\n   * **Basic** — products only\n   * **Standard** (default) — products + tech stack detection\n   * **Full** — Standard + reviews from [Yotpo](https://www.yotpo.com), [Judge.me](https://judge.me), [Stamped](https://stamped.io), [Okendo](https://www.okendo.com), [Loox](https://loox.io)\n3. Click **Run** — then download your dataset from the **Storage** tab as JSON, CSV, or Excel.\n\n> 💡 **Pro tip:** filter by collection handle to scrape only `/collections/sneakers` or any specific catalog slice instead of the whole store.\n\n### Input example\n\n```json\n{\n  \"store_urls\": [\n    \"https://allbirds.com\",\n    \"https://glossier.com\",\n    \"https://magicspoon.com\"\n  ],\n  \"extract_level\": \"full\",\n  \"max_products_per_store\": 250,\n  \"max_reviews_per_product\": 20,\n  \"max_concurrent_stores\": 3,\n  \"use_residential_proxy\": false\n}\n```\n\n> 💡 Set `use_residential_proxy: true` only when you scrape Cloudflare-protected stores like Tesla Shop or Manscaped. Datacenter proxy is enough for 98% of Shopify stores. Learn more about [Apify Proxy](https://docs.apify.com/platform/proxy).\n\n---\n\n## 🧩 Detected apps catalog (50+ apps, growing)\n\nThe detector spots the entire installed tech stack of any Shopify by running a library of regex patterns on the home page and one product page HTML.\n\n| Category | Detected apps |\n|---|---|\n| ⭐ **Reviews** | [Yotpo](https://www.yotpo.com) · [Judge.me](https://judge.me) · [Loox](https://loox.io) · [Stamped](https://stamped.io) · [Okendo](https://www.okendo.com) · [Reviews.io](https://www.reviews.io) · [Trustpilot](https://www.trustpilot.com) · Shopify legacy reviews |\n| 📧 **Email marketing** | [Klaviyo](https://www.klaviyo.com) · [Mailchimp](https://mailchimp.com) · [Omnisend](https://www.omnisend.com) · [Drip](https://www.drip.com) · **[Iterable](https://iterable.com)** · **[Bloomreach Engagement](https://www.bloomreach.com/en/products/engagement)** · **[Braze](https://www.braze.com)** |\n| 🎯 **Popups / opt-in** | [Privy](https://www.privy.com) · [Justuno](https://www.justuno.com) · [OptiMonk](https://www.optimonk.com) |\n| 🔁 **Subscriptions** | [Recharge](https://rechargepayments.com) · [Bold Subscriptions](https://boldcommerce.com/subscriptions) · [Appstle](https://appstle.com) |\n| 🎁 **Loyalty / rewards** | [Smile.io](https://smile.io) · [Yotpo Loyalty (Swell)](https://www.yotpo.com/platform/loyalty) · [LoyaltyLion](https://loyaltylion.com) |\n| 💬 **Live chat / helpdesk** | [Gorgias](https://www.gorgias.com) · [Tidio](https://www.tidio.com) · [Intercom](https://www.intercom.com) · [Zendesk](https://www.zendesk.com) · [Drift](https://www.drift.com) |\n| 🔎 **Search** | [Algolia](https://www.algolia.com) · [Searchanise](https://searchanise.io) · [Klevu](https://www.klevu.com) |\n| 🎨 **Page builders** | [Shogun](https://getshogun.com) · [PageFly](https://pagefly.io) · [GemPages](https://gempages.net) · [Zipify](https://zipify.com) |\n| 🌐 **Currency / i18n** | Currency Converter Plus · [Weglot](https://www.weglot.com) · [LangShop](https://langshop.app) |\n| 🛒 **Upsell / cart** | [ReConvert](https://www.reconvert.io) · [Bold Upsell](https://boldcommerce.com/upsell-cross-sell) · In Cart Upsell · [Rebuy](https://www.rebuyengine.com) |\n| 📈 **Analytics / pixels** | [Hotjar](https://www.hotjar.com) · [GTM](https://tagmanager.google.com) · [GA4](https://analytics.google.com) · [Facebook Pixel](https://www.facebook.com/business/help/952192354843755) · [TikTok Pixel](https://ads.tiktok.com) · [Pinterest Tag](https://help.pinterest.com/en/business/article/install-the-pinterest-tag) · [Snapchat Pixel](https://businesshelp.snapchat.com/s/article/pixel-direct-implementation) |\n\n> 💡 Don't see an app you care about? The patterns library is open — open an issue with a link to a store using it and I add the regex within 24h.\n\n---\n\n## 💰 Pricing\n\n🧩 Shopify Apps Spy + Product Scraper uses **pay-per-event** pricing. You only pay for what you actually extract:\n\n| Event | When it fires | Price |\n|---|---|---|\n| **Actor start** | Per charged GB at the start of a run | $0.05 / GB |\n| **Store analyzed** | Once per Shopify store with products | $0.01 |\n| **Product extracted** | Per product row pushed | $0.003 |\n| **Apps detected** | Per store at Standard or higher | $0.10 |\n| **Review extracted** | Per review row pushed | $0.001 |\n\n* The current default run allocation is **4 GB**, so actor start can charge **$0.20 per run** before store, product, app, or review events.\n* Apify platform usage is included in the event prices above.\n* Set `Max Total Charge USD` on every run to cap your spend\n\n### 💸 Real cost examples\n\nAll examples use one 4 GB run, therefore include a $0.20 actor-start charge. Apify platform usage is included in the event prices.\n\n* **Basic catalog — 1 store, 250 products:** $0.20 start + $0.01 store + (250 × $0.003 products) = **$0.96** in events.\n* **Standard tech-stack scan — 100 stores, 1 product each:** $0.20 start + (100 × $0.01 stores) + (100 × $0.003 products) + (100 × $0.10 app analysis) = **$11.50** in events.\n* **Full audit — 5 stores, 100 products and 10 reviews per product:** $0.20 start + (5 × $0.01 stores) + (500 × $0.003 products) + (5 × $0.10 app analysis) + (5,000 × $0.001 reviews) = **$7.25** in events.\n\nCompare to [PPSPY](https://www.ppspy.com) ($24/month), [Koala Inspector](https://koalainspector.com) ($9.99/month), [Charm.io](https://charm.io) ($299/month), [Shophunter](https://shophunter.io) ($99/month) — and none of them give you bulk API access or installed-apps data.\n\nLearn more about [Apify pricing](https://apify.com/pricing).\n\n---\n\n## 📦 Output format\n\nThe actor writes each output type to a separate run dataset so Apify tabs and CSV exports stay clean:\n\n* **Products** (default dataset) — one flat row per product, optimized for CSV / Sheets exports\n* **Store summary** — one row per store with metadata, counts, review diagnostics, and run health\n* **Apps detected** — one row per store with the detected Shopify app stack\n* **Reviews** — one row per review in Full mode, empty when no supported review provider is found\n\nExport any section to JSON / CSV / Excel / [Google Sheets](https://apify.com/integrations/google-sheets) / [Airtable](https://apify.com/integrations/airtable) / [Slack](https://apify.com/integrations/slack) / any [Apify integration](https://apify.com/integrations).\n\n> **Reviews note** — if the Reviews dataset is empty, check `reviews_status`, `reviews_products_probed`, and `review_providers_tried` in Store summary. The actor reports why reviews were not emitted instead of filling the Reviews tab with unrelated rows.\n\n### Products dataset\n\nOne row per product (or per variant if `include_variants: true`).\n\n```json\n{\n  \"store_url\": \"https://allbirds.com\",\n  \"store_domain\": \"allbirds.com\",\n  \"store_platform\": \"shopify\",\n  \"scraped_at\": \"2026-04-30T22:15:30Z\",\n  \"extract_level\": \"standard\",\n\n  \"product_id\": 7894123456,\n  \"product_handle\": \"wool-runner-mizzles-natural-white\",\n  \"product_title\": \"Wool Runner Mizzles - Natural White\",\n  \"product_url\": \"https://allbirds.com/products/wool-runner-mizzles-natural-white\",\n  \"product_type\": \"Sneakers\",\n  \"vendor\": \"Allbirds\",\n  \"tags\": \"wool, waterproof\",\n  \"description_text\": \"Plain text description\",\n\n  \"price\": 135.0,\n  \"price_min\": 135.0,\n  \"price_max\": 135.0,\n  \"compare_at_price\": null,\n  \"currency\": \"USD\",\n  \"available\": true,\n  \"available_variant_count\": 8,\n  \"total_variant_count\": 12,\n\n  \"image_urls\": \"https://cdn.shopify.com/...jpg | https://cdn.shopify.com/...jpg\",\n  \"main_image\": \"https://cdn.shopify.com/...jpg\",\n  \"image_count\": 6,\n\n  \"store_name\": \"Allbirds\",\n  \"myshopify_domain\": \"allbirds-2.myshopify.com\",\n  \"low_stock_message\": null,\n  \"in_stock_count\": null,\n  \"viewing_now_widget\": false,\n  \"recent_purchases\": false\n}\n```\n\n> **Variants** — `total_variant_count` and `available_variant_count` are always present. If a product has multiple flavors / sizes / colors (e.g. an energy drink with 5 flavors), set `include_variants: true` in the input to get one row per variant with per-SKU price, availability, and option labels (size, color, flavor, etc.) on top of the per-product summary.\n\n### Store summary dataset\n\nOne row per scraped store with store metadata, product counts, variant counts, and review diagnostics in Full mode.\n\n```json\n{\n  \"store_url\": \"https://magicspoon.com\",\n  \"store_domain\": \"magicspoon.com\",\n  \"myshopify_domain\": \"magicspoon-cereal.myshopify.com\",\n  \"store_name\": \"Magic Spoon\",\n  \"currency\": \"USD\",\n  \"country\": \"US\",\n  \"extract_level\": \"standard\",\n  \"detected_at\": \"2026-04-30T22:15:30Z\",\n  \"reviews_apps\": [\"okendo\"],\n  \"email_marketing\": [\"klaviyo\"],\n  \"subscriptions\": [\"recharge\"],\n  \"page_builder\": [\"shogun\"],\n  \"upsell\": [\"rebuy\"],\n  \"analytics\": [\"google_tag_manager\"],\n  \"all_apps_raw\": [\"okendo\", \"klaviyo\", \"recharge\", \"shogun\", \"rebuy\", \"google_tag_manager\"],\n  \"detected_count\": 6,\n  \"product_count\": 250,\n  \"in_stock_product_count\": 231,\n  \"total_variant_count\": 412,\n  \"row_count_pushed\": 250,\n  \"review_count\": 0,\n  \"reviews_status\": \"no_supported_review_app_detected\",\n  \"reviews_products_probed\": 100,\n  \"review_providers_tried\": [\"yotpo\", \"judgeme\", \"stamped\", \"okendo\", \"loox\"]\n}\n```\n\n### Apps detected dataset\n\nOne row per store in Standard and Full modes.\n\n```json\n{\n  \"store_url\": \"https://magicspoon.com\",\n  \"store_domain\": \"magicspoon.com\",\n  \"store_name\": \"Magic Spoon\",\n  \"myshopify_domain\": \"magicspoon-cereal.myshopify.com\",\n  \"detected_at\": \"2026-04-30T22:15:30Z\",\n  \"reviews_apps\": [\"okendo\"],\n  \"email_marketing\": [\"klaviyo\"],\n  \"subscriptions\": [\"recharge\"],\n  \"analytics\": [\"google_tag_manager\"],\n  \"all_apps_raw\": [\"okendo\", \"klaviyo\", \"recharge\", \"google_tag_manager\"],\n  \"detected_count\": 4\n}\n```\n\n### Reviews dataset\n\nOne row per review with normalized provider-agnostic fields. Emitted only at `extract_level: 'full'`.\n\n```json\n{\n  \"store_domain\": \"glossier.com\",\n  \"product_id\": 9576351138037,\n  \"product_handle\": \"spring-pinks\",\n  \"review_id\": \"yotpo_12345\",\n  \"provider\": \"yotpo\",\n  \"rating\": 5,\n  \"title\": \"Best lip balm ever\",\n  \"body\": \"I wear them every day...\",\n  \"author_name\": \"Sarah J.\",\n  \"author_verified\": true,\n  \"created_at\": \"2026-03-12T08:00:00Z\",\n  \"helpful_count\": 14,\n  \"images\": [\"https://cdn.yotpo.com/...\"]\n}\n```\n\n## 💡 Tips for scraping Shopify efficiently\n\n* 📈 **Batch multiple stores** in a single run — the actor runs them in parallel\n* 🌐 **Multi-region brands** — pass `https://allbirds.com`, `https://allbirds.eu`, `https://allbirds.co.uk` to compare regional storefronts (different stacks, different currencies)\n* 🛡️ **Hit a 403?** Toggle `Use Residential Proxy` for Cloudflare-protected stores ([Apify Proxy docs](https://docs.apify.com/platform/proxy))\n* 🔄 **Schedule weekly runs** with [Apify Scheduler](https://apify.com/schedules) to track product changes and price drops over time\n* 🪝 **Push to Sheets, Slack, Airtable** via [Apify integrations](https://apify.com/integrations) — no glue code needed\n* 🤖 **Run from any AI agent** ([Claude](https://claude.ai), [Cursor](https://cursor.com), [Windsurf](https://codeium.com/windsurf)) using the [Apify MCP server](https://apify.com/apify/actors-mcp-server)\n\n---\n\n## 🌍 Supported Shopify markets and stores\n\n🧩 Shopify Apps Spy + Product Scraper works on **any [Shopify](https://www.shopify.com) storefront worldwide** — custom domain, `*.myshopify.com`, regional subdomains, [Shopify Plus](https://www.shopify.com/plus).\n\n✅ Empirically tested on stores from these countries before publishing:\n\n🇺🇸 United States · 🇬🇧 United Kingdom · 🇪🇺 European Union · 🇫🇷 France · 🇩🇪 Germany · 🇮🇹 Italy · 🇪🇸 Spain\n\nThe endpoint we use ([`/products.json`](https://shopify.dev/docs/api/ajax/section/product)) is a public, version-less Shopify spec that has been stable since 2014. **Country, currency, and language do not affect detection** — the actor handles every Shopify storefront identically.\n\n---\n\n## 🧭 When to use Shopify Apps Spy + Product Scraper vs alternatives\n\nUse **🧩 Shopify Apps Spy + Product Scraper** if you want:\n\n* The only [Apify Shopify scraper](https://apify.com/store?search=shopify) with **installed-apps detection**\n* Catalog + apps + reviews in one run\n* Sub-30s per store, batchable up to 100\n* Pay-per-event with no subscription\n\nUse **[PPSPY](https://www.ppspy.com)** ($24/month) or **[Charm.io](https://charm.io)** ($299/month) if you prefer:\n\n* A polished web UI without API access\n* Flat monthly pricing instead of usage-based\n\nUse **a generic [web scraper](https://apify.com/apify/web-scraper)** if you only need:\n\n* Single-product scraping with custom selectors\n* No Shopify-specific data model\n\n> 💡 Product extraction is billed at $0.003 per row. Total event cost also includes the run-start, store, and optional app-analysis and review events described in the pricing table.\n\n---\n\n## 🔗 Part of the KazKN ecosystem\n\nThis actor is part of the [KazKN](https://apify.com/kazkn) family of scrapers and MCP servers on Apify:\n\n* [🧩 Shopify Apps Spy + Product Scraper](https://apify.com/kazkn/shopify-scraper-apps-spy) — this actor\n* [Vinted Smart Scraper — Cross-Country Price Comparison](https://apify.com/kazkn/vinted-smart-scraper) — full Vinted intelligence across 26 markets\n* [⚡ Vinted Turbo Scraper](https://apify.com/kazkn/vinted-turbo-scraper) — fastest Vinted URL-to-dataset workflow\n* [Vinted MCP Server](https://apify.com/kazkn/vinted-mcp-server) — connect any AI agent ([Claude](https://claude.ai), [Cursor](https://cursor.com), [Windsurf](https://codeium.com/windsurf)) to Vinted data\n* [App Store Scraper for Localization Gaps](https://apify.com/kazkn/apple-app-store-localization-scraper) — find US apps missing French, German, Spanish localizations\n* [GPT Crawler MCP](https://apify.com/kazkn/gpt-crawler-mcp) — turn any website into a clean knowledge file for [ChatGPT](https://chatgpt.com), [Claude](https://claude.ai), or [RAG](https://www.anthropic.com/news/contextual-retrieval) pipelines\n\n---\n\n## ❓ Frequently asked questions\n\n### Is scraping Shopify legal?\n\nYes. The [`/products.json`](https://shopify.dev/docs/api/ajax/section/product) endpoint is a public, official [Shopify](https://www.shopify.com) feature documented by Shopify and consumed by [Google Shopping](https://shopping.google.com) for indexing. The actor does not bypass authentication, does not interact with Shopify's Admin API, and does not collect any buyer personal data. Read more on the [Apify legal blog](https://blog.apify.com/is-web-scraping-legal/).\n\n### Can you scrape Shopify products without an API key?\n\nYes. The actor uses only the public [storefront `/products.json` endpoint](https://shopify.dev/docs/api/ajax/section/product) — no app install, no [OAuth](https://shopify.dev/docs/apps/auth/oauth), no API key.\n\n### Does Shopify have an API?\n\nTwo: the [Admin API](https://shopify.dev/docs/api/admin) (requires OAuth + a per-store install — not used here) and the public [storefront `/products.json` endpoint](https://shopify.dev/docs/api/ajax/section/product) (used here).\n\n### How many products can I extract per store?\n\nUp to 100,000 per store, paginated 250 at a time. Realistic Shopify catalogs have 50–10,000 products.\n\n### What if a store disables `/products.json`?\n\nThe actor automatically falls back to `sitemap_products_1.xml` and pulls each product via `/products/{handle}.json`. About 2 % of [Shopify Plus](https://www.shopify.com/plus) stores disable both — they show up as a graceful \"no products fetched\" record with diagnostic info.\n\n### Does the actor work on Shopify Plus stores?\n\nYes — most of the validation set is [Shopify Plus](https://www.shopify.com/plus) (Allbirds, Magic Spoon, Glossier, Kith, Princess Polly, Pinko, Aspesi, PDPaola).\n\n### How does the apps detector work?\n\nIt fetches the home page HTML and one product page HTML, then runs a library of regex patterns against the combined markup. Detection signals include CDN URLs, JavaScript globals, custom HTML attributes, and inline configuration objects.\n\n### How accurate is the apps detection?\n\nVery high recall on apps that ship visible front-end widgets ([Yotpo](https://www.yotpo.com), [Judge.me](https://judge.me), [Recharge](https://rechargepayments.com), [Klaviyo](https://www.klaviyo.com), [Privy](https://www.privy.com), [Gorgias](https://www.gorgias.com), [Algolia](https://www.algolia.com), [Okendo](https://www.okendo.com)). Lower recall on stores that lazy-load apps via SPAs or use a heavily customized headless theme (e.g. Gymshark, Bombas). The detector reports actual reality — never fabricates apps.\n\n### What review providers are supported?\n\n[Yotpo](https://www.yotpo.com), [Judge.me](https://judge.me), [Stamped](https://stamped.io), [Okendo](https://www.okendo.com), and [Loox](https://loox.io). The crawler picks the first provider the apps detector flagged for the store, or falls through the list until one returns reviews.\n\n### Can I scrape multi-region brands?\n\nYes. Pass each storefront URL separately (e.g. `https://allbirds.com`, `https://allbirds.eu`, `https://allbirds.co.uk`) and the actor reports the local currency in the product and store summary outputs, then treats each storefront as an independent run.\n\n### What about Cloudflare-protected stores?\n\nSome stores ([Tesla Shop](https://shop.tesla.com), [Manscaped](https://www.manscaped.com)) front their storefront with [Cloudflare](https://www.cloudflare.com). Toggle **Use Residential Proxy** on those — the actor routes through [Apify's residential pool](https://apify.com/proxy/residential).\n\n### Can I filter by collection?\n\nYes — set `Filter by Collection` to a collection handle (e.g. `sneakers`, `new-arrivals`) and the actor restricts the scrape to that collection only.\n\n### Can I run this on a schedule?\n\nYes — schedule runs in [Apify Scheduler](https://apify.com/schedules) with any cadence (hourly, daily, weekly). Export to webhook, [Google Sheets](https://apify.com/integrations/google-sheets), [S3](https://apify.com/integrations/aws-s3), [BigQuery](https://apify.com/integrations/google-bigquery), or any [Apify integration](https://apify.com/integrations).\n\n### Is data validated before being pushed?\n\nYes — every product, store summary, and review is validated against a [Zod](https://zod.dev) schema before being pushed. Invalid rows are logged and skipped, never stored.\n\n### What's the typical run time?\n\nStandard level: 5–10 seconds per store on a single product page (250 products), parallelized across stores. 20 stores in standard level finishes in ~45 seconds in cloud benchmarks.\n\n### What's the memory footprint?\n\nThe current default run allocation is 4 GB. Actor start is charged at $0.05 per charged GB, so this allocation can bill $0.20 before result events. See [Apify resource pricing](https://apify.com/pricing).\n\n### What if the URL isn't a Shopify store?\n\nThe actor returns a diagnostic record with `error: \"not_a_shopify_store\"`, the signals it checked, and the HTTP status code. **You are never charged for non-Shopify URLs**.\n\n### How is this different from a generic scraper?\n\nGeneric scrapers like [Apify Web Scraper](https://apify.com/apify/web-scraper) extract one product at a time, do not understand Shopify's variants/collections/inventory model, and can't detect installed apps. This actor is purpose-built for Shopify with regex patterns tuned for the apps detection use case.\n\n### Can I use this from an AI agent?\n\nYes — connect any [MCP-compatible AI agent](https://modelcontextprotocol.io) ([Claude](https://claude.ai), [Cursor](https://cursor.com), [Windsurf](https://codeium.com/windsurf)) via the [Apify MCP server](https://apify.com/apify/actors-mcp-server). The agent can call this actor as a tool.\n\n### Can you add a specific app to the detector?\n\nYes — the patterns library is regex-based. Open an issue with a link to a store using the app and I'll add the regex.\n\n---\n\n## ⚖️ Is it legal to scrape Shopify?\n\nThe [`/products.json`](https://shopify.dev/docs/api/ajax/section/product) endpoint is public and documented by [Shopify](https://www.shopify.com). The actor does not bypass authentication, respects rate limits, and does not collect buyer personal data.\n\nNote that personal data is protected by [GDPR](https://gdpr.eu) in the EU and other regulations worldwide. Do not scrape personal data unless you have a legitimate reason. If unsure, consult your lawyers. Suggested reading: [Is web scraping legal? — Apify Blog](https://blog.apify.com/is-web-scraping-legal/).\n",
      "input": {
        "title": "🧩 Shopify Store Intelligence — Catalog, Apps & Reviews",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "store_urls": {
            "title": "Shopify Store URLs",
            "type": "array",
            "description": "Paste one or more Shopify storefront URLs (for example https://allbirds.com). Works with custom domains and *.myshopify.com URLs.",
            "editor": "stringList",
            "prefill": [
              "https://allbirds.com"
            ],
            "minItems": 1,
            "maxItems": 100
          },
          "extract_level": {
            "title": "Data to Extract",
            "type": "string",
            "description": "Choose the data depth:\n- Basic: product catalog only\n- Standard: product catalog + installed apps\n- Full: product catalog + installed apps + reviews",
            "editor": "select",
            "enum": [
              "basic",
              "standard",
              "full"
            ],
            "enumTitles": [
              "Basic — catalog only",
              "Standard — catalog + apps",
              "Full — catalog + apps + reviews"
            ],
            "default": "standard"
          },
          "max_products_per_store": {
            "title": "Max Products Per Store",
            "type": "integer",
            "description": "Maximum products to extract per store. Set 0 for unlimited; unlimited runs can take longer and cost more.",
            "editor": "number",
            "default": 250,
            "minimum": 0,
            "maximum": 100000
          },
          "products_collection_filter": {
            "title": "Filter by Collection (optional)",
            "type": "string",
            "description": "Only extract products from one collection handle (for example sneakers or new-arrivals). Leave empty for the full catalog.",
            "sectionCaption": "Advanced options",
            "sectionDescription": "Optional controls for collection filtering, variant-level rows, review limits, parallel runs, proxy routing, and troubleshooting logs.",
            "editor": "textfield",
            "default": ""
          },
          "include_variants": {
            "title": "Include Product Variants",
            "type": "boolean",
            "description": "Output one row per variant (size/color/SKU) instead of one row per product.",
            "default": false
          },
          "max_reviews_per_product": {
            "title": "Max Reviews Per Product (Full only)",
            "type": "integer",
            "description": "Maximum reviews to extract per product in Full mode.",
            "editor": "number",
            "default": 20,
            "minimum": 1,
            "maximum": 500
          },
          "max_concurrent_stores": {
            "title": "Concurrent Stores (multi-store mode)",
            "type": "integer",
            "editor": "number",
            "description": "Number of stores scraped in parallel. Higher = faster but more memory.",
            "default": 3,
            "minimum": 1,
            "maximum": 10
          },
          "use_residential_proxy": {
            "title": "Use Residential Proxy (advanced)",
            "type": "boolean",
            "description": "Keep off for most stores. Enable only when a store blocks datacenter traffic or is protected by anti-bot tools.",
            "default": false
          },
          "debug_mode": {
            "title": "Debug Mode",
            "type": "boolean",
            "description": "Enable verbose logs for troubleshooting.",
            "default": false
          }
        },
        "required": [
          "store_urls"
        ]
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "Output schema of Shopify Scraper",
        "description": "The actor stores each record type in separate datasets: products, store summaries, detected apps, and reviews.",
        "properties": {
          "products": {
            "type": "string",
            "title": "Products",
            "description": "Product rows from the Shopify catalog. When variants are enabled, each variant is a separate row.",
            "template": "{{storages.datasets.default.apiUrl}}/items"
          },
          "storeSummary": {
            "type": "string",
            "title": "Store summary",
            "description": "One summary row for each attempted store, including product counts and review diagnostics.",
            "template": "{{storages.datasets.summary.apiUrl}}/items"
          },
          "appsDetected": {
            "type": "string",
            "title": "Apps detected",
            "description": "Detected Shopify apps grouped by category for stores processed in Standard or Full mode.",
            "template": "{{storages.datasets.apps.apiUrl}}/items"
          },
          "reviews": {
            "type": "string",
            "title": "Reviews",
            "description": "Publicly accessible product reviews extracted in Full mode.",
            "template": "{{storages.datasets.reviews.apiUrl}}/items"
          }
        }
      },
      "storages": {
        "datasets": {
          "default": {
            "actorSpecification": 1,
            "title": "Products",
            "description": "Clean product catalog dataset. One row per product, or one row per variant when Include Product Variants is enabled.",
            "views": {
              "overview": {
                "title": "📦 Products",
                "description": "Product catalog rows with CSV-friendly flat columns.",
                "transformation": {
                  "fields": [
                    "main_image",
                    "store_domain",
                    "product_title",
                    "price",
                    "currency",
                    "available",
                    "vendor",
                    "product_type",
                    "tags",
                    "total_variant_count",
                    "available_variant_count",
                    "product_url",
                    "product_handle",
                    "product_id",
                    "compare_at_price",
                    "price_min",
                    "price_max",
                    "image_count",
                    "image_urls",
                    "description_text",
                    "store_name",
                    "myshopify_domain",
                    "created_at",
                    "updated_at",
                    "published_at"
                  ]
                },
                "display": {
                  "component": "table",
                  "properties": {
                    "main_image": {
                      "label": "Image",
                      "format": "image"
                    },
                    "store_domain": {
                      "label": "Store",
                      "format": "text"
                    },
                    "product_title": {
                      "label": "Product",
                      "format": "text"
                    },
                    "price": {
                      "label": "Price",
                      "format": "number"
                    },
                    "currency": {
                      "label": "Currency",
                      "format": "text"
                    },
                    "available": {
                      "label": "In stock",
                      "format": "boolean"
                    },
                    "vendor": {
                      "label": "Vendor",
                      "format": "text"
                    },
                    "product_type": {
                      "label": "Type",
                      "format": "text"
                    },
                    "tags": {
                      "label": "Tags",
                      "format": "text"
                    },
                    "total_variant_count": {
                      "label": "# variants",
                      "format": "number"
                    },
                    "available_variant_count": {
                      "label": "# available variants",
                      "format": "number"
                    },
                    "product_url": {
                      "label": "Link",
                      "format": "link"
                    }
                  }
                }
              }
            }
          },
          "summary": {
            "actorSpecification": 1,
            "title": "Store Summary",
            "description": "One row per store with catalog counts, detected app count, and review diagnostics.",
            "views": {
              "overview": {
                "title": "🏪 Store Summary",
                "description": "A true store-level summary. One row per scraped store.",
                "transformation": {
                  "fields": [
                    "store_domain",
                    "store_name",
                    "currency",
                    "country",
                    "product_count",
                    "in_stock_product_count",
                    "total_variant_count",
                    "row_count_pushed",
                    "detected_count",
                    "all_apps_raw",
                    "review_count",
                    "reviews_status",
                    "reviews_products_probed",
                    "review_providers_detected",
                    "review_providers_tried",
                    "review_provider_keys_found",
                    "myshopify_domain",
                    "store_url",
                    "scraped_at"
                  ]
                },
                "display": {
                  "component": "table",
                  "properties": {
                    "store_domain": {
                      "label": "Store",
                      "format": "text"
                    },
                    "store_name": {
                      "label": "Name",
                      "format": "text"
                    },
                    "currency": {
                      "label": "Currency",
                      "format": "text"
                    },
                    "country": {
                      "label": "Country",
                      "format": "text"
                    },
                    "product_count": {
                      "label": "# products",
                      "format": "number"
                    },
                    "in_stock_product_count": {
                      "label": "# in stock",
                      "format": "number"
                    },
                    "total_variant_count": {
                      "label": "# variants",
                      "format": "number"
                    },
                    "row_count_pushed": {
                      "label": "# rows pushed",
                      "format": "number"
                    },
                    "detected_count": {
                      "label": "# apps",
                      "format": "number"
                    },
                    "all_apps_raw": {
                      "label": "Apps",
                      "format": "array"
                    },
                    "review_count": {
                      "label": "# reviews",
                      "format": "number"
                    },
                    "reviews_status": {
                      "label": "Reviews status",
                      "format": "text"
                    },
                    "reviews_products_probed": {
                      "label": "Products probed",
                      "format": "number"
                    },
                    "review_providers_detected": {
                      "label": "Review apps",
                      "format": "array"
                    },
                    "review_providers_tried": {
                      "label": "Providers tried",
                      "format": "array"
                    },
                    "review_provider_keys_found": {
                      "label": "Keys found",
                      "format": "array"
                    },
                    "store_url": {
                      "label": "URL",
                      "format": "link"
                    },
                    "scraped_at": {
                      "label": "Scraped at",
                      "format": "date"
                    }
                  }
                }
              }
            }
          },
          "apps": {
            "actorSpecification": 1,
            "title": "Apps Detected",
            "description": "One row per store with detected apps grouped by category.",
            "views": {
              "overview": {
                "title": "🧩 Apps detected",
                "description": "Detected Shopify apps by category.",
                "transformation": {
                  "fields": [
                    "store_domain",
                    "store_name",
                    "detected_count",
                    "all_apps_raw",
                    "email_marketing",
                    "sms_marketing",
                    "reviews_apps",
                    "subscriptions",
                    "popups",
                    "loyalty",
                    "live_chat",
                    "upsell",
                    "search",
                    "analytics",
                    "pricing_ab_testing",
                    "cookie_consent",
                    "geo_region",
                    "page_builder",
                    "currency_converter",
                    "detected_at"
                  ]
                },
                "display": {
                  "component": "table",
                  "properties": {
                    "store_domain": {
                      "label": "Store",
                      "format": "text"
                    },
                    "store_name": {
                      "label": "Name",
                      "format": "text"
                    },
                    "detected_count": {
                      "label": "# apps",
                      "format": "number"
                    },
                    "all_apps_raw": {
                      "label": "All apps",
                      "format": "array"
                    },
                    "email_marketing": {
                      "label": "Email",
                      "format": "array"
                    },
                    "sms_marketing": {
                      "label": "SMS",
                      "format": "array"
                    },
                    "reviews_apps": {
                      "label": "Reviews apps",
                      "format": "array"
                    },
                    "subscriptions": {
                      "label": "Subscriptions",
                      "format": "array"
                    },
                    "popups": {
                      "label": "Popups",
                      "format": "array"
                    },
                    "loyalty": {
                      "label": "Loyalty",
                      "format": "array"
                    },
                    "live_chat": {
                      "label": "Live chat",
                      "format": "array"
                    },
                    "upsell": {
                      "label": "Upsell / Bundles",
                      "format": "array"
                    },
                    "search": {
                      "label": "Search",
                      "format": "array"
                    },
                    "analytics": {
                      "label": "Analytics / Pixels",
                      "format": "array"
                    },
                    "pricing_ab_testing": {
                      "label": "Pricing / AB",
                      "format": "array"
                    },
                    "cookie_consent": {
                      "label": "Cookie banner",
                      "format": "array"
                    },
                    "geo_region": {
                      "label": "Geo / Region",
                      "format": "array"
                    },
                    "page_builder": {
                      "label": "Page builder",
                      "format": "array"
                    },
                    "currency_converter": {
                      "label": "Currency / i18n",
                      "format": "array"
                    },
                    "detected_at": {
                      "label": "Detected at",
                      "format": "date"
                    }
                  }
                }
              }
            }
          },
          "reviews": {
            "actorSpecification": 1,
            "title": "Reviews",
            "description": "One row per extracted review in Full mode.",
            "views": {
              "overview": {
                "title": "⭐ Reviews",
                "description": "Extracted product review rows. Empty when no supported review provider returns reviews.",
                "transformation": {
                  "fields": [
                    "store_domain",
                    "product_handle",
                    "provider",
                    "rating",
                    "title",
                    "body",
                    "author_name",
                    "author_verified",
                    "created_at",
                    "helpful_count",
                    "images"
                  ]
                },
                "display": {
                  "component": "table",
                  "properties": {
                    "store_domain": {
                      "label": "Store",
                      "format": "text"
                    },
                    "product_handle": {
                      "label": "Product",
                      "format": "text"
                    },
                    "provider": {
                      "label": "Provider",
                      "format": "text"
                    },
                    "rating": {
                      "label": "Rating",
                      "format": "number"
                    },
                    "title": {
                      "label": "Title",
                      "format": "text"
                    },
                    "body": {
                      "label": "Body",
                      "format": "text"
                    },
                    "author_name": {
                      "label": "Author",
                      "format": "text"
                    },
                    "author_verified": {
                      "label": "Verified",
                      "format": "boolean"
                    },
                    "created_at": {
                      "label": "Date",
                      "format": "date"
                    },
                    "helpful_count": {
                      "label": "Helpful",
                      "format": "number"
                    },
                    "images": {
                      "label": "Images",
                      "format": "array"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "changelog": "# Changelog\n\nAll notable changes to **Shopify Apps Spy + Product Scraper** are documented here.\nThis project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\nThe Apify build numbers track each deployment to the Apify Store; the version\nnumbers below reflect functional changes visible to users.\n\n---\n\n## [1.2.4] — 2026-06-24\n\n### Fixed\n- Split actor output into separate run-scoped datasets for Products, Store summary, Apps detected, and Reviews so Apify Console sections no longer display unrelated rows.\n- Flattened product rows for cleaner CSV exports: tags and image URLs are now string fields, while nested app/store metadata and raw HTML were removed from the Products dataset.\n- Added focused dataset schemas for each output tab and updated the README output examples.\n\n---\n\n## [1.2.3] — 2026-06-24\n\n### Fixed\n- Improved app detection for Shopify App Extension script URLs, including Shopify Inbox, Smile.io, and Free Gifts widgets.\n- Added a dedicated **Apps detected** dataset view in Apify Console.\n- Added review diagnostics to `store_summary` so Full mode explains whether reviews were found, no supported review app was detected, or providers were tried with no results.\n\n---\n\n## [1.2.2] — 2026-06-24\n\n### Fixed\n- Fixed Apify proxy session IDs for hyphenated Shopify domains such as `kbeauty-cosmetics.com`, which previously stopped the run before scraping began.\n- Automatically infers the collection filter when users paste a Shopify `/collections/...` URL and leave the advanced collection filter empty.\n\n---\n\n## [1.2.1] — 2026-06-24\n\n### Changed\n- Moved optional input controls into a collapsible **Advanced options** section in Apify Console, starting at collection filtering and including variants, review limits, concurrency, proxy, and debug settings.\n\n---\n\n## [1.2.0] — 2026-06-24\n\n### Fixed\n- Hardened store URL validation to reject non-public hosts, private IPs, localhost, ports, and unsupported protocols before any request is made.\n- Preserved extended app categories (`sms_marketing`, `pricing_ab_testing`, `cookie_consent`, `geo_region`) inside product-level `apps_detected` rows.\n- Fixed `store_summary.review_count` so multi-store runs report the current store's reviews instead of the global run counter.\n- Restored `npm test` with focused Node regression tests and refreshed vulnerable transitive dependencies.\n- Removed the unsupported placeholder tier from the public input and output contract. Active modes are now `basic`, `standard`, and `full`.\n- Updated output schema, dataset views, and README wording to match the default-dataset `record_type` output.\n\n---\n\n## [1.1.0] — 2026-05-26\n\n### Fixed (critical — actor was returning only the store domain instead of products)\n- **`Insufficient permissions for the dataset` hung the run when the actor was called via the Apify API or by any user other than the actor owner.** Apify runs every public actor under a `LIMITED_PERMISSIONS` token that can write to the run's default dataset but cannot open globally-named datasets like `apps` or `reviews`. The previous code called `Actor.openDataset('apps')` which hung indefinitely under that token, freezing the run after the first store and leaving the dataset effectively empty (just an error/domain record). The actor now writes every row to the default dataset only, tagged with a `record_type` field so the output stays filterable.\n- Anti-bot block detection (Cloudflare Bot Fight Mode, Akamai, PerimeterX, Datadome) — datacenter IPs sometimes get a 403 from anti-bot, which the previous code misreported as `not_a_shopify_store`. The actor now distinguishes \"blocked by anti-bot\" from \"not a Shopify store\" and auto-retries with a residential proxy on the first block. If the block persists, the diagnostic record now includes an actionable `next_steps` array (whitelist Apify IPs in Cloudflare, disable Bot Fight Mode for `/products.json`, etc.).\n\n### Added\n- `record_type` field on every dataset record (`product` / `apps` / `reviews`). Filter the default dataset by this field instead of opening separate named datasets.\n- `proxy_tier_used` field in diagnostic records (`datacenter` / `residential_fallback`) so users can see exactly which network path succeeded.\n- Anti-bot signal codes in the `signals` array (`anti_bot_cloudflare`, `anti_bot_akamai`, etc.) for downstream filtering.\n- 4-second timeout on every `Actor.charge()` call so a hung billing endpoint can never freeze the run.\n\n### Changed\n- **Output structure.** All records now flow through the default dataset. Existing scripts that read from the `apps` and `reviews` named datasets need to switch to `dataset.filter(r => r.record_type === 'apps')` etc. on the default dataset.\n- **`include_variants: true` now emits one row per variant** (matching the README contract) instead of a nested `variants[]` array on a single product row. Each variant row carries the full product fields plus per-variant `variant_id`, `variant_title`, `sku`, `option1/2/3`, variant-level `price`, `compare_at_price`, `available`, and `main_image` (variant featured image when available). Verified on `aplusnutri.com`: the product \"Équilibre et bien-être au quotidien\" now correctly produces 5 rows (Limonade framboise / Pastèque fraîche / Cerise gourmande / Orange douce / Piña colada).\n- **Revenue placeholder row** (emitted at `extract_level: 'pro'`) moved from the named `revenue` dataset to the default dataset with `record_type: 'revenue'`. Same LIMITED_PERMISSIONS rationale.\n\n### Added (apps detection coverage — major expansion)\n- **30+ new detectors** across 4 new categories:\n  - **Analytics**: Microsoft Clarity, Segment, Mixpanel\n  - **Pricing / AB testing** (new category): Intelligems, Visually.io, Dexter\n  - **SMS marketing** (new category): Attentive, Postscript, Emotive\n  - **Bundles / Upsell**: Kaching Bundles, Bundler, FastBundle\n  - **Geo / Region** (new category): Boostymark Region Block, Shopify Geolocation\n  - **Cookie consent** (new category): Axeptio, Iubenda, Cookiebot, OneTrust, Termly, Shopify Privacy Banner\n  - **Live chat extended**: Shopify Inbox, Re:amaze, Crisp, Freshchat\n  - **Currency / i18n extended**: Multi Currency Converter, Bagging\n- Verified on `aplusnutri.com`: detection went from 1 app (klaviyo only) to 6 apps across 6 categories — Klaviyo, Microsoft Clarity, Intelligems, Kaching Bundles, Boostymark Region Block, Shopify Privacy Banner.\n\n### Added (Apify Console UI)\n- **4 dedicated dataset views** for clean per-type rendering in Apify Console:\n  - **All records** — universal columns with `record_type` first for sort/filter\n  - **📦 Products** — image, title, variant_title, sku, price, currency, availability, vendor, link\n  - **🧩 Apps detected** — one row per store, columns per category (email/SMS/reviews/subs/popups/loyalty/chat/upsell/search/analytics/pricing_ab/consent/geo/page_builder/i18n)\n  - **⭐ Reviews** — store, product, provider, rating, body, author, date\n  - **💰 Revenue** — placeholder until the model lands\n\n---\n\n## [1.0.2] — 2026-05-05\n\n### Added\n- 4-language video tutorials (EN / FR / DE / ES) embedded in README and on Apify Store\n- `examples/` folder with 5 runnable code samples covering ICP qualification, app market-share research, cold-outreach personalization, cURL quickstart, and Zapier/Make.com integration\n- README badges (Apify Run, MIT License, YouTube Tutorial)\n- \"Video Tutorial\" section in README + Apify Store, mirroring the format used on the Vinted Turbo Scraper actor\n\n### Changed\n- Renamed actor from \"Shopify Product Scraper - Apps Spy + Reviews\" to **\"Shopify Apps Spy + Product Scraper\"** to lead with the differentiated apps-detection feature while keeping the product-scraper SEO term\n- Aligned `.actor/actor.json` title and `.actor/README.md` with the new name\n\n---\n\n## [1.0.0] — 2026-04-30\n\n### Added\n- Apps detection across 150+ Shopify apps (email/SMS, reviews, subscriptions, popups, search, loyalty, ad pixels)\n- Product catalog extraction via the official `/products.json` endpoint\n- Reviews extraction at `extract_level: full` for Yotpo, Judge.me, Stamped, Okendo, Loox, Junip, Reviews.io, Rebuy\n- Pay-per-event pricing: $0.003/store, $0.0005/product, $0.001/apps_detected, $0.0003/review\n- 4 extract levels: `basic`, `standard`, `full`, `pro`\n- JSON / CSV / Excel / RSS export\n- Free $5 monthly credit covers ≈1,500 stores at standard tier\n\n### Performance\n- Polite concurrency of 5 simultaneous requests scans 1,000 stores in ~25 minutes\n- No proxy required for the vast majority of stores\n- No login, no API key, no headless browser\n\n---\n\n## Roadmap\n\n- **MCP server mode** — query the actor directly from Claude desktop / Cursor (in line with the existing [Vinted MCP Server](https://apify.com/kazkn/vinted-mcp-server) and [GPT Crawler MCP](https://apify.com/kazkn/gpt-crawler-mcp))\n- **Theme detection** — useful for agency outbound (Shopify 2.0 vs vintage themes vs custom)\n- **More detectors** — every \"this is missing\" issue gets a 15-minute add. Open an issue to request one.\n"
    },
    "buildNumber": "1.2.6",
    "actVersion": {
      "sourceType": "TARBALL",
      "buildTag": "latest",
      "versionNumber": "1.2"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.055314444444444444
    }
  }
}