The Architectural Chasm: Magento EAV vs. Shopify Resource Models
For mid-market merchants and enterprise retailers throughout the Wirral—from industrial distribution hubs in Bromborough to multi-channel operations across Birkenhead and Heswall—migrating off legacy Magento (Adobe Commerce) environments is an architectural imperative. However, legacy Magento installations (both 1.9.x legacy builds and heavily customized 2.4.x platforms) rely on an Entity-Attribute-Value (EAV) database structure that fundamentally conflicts with Shopify’s normalized, API-first resource architecture.
In Magento, a single product record is fractured across dozens of relational database tables (including catalog_product_entity, catalog_product_entity_varchar, catalog_product_entity_int, and catalog_product_entity_decimal). Reconstructing this relational web into clean, performant payloads requires deep extraction, transformation, and load (ETL) engineering before injecting records into Shopify’s variant and metafield constructs. As detailed in our comprehensive guide to Migrating Existing Wirral Retail Websites to Shopify from WooCommerce or Magento, failure to map these complex attributes accurately undermines catalog integrity, breaks historical accounting, and ruins customer accounts.
Delivering enterprise-grade Shopify Wirral deployments requires navigating product schema transformations, managing historical transactional pipelines, and resolving API rate limits when porting millions of data points into Shopify Plus.
Extracting and Normalizing the Magento Catalog Schema
Magento allows merchants to define near-infinite global, website, and store-view scoped attributes. Shopify historically bound products to a rigid construct: one base product with up to 3 options and 100 variants (expanding in contemporary GraphQL schemas via the Combined Listings architecture and updated variant limits). Mapping complex Magento entities into this model requires distinct algorithmic separation.
1. Simple Products with Custom Options
Magento simple products often carry customizable options (e.g., text engravings, custom dimensions, bespoke finishes) that do not possess distinct inventory tracking. In Shopify, these should not be forced into variants if they exceed the option threshold. Instead, transform these into line-item properties handled via UI extensions on the storefront, backed by custom metafield configurations on the product object to define the validation rules.
2. Configurable to Variant Normalization
Configurable products represent the standard parent-child relationship in Magento. The parent entity holds descriptive content and media, while associated simple products contain SKU, inventory, price, and specific super-attribute axes (e.g., Size, Colour).
During extraction, your ETL pipeline must query the catalog_product_super_link and catalog_product_super_attribute tables to extract the permutation matrix:
SELECT
parent.entity_id AS parent_id,
parent.sku AS parent_sku,
child.entity_id AS child_id,
child.sku AS child_sku,
ea.attribute_code,
eaov.value AS attribute_value
FROM catalog_product_super_link link
INNER JOIN catalog_product_entity parent ON link.parent_id = parent.entity_id
INNER JOIN catalog_product_entity child ON link.product_id = child.entity_id
INNER JOIN catalog_product_super_attribute cpsa ON cpsa.product_id = parent.entity_id
INNER JOIN eav_attribute ea ON cpsa.attribute_id = ea.attribute_id
INNER JOIN catalog_product_entity_int cpei ON cpei.entity_id = child.entity_id AND cpei.attribute_id = ea.attribute_id
INNER JOIN eav_attribute_option_value eaov ON cpei.value = eaov.option_id AND eaov.store_id = 0;
This dataset must be pivoted to construct the Shopify variants array under a unified parent handle. If the permutation count exceeds 100 variants, split the parent product into sibling products grouped by a primary axis (e.g., Colour) using a shared metafield (custom.family_id) to dynamically link the siblings via a collection or GraphQL-driven swatch component.
3. Bundle and Grouped Product Resolution
Magento Bundle and Grouped products have no native 1:1 parity in standard Shopify architecture:
- Grouped Products: Flatten into individual Simple Products, tagged identically, and aggregated on the collection template, or leverage Shopify’s GraphQL
productBundlecomponents or modern native bundling APIs. - Bundle Products (Dynamic Pricing/Kitting): Extract the constituent SKU rules from
catalog_product_bundle_selectionandcatalog_product_bundle_option. Implement Shopify Bundles via the Bundles API or link individual inventory items using custom draft orders and inventory management middleware (e.g., Linnworks, Mintsoft) prevalent across Merseyside logistics operations.
4. Custom Attribute Preservation via Metafields
Attributes critical for B2B operations, compliance, or local technical components (e.g., hazardous material flags, localized delivery rules, Wirral council trade licenses, custom spec sheets) must not be concatenated into the product description HTML. Instead, create programmatic Metafield Definitions via the Shopify Admin GraphQL API prior to ingestion:
mutation CreateProductMetafieldDefinition {
metafieldDefinitionCreate(definition: {
name: "Technical Specification Sheet",
namespace: "specifications",
key: "pdf_url",
type: "file_reference",
ownerType: PRODUCT
}) {
createdDefinition {
id
namespace
key
}
userErrors {
field
message
}
}
}
ETL Pipeline: Handling Assets, Media, and Local SEO Handle Mapping
Magento stores catalog images across an internal hashing directory (e.g., /media/catalog/product/a/b/ab123_image.jpg). Exporting this data requires resolving records from catalog_product_entity_media_gallery and catalog_product_entity_media_gallery_value to retain image labels (alt tags) and ordering positions.
Automating Asset Ingestion
Rather than uploading images sequentially over REST (which triggers 429 Too Many Requests errors), stage images in an accessible public bucket (e.g., AWS S3 or Cloudflare R2). In the product creation GraphQL payload, inject URLs via the media input object. Shopify’s background workers asynchronously fetch, optimize, convert to WebP, and host these assets on their global CDN infrastructure.
SEO Handle Parity and Redirection
Preserving established search rankings for Wirral retail operations requires precise handle generation. Magento generates URL keys stored in url_rewrite. When mapping:
- Extract the original
request_pathwhereentity_type = 'product'. - Sanitize the path into a compliant Shopify handle (lowercased, alphanumeric, hyphen-delimited, stripping trailing
.html). - If legacy paths differ from the Shopify
/products/[handle]schema, construct an automated 301 redirect map for upload via Shopify’surlRedirectImportCreateGraphQL mutation to maintain equity across regional search surfaces.
Historical Order Data Migration: Financial and Structural Integrity
Historical order migrations represent the highest risk factor in platform transitions. Inaccurate order ingest breaks VAT reporting, skews lifetime value (LTV) cohorts, disrupts third-party ERP synchronizations, and causes customer friction if accounts fail to reflect prior purchases.
Extracting the Sales Data Warehouse
Do not export orders using Magento’s flat sales grid tables alone, as they frequently fall out of sync with raw transactions. Extract transactional records directly from the base sales tables:
sales_order: Header data, tax calculations, discounts, shipping addresses, customer linkages.sales_order_item: Line-item level SKU, quantity, pricing, discounts, tax percentages, and product options.sales_order_payment: Historical payment method data (e.g., SagePay/Opayo, Barclaycard, PayPal).sales_order_status_history: Customer comments, tracking numbers, and state transition timestamps.
Status and Lifecycle Mapping
Magento uses a dual state and status machine, whereas Shopify splits order states into financial_status, fulfillment_status, and general order lifecycle. Map these states methodically:
| Magento State / Status | Shopify Financial Status | Shopify Fulfillment Status |
|---|---|---|
processing / processing |
PAID |
UNFULFILLED |
complete / complete |
PAID |
FULFILLED |
closed / closed |
REFUNDED |
FULFILLED (or RESTOCKED) |
canceled / canceled |
VOIDED |
UNFULFILLED |
holded / holded |
PAID or AUTHORIZED |
ON_HOLD |
UK VAT and Tax Normalization
For Wirral retailers filing VAT returns to HMRC, historical data must accurately distinguish between 20% Standard Rate VAT, reduced rate items, zero-rated goods (e.g., children’s clothing, specific food products), and non-taxable shipping surcharges. When preparing the Shopify order payload, map tax lines explicitly to prevent Shopify from auto-calculating modern tax rates across legacy orders:
"tax_lines": [
{
"price": "24.50",
"rate": 0.20,
"title": "UK VAT"
}
]
Set send_receipt: false and inventory_behaviour: "bypass" to ensure that historical insertions do not trigger customer notifications or decrement active warehouse physical inventory allocations.
Customer Entity Deduplication and Password Migration
Magento identifies customers by an entity_id scoped to a website_id. Shopify identifies customers globally across a store by their email address or unique phone number. Wirral retailers with long-standing retail histories often suffer from split accounts where the same customer ordered via multiple guest checkouts or distinct store views.
Customer Unification Pipeline
- Extract unique customer identities based on a normalized lowercase email address.
- Merge order histories from guest orders where
sales_order.customer_emailmatches the primary customer identity. - Aggregate all known shipping and billing addresses into the customer’s
addressesarray, setting the most recent billing location as the default.
The Password Hash Barrier
Magento 1 used MD5 or SHA256 hashes with custom salts; Magento 2 utilizes Argon2ID13 or Bcrypt with SHA256 cryptographic chaining. Shopify does not permit arbitrary ingestion of external password hashes through standard APIs. You have two technical pathways to address this:
- Multipass Authentication (Shopify Plus): Retain a headless authentication microservice that validates the customer’s legacy password against the Magento hash. Upon a valid hit, generate an encrypted Multipass token and seamlessly establish a authenticated Shopify customer session.
- Automated Account Activation Workflows: Ingest customer records with their historical orders attached, leaving accounts in a
DISABLEDstate. Execute an automated email sequence inviting the user to claim their account, redirecting them to a secure tokenized activation URL (/account/activate/[customer_id]/[token]) to establish a new password compliant with Shopify’s identity infrastructure.
High-Throughput Execution: Bulk Ingestion via GraphQL
Migrating catalogs with 50,000+ SKUs and hundreds of thousands of historical orders via the traditional REST Admin API triggers Shopify’s leaky bucket rate limit (40 requests per minute on standard plans; up to 80-100 on Plus). Attempting sequential REST calls will extend migrations across days, introducing data divergence.
The solution is Shopify’s GraphQL bulkOperationRunMutation or the specialized orderCreate asynchronous API.
Bulk Operation Mutation Pattern
Construct a JSON Lines (JSONL) file containing your mutation definitions. For instance, creating variants and products:
{"input":{"title":"Chester Road Heritage Jacket","handle":"chester-road-heritage-jacket","vendor":"Wirral Outfitters","productType":"Apparel","status":"ACTIVE"}}
{"input":{"title":"Heswall Tweed Overcoat","handle":"heswall-tweed-overcoat","vendor":"Wirral Outfitters","productType":"Apparel","status":"ACTIVE"}}
Upload the generated JSONL to a Shopify-provided Google Cloud Storage stage endpoint, then trigger the bulk operation:
mutation RunProductImport {
bulkOperationRunMutation(
mutation: "mutation call($input: ProductInput!) { productCreate(input: $input) { product { id } userErrors { message } } }",
stagedUploadPath: "tmp/magento_migration_products.jsonl"
) {
bulkOperation {
id
status
}
userErrors {
field
message
}
}
}
Shopify processes these jobs on isolated background clusters at significant scale, entirely bypassing the local API rate limit barriers that constrain traditional migration scripts.
Post-Migration Data Reconciliation and Auditing
Before switching your DNS pointers from the legacy Magento server to Shopify’s edge network, run rigorous programmatic validation scripts across the migrated data sets.
1. Financial Total Cross-Check
Run SQL queries against the Magento database to aggregate gross sales, net sales, total tax collected, and refund totals grouped by month. Execute an identical extraction query against Shopify via the GraphQL orders query (or run raw data warehouse queries on BigQuery/Snowflake if utilizing Shopify Plus with ShopifyQL data sync).
SELECT
DATE_FORMAT(created_at, '%Y-%m') AS order_month,
COUNT(entity_id) AS total_orders,
SUM(grand_total) AS gross_revenue,
SUM(tax_amount) AS total_tax,
SUM(shipping_amount) AS total_shipping
FROM sales_order
WHERE status NOT IN ('canceled')
GROUP BY order_month
ORDER BY order_month DESC;
Reconcile this output directly against the imported Shopify financial summaries. Variances exceeding 0.01% typically indicate line-item discounts being applied post-tax rather than pre-tax, or mismatches in currency exchange calculations on international orders.
2. SKU and Inventory Audit
Execute an automated diff match verifying that every SKU in Magento’s cataloginventory_stock_item correlates with an identical SKU on Shopify. Verify that:
- Active available inventory matches real physical stock levels.
- Inventory tracking (
tracked: true) is correctly applied to physical goods and disabled on virtual/service products. - Barcode (EAN/UPC) values are intact, preventing downtime for barcode-driven pick-and-pack stations operating within local Wirral warehouse facilities.
3. Data Integrity Sign-Off
Once reconciliation scripts clear without exceptions, disable write access on the legacy Magento instance (switch to maintenance mode), perform one final delta sync of orders placed within the cutover window, and transition primary domain records to Shopify. This process ensures data accuracy, regulatory tax compliance, and seamless operational continuity for your local retail brand.