Skip to content

Shopify Import

Import products, customers, and orders from Shopify — either from Shopify's CSV exports or live from the Shopify Admin API. Use it when migrating a store off Shopify onto Vectis: both source modes normalize to the same field names, so one reviewed mapping works for either, and Shopify metafields are auto-routed into Vectis custom fields so a customized shop migrates without manual mapping.

At a glance

Extension id shopify
Category migration
Version 0.1.0
Provides Import provider (products, variants, images, customers, orders)
External account Shopify Admin API access token (Admin API mode only; CSV mode needs none)

What It Provides

  • An import provider with key shopify (label "Shopify"), registered on the strategy resolver when the extension activates. It appears in the provider list of the admin Import Wizard via the importProviders GraphQL query.
  • Two source modes: csv (Shopify CSV exports) and admin_api (Shopify Admin REST API).
  • Five entity types: product, variant, image, customer, order, with a dependency DAG — variants and images require products; orders require customers, products, and variants. Runs import dependencies before dependents, and the wizard flags unselected prerequisites.
  • Default field mappings per entity (e.g. product nameTitle, slugHandle, descriptionBody (HTML) stripped of HTML tags, status mapped activepublished / draftdraft / archivedarchived). Discovered metafield.* source fields are automatically routed into custom_fields.
  • Import runs execute through the core ImportRunWorkflow Temporal workflow (Building Extensions covers the strategy surface). The extension itself registers no workflows, webhook endpoints, admin pages, or GraphQL fields of its own.

Setup

  1. The extension loads at boot; it should appear under Settings > Extensions.
  2. Open Settings > Import Wizard in the admin (/settings/import).
  3. Provider step: pick Shopify.
  4. Entities step: choose what to import. The wizard flags unselected prerequisites (e.g. picking order without product/variant/customer) and offers to add them, so cross-entity references stay linked.
  5. Connect step:
    • CSV / spreadsheet upload — upload the Shopify export CSV for each selected entity. The products export backs the product, variant, and image entities; separate customers and orders exports back the rest.
    • Live Admin API — enter the connection config as JSON: shop_domain, access_token, and optionally api_version (see the reference below).
  6. Map & review step: the provider's default mapping is pre-filled per entity; unmapped source fields can be routed into custom_fields, and each entity's mapping can be saved as a reusable import profile.
  7. Dry run step: previews create/update/skip/fail counts without writing anything — every row runs in a savepoint that a dry run rolls back.
  8. Run step: executes the import.

There is no separate test-connection step in the wizard: bad credentials surface when the wizard first discovers source fields on the way into Map & review. (The connector implements a test_connection hook that fetches shop.json, but no wizard step currently invokes it.)

Configuration Reference

This provider has no extension-level config_schema — connection details are entered per run in the wizard's Connect step and are not stored (the persisted import-run record keeps the plan, not the connection config). Per source mode:

CSV mode

Key Type Required Secret Description
contents object No No Shopify CSV exports keyed by products/customers/orders

Admin API mode

Key Type Required Secret Description
shop_domain string Yes No e.g. acme.myshopify.com
access_token string Yes Yes Shopify Admin API access token, sent as X-Shopify-Access-Token
api_version string No No Defaults to 2024-01

Permissions

The manifest declares no permissions of its own. Running imports and saving mapping profiles require the core import_export.import permission.

Operational Notes

  • Admin API pagination — cursor pagination via the Link response header, 250 records per page. Requests use a 60-second HTTP timeout.
  • Metafields — the API connector surfaces product and customer metafields as metafield.<namespace>.<key> source fields; the default mapping auto-routes them into custom_fields.
  • CSV reshaping — Shopify's products export is multi-row-per-product: the first row of a Handle group is the product, rows with a Variant SKU become variants, and rows with an Image Src become images. The orders export is grouped by Name: the first row of a group carries the order-level fields, and every row with a Lineitem name or Lineitem sku contributes a line item. Shopify has no standard collection CSV export, so collections are not an importable entity here.
  • Orders import as historical records — the default (and currently only working) order_import_mode is historical: order and line rows are written without triggering payment, inventory, or fulfillment workflows, and imported orders are stamped _imported in metadata. Selecting live mode is rejected by the order loader (it raises per row instead of silently re-entering workflows).
  • Order lines must resolve to variants — each order line is matched to an existing variant by SKU; an unresolvable line fails that order's row. Import products and variants before orders.
  • Idempotent re-runs — each successfully imported row records a (provider, entity, external_id) → internal id crossref, and loaders upsert by natural key: slug for products, SKU for variants, email for customers, order number for orders. In the default mapping those keys and the external ids come from the same source columns (Handle, Variant SKU, Email, Name), so re-running an import updates existing records instead of duplicating them.
  • Failure isolation — every row runs inside a database savepoint, so one bad row cannot poison the rest; failures are collected into the run's error report.
  • Durability — runs execute as the core ImportRunWorkflow on the vectis-main Temporal task queue, with a 30-minute activity timeout and up to 3 retry attempts.

See also: WooCommerce Import, Building Extensions.