Changes

Comparing empty160dc49.

@@ -1,0 +1,73 @@
1+---
2+title: Migrating from Shopify
3+sort: 2
4+tags: [migration]
5+---
6+
7+# Migrating from Shopify
8+
9+A migration takes between an afternoon (10 SKUs, no historical orders) and several days (100k SKUs,
10+two years of order history). Three phases.
11+
12+## Phase 1 — Export from Shopify
13+
14+Use Shopify's GraphQL Admin API. The CLI has a helper that runs the exact queries we need:
15+
16+```bash
17+zephyr migrate shopify pull \
18+ --shop my-shop.myshopify.com \
19+ --token shpat_… \
20+ --out ./shopify-export/
21+```
22+
23+This writes one JSON file per resource type: `products.jsonl`, `customers.jsonl`,
24+`orders.jsonl`, `collections.jsonl`. Each line is one Shopify record, untouched.
25+
26+## Phase 2 — Map and validate
27+
28+Mapping is where most of the work lives. The CLI's default rules cover the 80 % case:
29+
30+| Shopify field | ZephyrCart field |
31+|-----------------------------|---------------------------------------------------|
32+| `product.handle` | `product.sku` (if no other SKU set) |
33+| `product.product_type` | First collection assignment |
34+| `variant.sku` | `variant.sku` |
35+| `variant.price` (string) | `variant.default_price_cents` (× 100) |
36+| `customer.email` | `customer.email` |
37+| `customer.default_address` | `customer.addresses[0]`, `is_default: true` |
38+| `order.line_items[]` | `order.line_items[]` |
39+
40+Override any rule with a `mapping.toml` next to the export:
41+
42+```toml
43+[product]
44+sku_from = "variants[0].sku"
45+
46+[customer]
47+exclude_if_marketing_opt_out = false
48+```
49+
50+Validate before importing:
51+
52+```bash
53+zephyr migrate shopify validate --in ./shopify-export/ --mapping ./mapping.toml
54+```
55+
56+The validator reports field-by-field anything ZephyrCart can't accept (currencies it doesn't
57+recognise, SKUs longer than its limit, etc.). Fix at the source, re-export, re-validate.
58+
59+## Phase 3 — Import
60+
61+```bash
62+zephyr migrate shopify push --in ./shopify-export/ --mapping ./mapping.toml --concurrency 8
63+```
64+
65+The CLI streams resources to the API with idempotency keys derived from the Shopify ID, so a
66+re-run of an interrupted import is safe. Progress is checkpointed to `./shopify-export/.zephyr-state`.
67+
68+## What we do not migrate
69+
70+- **Shopify scripts** — no equivalent in ZephyrCart; checkout rules express most of what scripts do.
71+- **Shopify Markets** — model the same shape with our [tax zones](../api-reference/products.md).
72+- **Custom apps' metafields** — these come through as `product.metadata` keys prefixed with the
73+ app handle; review and rename before going live.