David Abraham Aguilar × MLVeda

Technical overview: the Embed Migration Kit and Cutover

This page is for your lead developer and anyone on the technical side who was not on the call. It explains the two tools I built for the script tag migration: how they are built, how they are tested and deployed, and what they deliberately do not do.

Part 1 · Embed Migration Kit

What it is

The kit is an embedded admin app built on Shopify's React Router app template. The merchant opens it from the Shopify admin. The kit reads the store's script tags and theme files, tells the merchant exactly what to switch on and where, verifies the result with three independent signals, and only then cleans up. It also moves "one variant per country" pricing to Markets price lists.

Stack

Layer What it uses
App framework Shopify app template for React Router 7 (@shopify/shopify-app-react-router v3), Node.js 22
Admin UI Embedded in the Shopify admin through App Bridge, built with Polaris web components (<s-section>, <s-table>, <s-button>)
Shopify APIs Admin GraphQL API 2026-10: scriptTags, scriptTagCreate (only as a live proof), scriptTagDelete, themes / theme.files, Markets catalogs, priceListCreate, priceListFixedPricesAdd, contextualPricing
Storefront Theme app extension with one app embed block (target: body): a country selector that posts Shopify's native localization form, plus a beacon
Data Prisma with SQLite: sessions (including refresh tokens), beacons, extension status snapshots and the removal queue
Auth Expiring offline access tokens with refresh, which is what the Admin API requires from January 1, 2027
Webhooks app/uninstalled, app/scopes_update and the three compliance topics (customers/data_request, customers/redact, shop/redact)

How the data flows

Shopify admin merchant opens the app Embed Migration Kit app server + SQLite Admin GraphQL API 2026-10 Storefront app embed runs App proxy signed by Shopify App Bridge read tags, themes write price lists beacon stored as signal C
The kit talks to Shopify only through the Admin API. The storefront talks back only through the signed app proxy, so a beacon cannot be faked by a third party.

The five stages, per store

  1. Measure. Lists the script tags this app still has registered and scans every theme (layout/theme.liquid, snippets/*, sections/*) for legacy currency code: prices wrapped for JavaScript conversion, old currency pickers and included legacy snippets. Every hit has a file and a line. A "live proof" button asks Shopify to create a script tag and shows the refusal word for word.

  2. Activate. Reads config/settings_data.json for each theme. It strips the leading comment that breaks JSON.parse, handles current being a preset name and matches the block by handle. Then it builds the activation deep link by theme ID, never themes/current, with manual steps as a fallback.

  3. Verify. Enabled is not the same as running. The kit waits for three signals:

    • A · the embed is on in settings_data.json of the live theme;
    • B · app.extensions() reports it active while the merchant is in the app, stored with a timestamp because it only answers then;
    • C · a beacon from the embed, sent through the app proxy, when it actually runs on a storefront page.
  4. Remove. A per-store queue deletes this app's script tags one at a time, only after all three signals are green. It backs off on throttling, using throttleStatus. On 423 Locked it waits 15 minutes, doubling up to 6 hours. Frozen (402), closed (404) and token-rejected stores go to a separate "unreachable" list instead of failing the run. Legacy theme code gets a human cleanup checklist with file, line and "already neutralized by the embed".

  5. Prices by country (only when needed). Finds products that fake a local price with one variant per country and moves the price to Markets:

    • the market's catalog, created if missing and without a publication, so availability stays with the sales channel;
    • a price list in the market's currency;
    • fixed prices in batches of at most 250 (priceListFixedPricesAdd), retried on throttling;
    • an audit with contextualPricing(context: {country}), which compares what Shopify will actually charge with the plan.

    It is idempotent and never deletes variants or products.

Every store also gets a tokens card, showing it runs with expiring offline tokens, and a JSON and CSV report, so many stores can be merged into one migration board.

Design decisions worth knowing

What it cannot do, by design

Data and privacy

The kit stores no customer data. A beacon records the shop, the theme ID, name and role, the page path and a count of legacy markers it neutralized. The compliance webhooks are wired in.

How it is tested

npm test        # Node.js 22 · 12/12 passing (re-run on October 13, 2026)

The 12 unit tests cover the pure logic in app/lib/:

End to end, the full flow ran on a development store. The embed was switched on, all three signals went green, the selector appeared on the storefront and a product's price in Mexico moved from a converted 16,558 MXN to a fixed 15,999 MXN.

How it is deployed

From the first commit to the production release with price lists took under 3 hours of wall-clock time (October 10, 2026).

Part 2 · Cutover

What it is

Cutover is a "migration control room" for the team that runs the migration. It is an installable PWA, in English and Spanish, that works offline. It was built on the morning of October 13, 2026.

What each view does

View What it does
Board A countdown to the day script tags stop loading, and a departure board of every dated Shopify platform change since 2024. Each change links to its source and carries a confidence label: official, secondary or community.
Manuals Step-by-step migration manuals with copyable code. A shared "code context" (store, app name, block handle) fills every snippet, so the code is ready to paste. Official facts and field notes are labeled differently. Teams can write their own manuals in Markdown, export them and share them as a link.
Fix "Diagnose a migration": a decision tree that ends in a fix, plus a filterable troubleshooting table of problems developers actually hit (draft themes, 423, settings_data.json, and more).
Tools Tools that run entirely in the browser, so nothing pasted leaves the page:
  • a theme scanner that reads theme.liquid or a whole theme .zip and finds legacy markers and a silently broken </body>, with file and line;
  • a settings_data.json inspector;
  • an activation link builder by theme ID, with a QR code;
  • a queue and backoff calculator for 423;
  • merchant email templates for activation and cleanup approval;
  • a price-list batch builder that turns a CSV into batches of 250;
  • a token inspector that says whether a token survives January 1, 2027.
Stores The same stages as a per-store checklist, with the runbook's verdicts. Exports to CSV and JSON.
Tracker A dashboard, task list and roadmap for the whole migration. Every task has a tutorial and a "done when" check. It shows progress by phase, the next deadline and recent activity, and exports to CSV.

How it is built

Next step

Happy to walk your lead developer through the code live.