\n {% break %}\n {% endif %}\n{% endfor %}","targetProduct":"Shopify"},{"@type":"SoftwareSourceCode","name":"Pre-Launch SEO Audit","programmingLanguage":"text/plain","codeSampleType":"snippet","text":"Trigger: Manual workflow start or scheduled daily at 2 AM\n\nCondition: Check if \"migration_stage\" metafield equals \"pre_launch\"\n\nActions:\n 1. Send HTTP request to Heroku crawl service:\n POST /crawl/validate-redirects\n Body: { legacy_domain: \"original-site.com\", shopify_domain: \"new-site.myshopify.com\" }\n 2. Wait for response; parse redirect_success_count and redirect_fail_urls\n 3. If redirect_fail_urls.length > 0:\n → Slack notification: \"Redirect audit failed on {{redirect_fail_urls.count}} URLs — review dashboard\"\n 4. If all pass:\n → Email store owner: \"Pre-launch audit passed. Safe to flip DNS.\"","targetProduct":"Shopify"}]} \n {% break %}\n {% endif %}\n{% endfor %}"}]},{"@type":"HowToStep","position":3,"name":"Historical Order Archive","text":"Stores your complete order history in a secure, queryable archive with original timestamps and customer data intact, accessible to your team without cluttering Shopify's native order interface. (Paste target: Postgres archive schema.)"},{"@type":"HowToStep","position":4,"name":"Pre-Launch SEO Audit","text":"Runs an automated crawl of your live legacy site, builds the redirect map, tests every 301 response, and flags broken or missing mappings before you cut over DNS. (Paste target: Shopify Flow editor: When → Then.)","itemListElement":[{"@type":"HowToDirection","text":"Trigger: Manual workflow start or scheduled daily at 2 AM\n\nCondition: Check if \"migration_stage\" metafield equals \"pre_launch\"\n\nActions:\n 1. Send HTTP request to Heroku crawl service:\n POST /crawl/validate-redirects\n Body: { legacy_domain: \"original-site.com\", shopify_domain: \"new-site.myshopify.com\" }\n 2. Wait for response; parse redirect_success_count and redirect_fail_urls\n 3. If redirect_fail_urls.length > 0:\n → Slack notification: \"Redirect audit failed on {{redirect_fail_urls.count}} URLs — review dashboard\"\n 4. If all pass:\n → Email store owner: \"Pre-launch audit passed. Safe to flip DNS.\""}]}]}
Tom Sailors
Brief · Anonymized case study

WooCommerce to Shopify Plus Migration

I'd approach this as a four-phase build: pull the product catalog and inventory via WooCommerce's REST API into Shopify using the Admin GraphQL, store the original WC product IDs as metafield references for traceability; build a URL router that intercepts old paths and serves proper 301 responses to preserve SEO signals; archive the full order history in a queryable Postgres schema outside Shopify (the Admin API has no archive layer); and run an automated pre-launch crawl that validates every redirect and flags breaks before you flip DNS. The merchant gets a clean inventory handoff, zero broken links, and a searchable record of every legacy transaction.

A mid-market DTC merchant with eight years of operational history on WooCommerce needed to migrate to Shopify Plus without losing SEO equity, breaking legacy URLs, or severing access to historical order records. The challenge combined technical scope—preserving 301 redirect chains at scale, importing orders with original timestamps, and maintaining inventory accuracy—with the business risk of downtime and organic traffic loss during cutover.
Four pieces
Migration

Product & Inventory Import

Pulls your product catalog, SKUs, pricing, inventory, and custom fields from the legacy platform into Shopify Plus, storing the original product IDs as reference data so you can trace any discrepancies later.

Custom Shopify app + Heroku backend
Admin GraphQL explorer graphql
# Admin GraphQL — bulk product + metafield import
query GetProductsForImport($first: Int!) {
  products(first: $first) {
    edges {
      node {
        id
        title
        handle
        productType
        vendor
        variants(first: 100) {
          edges {
            node {
              id
              sku
              barcode
              price
              inventoryQuantity
            }
          }
        }
        metafields(first: 100, namespace: "wc_legacy") {
          edges {
            node {
              id
              namespace
              key
              value
            }
          }
        }
      }
    }
    pageInfo { hasNextPage endCursor }
  }
}

mutation ImportProduct($input: ProductInput!) {
  productCreate(input: $input) {
    product {
      id
      title
      handle
    }
    userErrors { field message }
  }
}
Pair with a CSV or JSON export from the legacy REST API; use metafieldsSet to store original product IDs under a custom namespace for traceability.
Migration

URL Redirect Router

Maps every product, category, and page URL from your legacy platform to its new Shopify equivalent, serving 301 redirects that search engines recognize and preserving all backlink authority.

Shopify Plus theme extension + Heroku redirect service
theme/snippets/legacy-redirect-check.liquid liquid
{% comment %}
  Legacy URL redirect checker — intercept old URLs and 301 them to new Shopify ones.
  Store redirect map in a JSON metafield on the store's settings.
{% endcomment %}

{% assign legacy_redirects = shop.metafields.migrations.url_map | parse_json %}
{% assign current_path = request.path | downcase %}

{% for mapping in legacy_redirects %}
  {% if current_path == mapping.old_path %}
    {% comment %} Match found; render 301 redirect {% endcomment %}
    <meta http-equiv="refresh" content="0; url={{ mapping.new_url }}" />
    <script>
      if (navigator.userAgent.indexOf('Googlebot') !== -1 || navigator.userAgent.indexOf('bingbot') !== -1) {
        window.location.href = '{{ mapping.new_url }}';
      }
    </script>
    {% break %}
  {% endif %}
{% endfor %}
For true HTTP 301 responses (not meta-refresh), use a Heroku middleware that intercepts requests and returns the proper status code; upload the redirect map as a Shopify metafield CSV.
Operations

Historical Order Archive

Stores your complete order history in a secure, queryable archive with original timestamps and customer data intact, accessible to your team without cluttering Shopify's native order interface.

Postgres database + custom admin dashboard
Migration

Pre-Launch SEO Audit

Runs an automated crawl of your live legacy site, builds the redirect map, tests every 301 response, and flags broken or missing mappings before you cut over DNS.

Crawl service + Heroku validation job
Shopify Flow editor: When → Then flow
Trigger: Manual workflow start or scheduled daily at 2 AM

Condition: Check if "migration_stage" metafield equals "pre_launch"

Actions:
  1. Send HTTP request to Heroku crawl service:
     POST /crawl/validate-redirects
     Body: { legacy_domain: "original-site.com", shopify_domain: "new-site.myshopify.com" }
  2. Wait for response; parse redirect_success_count and redirect_fail_urls
  3. If redirect_fail_urls.length > 0:
     → Slack notification: "Redirect audit failed on {{redirect_fail_urls.count}} URLs — review dashboard"
  4. If all pass:
     → Email store owner: "Pre-launch audit passed. Safe to flip DNS."

Got a similar problem?

Sketch your build in 30 seconds — voice, type, or attach a screenshot.

Sketch the build →