# Shopify Scripttag Migration Auditor (`respectful_ninja/shopify-scripttag-migration-auditor`) Actor

Scan public Shopify storefronts for legacy ScriptTags before the March 2027 shutdown. Identify asyncLoad() scripts, check URL reachability, and flag possible app-extension replacements. No Shopify Admin access required; findings require manual verification.

- **URL**: https://apify.com/respectful_ninja/shopify-scripttag-migration-auditor.md
- **Developed by:** [Michaelangelo Couvertier](https://apify.com/respectful_ninja) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 store auditeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Shopify ScriptTag Migration Auditor

Identify **legacy Shopify Online Store ScriptTags** that may require attention before Shopify stops injecting them on **March 1, 2027**. Built for Shopify agencies, developers, and merchants performing migration triage across multiple storefronts.

**What it does:** Scans public HTML, identifies Shopify theme signals, extracts URLs from legacy `asyncLoad()` loaders, checks whether script URLs are reachable, and reports possible Theme App Extension replacements. No merchant login is required for this *public-page review*.

**What it does not do:** It cannot determine whether a script executes successfully, whether the merchant needs its functionality, whether the associated app has already migrated internally, or whether a replacement behaves identically. **Do not treat the output as a completed migration certification.**

### What you receive

Each scanned URL produces a dataset record with:

- The storefront URL, Shopify identity assessment, theme indicators, and scanned page types.
- Legacy `asyncLoad()` ScriptTags, source URL, recognized app/vendor when available, HTTP status, and evidence category.
- Potential replacement assets found in public HTML, including their HTTP reachability (not functional verification).
- Counts of reachable scripts lacking a detected replacement, candidate dual-loads, unreachable or unprobed scripts, and dead script URLs.
- An agency action plan and coverage limitations to guide follow-up.
- Estimated billing-event selection and, when monetization is enabled, actual charge-attempt telemetry.

#### How to interpret the main categories

| Finding | Meaning | Suggested follow-up |
| --- | --- | --- |
| Reachable legacy script, no replacement detected | Script URL returned HTTP 200/206; a replacement was not visible in the inspected templates | Confirm app ownership and its current integration in Shopify Admin; check migration requirements |
| Candidate dual-load | A possible replacement asset or pixel is visible, but functional parity is unverified | Test the modern integration in a preview theme before removing the legacy tag |
| Unreachable or unprobed script | HTTP checks failed, were blocked, or were disabled | Retry or investigate manually; this is not a verified failed integration |
| Dead legacy script | Script URL returned HTTP 404/410 | Check whether app is abandoned and whether removal is safe |
| Unverified storefront | Insufficient HTML evidence, password protection, WAF, or headless/custom storefront | Manual verification needed; do not interpret zero findings as a clean migration |

### Run the Actor

1. Enter a public Shopify storefront URL (or a batch of URLs) in **Storefront URLs to Audit**.
2. Keep **Probe HTTP Liveness** enabled to distinguish reachable URLs from uncertain ones.
3. Keep **Multi-Template Scan** enabled. It follows available links to up to one product, collection, and cart page in addition to the homepage.
4. Use a modest **Max Concurrent Storefront Workers** setting, such as 2–5, especially for first-time audits.
5. Start the Actor. Inspect the **Dataset** tab for the resulting storefront-level records.

**Example input:**

```json
{
  "storeUrls": ["https://www.allbirds.com"],
  "verifyScriptLiveness": true,
  "scanProductPage": true,
  "maxConcurrency": 2,
  "useApifyProxy": false
}
```

The example is a public website used in the November 2026 pilot. Its live output may change at any time. Use your own storefront list for operational work.

### Real-world pilot

On **November 5, 2026**, the scanner identified legacy `asyncLoad()` URLs on three accessible Shopify-theme storefronts: **2 on Allbirds, 6 on tentree, and 4 on Brooklinen**, all returning HTTP 200 at the time of testing. They were **twelve reachable migration-review candidates**, not twelve confirmed broken integrations or paid remediation opportunities. Other sites were correctly or cautiously classified as non-Shopify, headless/custom, or inconclusive. This small nonrandom pilot does **not** establish detection accuracy.

### Scope and limitations

- Public HTML only: no Shopify Admin API access, authenticated theme inspection, full ScriptTag inventory, app installation inventory, or browser-based runtime event testing.
- The tool extracts recognized legacy `asyncLoad()` patterns; scripts loaded through different mechanisms may not appear.
- The four template types are sampled only when public links are discoverable. Missing templates remain out of scope.
- A response of HTTP 200/206 proves file reachability, not execution, merchant reliance, or future failure.
- A matching extension asset proves reachability, not functional replacement. An absent match does not prove the app has no replacement.
- Bot defenses, passwords, redirects, and custom/headless architecture can produce inconclusive results.
- Vendor signatures are heuristics for triage, not a verified map of every installed merchant app.
- Follow the site's access policies and scan responsibly.

### Pricing and publication

The Actor is in a **private pilot** as of November 5, 2026. Its Apify account currently reports the pricing model as **FREE**; code-level billing telemetry is **not proof of customer revenue**. If published as Pay Per Event, the intended mutually exclusive event configuration is:

| Event | Intended price | Condition |
| --- | ---: | --- |
| `store-audited` | $0.002 | Confirmed Shopify theme, probing enabled, no reachable unmatched legacy script |
| `confirmed-live-unmigrated-lead` | $0.005 | Confirmed theme with one or more reachable legacy script URLs and no detected replacement |
| No event | $0 | Non-Shopify, unverified, blocked or probing disabled |

Prices only become effective when configured in **Apify Console → Publishing → Monetization**. Check the live Pricing tab before running a published Actor. Pricing is per store, not per ScriptTag.

### Technical details

Python 3.11; Apify Python SDK 4.2; public HTTP requests with a single DNS resolution and direct IP-pinned connections (direct mode), SSRF-protected redirects, decompression guards, scoped page parsing, and locally reproducible tests.

For implementation-level validation, see `VALIDATION.md` in the private source repository. The Actor does not modify the merchant storefront.

**Shopify source:** https://shopify.dev/docs/apps/build/online-store/script-tag-deprecation/storefront

# Actor input Schema

## `storeUrls` (type: `array`):

List of public storefront URLs to audit.

## `verifyScriptLiveness` (type: `boolean`):

Perform DNS-pinned HTTP HEAD + Range GET fallback checks on every asyncLoad ScriptTag and Theme App Extension asset URL.

## `scanProductPage` (type: `boolean`):

Automatically discover and scan product, collection, and cart templates alongside the homepage.

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

Number of concurrent worker threads (1-20).

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

Route outbound HTTP requests through Apify Proxy when scanning WAF-protected storefronts.

## Actor input object example

```json
{
  "storeUrls": [
    "https://www.allbirds.com"
  ],
  "verifyScriptLiveness": true,
  "scanProductPage": true,
  "maxConcurrency": 5,
  "useApifyProxy": false
}
```

# Actor output Schema

## `storefrontAudits` (type: `string`):

JSON rows with storefront identity, script reachability, vendor classifications, evidence and limitations.

## `batchSummary` (type: `string`):

Aggregated counts and validation categories for this Actor run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "storeUrls": [
        "https://www.allbirds.com"
    ],
    "verifyScriptLiveness": true,
    "scanProductPage": true,
    "maxConcurrency": 5,
    "useApifyProxy": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("respectful_ninja/shopify-scripttag-migration-auditor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "storeUrls": ["https://www.allbirds.com"],
    "verifyScriptLiveness": True,
    "scanProductPage": True,
    "maxConcurrency": 5,
    "useApifyProxy": False,
}

# Run the Actor and wait for it to finish
run = client.actor("respectful_ninja/shopify-scripttag-migration-auditor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "storeUrls": [
    "https://www.allbirds.com"
  ],
  "verifyScriptLiveness": true,
  "scanProductPage": true,
  "maxConcurrency": 5,
  "useApifyProxy": false
}' |
apify call respectful_ninja/shopify-scripttag-migration-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,respectful_ninja/shopify-scripttag-migration-auditor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/rYtbr8YwTEIYDdY7s/builds/tBgxWA6htw2N6v9wD/openapi.json
