PS PrestaShop Intermediate

DataFirefly Shopify Migrator — Complete guide

Migrate your PrestaShop 8/9 catalog to Shopify — products, variants, customers, collections, CMS pages, features and 301 redirects, in CSV or API mode.

Updated Module version 1.5.0

Overview

DataFirefly Shopify Migrator is a PrestaShop 8 and 9 module that exports your entire catalog to Shopify, with two modes to choose from: CSV (generates files ready to import manually via the Shopify admin, no API key required) or API (direct push to a connected Shopify store via the Admin REST API 2026-04).

The module handles eight entities, typically migrated in this order:

  • Products — full product records, variants up to 3 attribute groups, images, stocks, prices excluding or including tax, SEO meta preserved via global title_tag/description_tag metafields
  • Collections — PrestaShop categories converted to custom collections with image and description
  • CMS Pages — PrestaShop pages converted to Shopify pages with slug and SEO meta
  • Customers — customer records + default address + order statistics, tagged imported-prestashop
  • Orders — consultative CSV export only (Shopify does not accept native order imports via standard CSV)
  • 301 Redirects — mapping table from old PrestaShop URLs to new Shopify URLs to preserve search rankings
  • Repair images and Variant images — two repair jobs to recover images Shopify silently lost during async fetch, and to wire each Shopify variant to its image
  • Features → Metafields — pushes PrestaShop product features as Shopify metafields with automatic Metafield Definition creation via GraphQL

The architecture is asynchronous and job-based: each migration creates a job in the database, then processed in configurable batches via a token-protected cron worker. Shopify rate limits are respected automatically (1.8 req/s, 429 retry), and a persistent ID mapping in the database links PrestaShop identifiers to Shopify identifiers, enabling redirects and avoiding duplicates on re-runs.

Requirements

  • PrestaShop 8.0 to 9.x
  • PHP 7.4 to 8.3
  • For API mode: a target Shopify store (Basic plan is enough), a Shopify Partners account or access to the Shopify Dev Dashboard
  • For cron mode: the ability to schedule a URL on your host (crontab, cron-as-a-service, or Plesk/cPanel)
  • Server side: PHP curl and iconv extensions enabled

Installation

  1. Download the ZIP from your DataFirefly customer account (Downloads section of the product page).
  2. In the PrestaShop back office, go to Modules → Module Manager → Upload a module, drop the ZIP.
  3. Click Install. The module creates three tables (jobs, mapping, log) and a dedicated tab under Advanced Parameters → Shopify Migrator.
  4. Click Configure to access the main interface.
First reflex: start in CSV mode for risk-free testing. No API key required, and you can inspect the generated files before importing them into Shopify.

Choosing between CSV mode and API mode

CSV mode

The module generates CSV files in the native format expected by Shopify Admin (Products Import, Customers Import, URL Redirects Import). You download each file from the Jobs tab and import it manually into Shopify.

Advantages: no API key to configure, ability to inspect and adjust the files before import, very fast processing on the PrestaShop side.

Limitations: Shopify collections have no native CSV import (the generated file serves as a reference), and orders are never importable via standard CSV on the Shopify side.

API mode

The module sends each entity directly to your Shopify store via the Admin REST API 2026-04, with rate limit handling, automatic retry on 429 errors, and persistent ID mapping for automatic redirects and idempotent re-runs.

Advantages: end-to-end migration in one command, redirects pushed directly, collections created automatically with product attachment, perfect for large catalogs.

Limitations: requires a Shopify app with the right scopes, and some Shopify organizations created after April 2025 are GraphQL-only (the module remains REST-compatible for standard organizations).

API mode: creating the Shopify app

Important: since January 1, 2026, the legacy “Settings → Apps → Develop apps” flow has been deprecated. You must use the Shopify Dev Dashboard. Tokens are no longer shown directly in the Shopify admin — they must be exchanged via Client Credentials Grant (CCG).

Creating the app in the Dev Dashboard

  1. Log in to the Shopify Dev Dashboard (dev.shopify.com/dashboard) with your Partners account.
  2. Click Create app, name it (for example “Migrator”), and confirm.
  3. On the configuration screen, the App URL can be left to any valid HTTPS value. It is only used for OAuth, which does not concern our case.

Configuring scopes

In Configuration → Admin API integration → Configure access scopes, enable the following scopes:

  • read_products, write_products
  • read_customers, write_customers
  • read_content, write_content
  • read_inventory, write_inventory
  • read_online_store_pages, write_online_store_pages
  • read_online_store_navigation, write_online_store_navigation
  • write_metaobject_definitions (only if you use the Features → Metafields entity)

Click Save.

Installing on the target store

  1. In Distribution, choose Custom distribution and add your target Shopify store.
  2. Click the generated install link, which opens the merchant consent screen on the Shopify Admin side.
  3. Confirm the installation: you reach the final app screen.
If you modify scopes after installation, the merchant will not have approved the new ones. Uninstall and reinstall the app to refresh consent, otherwise you will get This action requires merchant approval for scope_name on the affected calls.

Retrieving Client ID and Client Secret

In Settings → Credentials of the app, copy the Client ID, then click the eye icon next to Secret to reveal and copy it.

The App Automation Token is not an Admin API token. It only authenticates Shopify CLI for CI/CD deployments. Do not use the “Create token” button in that section to configure the module.

API mode: configuring credentials

In the module’s Settings tab, choose the Shopify Admin REST API mode, then fill in:

  • Shopify store domain — either the short name (my-store) or the full domain (my-store.myshopify.com).
  • API version — defaults to 2026-04, the current stable version.
  • Authentication method — two choices are available:

Method 1: Admin access token

For the rare cases where you already have a valid Admin API token (legacy custom app or token obtained manually via OAuth). Paste the token in the dedicated field and save.

The module exchanges your Client ID + Client Secret for an Admin API access token via the OAuth Client Credentials Grant flow. The token is cached (24 h), automatically refreshed less than 5 minutes before expiration. No manual intervention required during migration.

Fill in both fields and save. Click Test connection: the module shows your Shopify store name and the time remaining before token expiration.

CCG limitation: your Shopify store and your Dev Dashboard app must belong to the same Shopify organization. On a paid store outside the organization, Shopify returns shop_not_permitted. In that case, either link the store to your Partners organization, or obtain a token manually via Authorization Code Grant OAuth (outside the module’s scope).

Products migration

Product export is the most complex. It handles products, variants (up to 3 attribute groups as Shopify allows), images (absolute URL from your PrestaShop), stocks, prices, manufacturers used as vendor, categories converted to tags and type, SEO meta preserved via global.title_tag and global.description_tag metafields.

Starting the job

  1. In Run a migration, select the Products card.
  2. Click Create export job. The job appears in the Jobs tab list with the pending status.
  3. If you configured the cron, the worker picks it up within the next minute. Otherwise click the Run now button to advance it synchronously (limited by PHP timeout, around 30 seconds).

Progress tracking

The Jobs tab auto-refreshes every 10 seconds. Each row shows the status (pending/running/done/failed/cancelled), progress percentage, success and error counts, and a collapsible log button that displays the last 30 log lines.

CSV mode case

The file job_X_products.csv is generated in Shopify Products Import format. Download it from the jobs list, then in Shopify Admin go to Products → Import and drop the file. Shopify handles the processing on its side, with an email notification when done.

Collections migration

PrestaShop categories (excluding root and category ID 1) become Shopify custom collections, with their title, description, image, SEO meta and the cleaned slug. In API mode, products already migrated are automatically attached to each collection via the /collects.json endpoint.

Order matters: in API mode, migrate products before collections, otherwise the Shopify ID mapping is not yet available and products cannot be attached.

CMS pages migration

Active PrestaShop pages are exported as Shopify pages with their title, HTML content (relative image URLs are automatically resolved to absolute URLs pointing to your PrestaShop domain), slug and SEO meta.

Customers migration

For each active, non-deleted customer, the module exports the name, email, default address, total spent, valid order count, and newsletter opt-in. Each customer receives the imported-prestashop tag for easier later filtering.

Passwords are not migrated, by design for security. Shopify will send a reset invitation to each of your customers on your first commercial send.

Orders migration (CSV only)

Orders export is consultative: Shopify does not offer native order import via standard CSV. The generated file contains all useful information for archive or analysis: reference, date, status, customer, billing and shipping addresses, currency, totals excluding and including tax, carrier, tracking, and one line per product purchased.

You can filter by date range in the job creation form (Orders from and Orders to fields).

For Shopify Plus users, third-party tools like Matrixify accept this format as input for true re-importation.

301 redirects migration

This is the key point to preserve your search rankings on domain switch day. The module reads the mapping table built by the previous exports (products, collections, pages) and generates a two-column CSV in the native Shopify URL Redirects format, with old PrestaShop URLs in the first column and new Shopify URLs in the second.

In API mode, the module directly pushes each redirect via POST /redirects.json. In CSV mode, import the file in Shopify Admin via Online Store → Navigation → URL Redirects → Import.

Redirects must be migrated last, after products, collections and CMS pages. They consume the mapping table built by those three previous jobs.

Exclusion filters (v1.1)

Two optional filters allow you to exclude products from the export, configurable in Settings → Product filters (exclusions).

Exclude categories

Text field with a comma-separated list of PrestaShop category IDs. A product belonging to at least one of these categories is excluded from the Products export. The categories themselves remain migrated by the Collections entity (useful if a technical category should not be displayed but may contain products).

Exclude reference prefixes

Text field with a comma-separated list of prefixes. Any product whose reference starts with one of these prefixes is excluded. Useful to skip internal products (NS for non-sellable, HB for off-business, OBSOLETE- for discontinued ranges, etc.). Prefixes are case-insensitive.

Snapshot at job creation: filters are stored in persistent config but frozen at job creation time (snapshot in params). Changing the filters does not affect a job already in progress.

Repair images (v1.3)

Shopify downloads images asynchronously after creating a product: it fetches the URL you provided, and if it fails silently (timeout, blocked URL, file too large, format rejected), it returns no error. The product is created “success” on the API side but without images.

The Repair images entity fixes these cases. For each product in the mapping:

  1. GET /products/{shopify_id}/images.json to count current images on Shopify.
  2. Read the corresponding images on PrestaShop.
  3. If Shopify already has as many images as PS → the product is skipped.
  4. Otherwise: delete partial Shopify images, then upload each PS image via base64 attachment (synchronous mode, Shopify confirms creation immediately), with URL fallback for files larger than 3 MB.

API mode required. Idempotent: you can re-run the job as many times as needed.

Variant images (v1.4)

Once main images are in place, each Shopify variant still needs to be tied to its corresponding image. The Variant images entity handles this: for each product in the mapping, it queries the list of variants and images on Shopify, then cross-references with PrestaShop’s product_attribute_image relations.

PS variant → Shopify variant matching uses SKU first (variant reference), with a fallback by option tuple (option1/option2/option3 lowercase) if reference is empty.

PS image → Shopify image matching uses position alignment: the N-th PS image corresponds to the N-th Shopify image. This holds as long as you have not manually reordered images in the Shopify admin.

Idempotent: a variant already on the correct image_id is skipped (logged already_ok). The log counts per product: assigned / already_ok / missing_image / missing_variant.

Features → Metafields (v1.5)

PrestaShop product features (Catalog → Attributes & Features → Features) are pushed as Shopify metafields under the custom namespace, with automatic Metafield Definition creation so they are editable from the Shopify admin.

Phase A: Definition creation (first batch)

On the first batch of the job, the module lists all distinct features in the shop and creates a Metafield Definition for each via the metafieldDefinitionCreate GraphQL mutation. Existing definitions (TAKEN or DUPLICATE_KEY codes) are silently ignored.

Phase B: value push (each batch)

For each product in the mapping, the module lists existing custom.* metafields, then for each PS feature performs an upsert: PUT if the key exists with a different value, POST if the key does not exist. Already identical values are skipped.

Name → key conversion

The PrestaShop feature name is converted to a Shopify metafield key by ASCII transliteration, lowercasing, replacing non-alphanumeric characters with underscores, truncation to 30 characters. Examples:

  • Matière principale becomes matiere_principale
  • Weight (kg) becomes weight_kg
  • Color becomes color
Required scope: without write_metaobject_definitions in the Shopify app, Phase A fails. Phase B still works but metafields are not visible in the Shopify admin UI in an editable way. To add it without reinstalling the app, add the scope in Configuration, save, then uninstall/reinstall the app to refresh merchant consent.

Cron worker

The module exposes a token-protected front endpoint that processes one job per tick, at 20 batches per tick. The full URL with token is displayed in the Run a migration tab, with a copy button.

Sample crontab entry for one tick per minute:

* * * * * curl -s "https://your-prestashop.com/index.php?fc=module&module=dfshopifymigrator&controller=cron&token=YOUR_TOKEN" > /dev/null

Without configured cron, you can always advance a job manually with the Run now button in the jobs list (synchronous advancement, limited by PHP back-office timeout, about 30 seconds).

For a complete migration without surprises, run the jobs in this order:

  1. Products — creates the PS→Shopify mapping for products, used by all subsequent steps.
  2. Collections — creates the mapping for categories and automatically attaches products.
  3. Pages — creates the mapping for CMS pages.
  4. Customers — independent of the rest.
  5. Orders — consultative CSV only, run at your own pace.
  6. Repair images (if needed) — fixes images lost during Shopify async fetch.
  7. Variant images — re-associates each variant with its image.
  8. Features → Metafields — pushes product features as visible metafields.
  9. Redirects — last, consumes all the mapping built above.

Known limitations (v1)

  • Only one language is exported per migration (the language selected in Settings). v2 will add mapping of PrestaShop languages to Shopify Markets and Translate & Adapt.
  • Orders are exported as consultative CSV only.
  • Customer passwords are not migrated.
  • Variants are limited to 3 attribute groups (Shopify Option1/Option2/Option3 limit).
  • Images are served from the public URL of your PrestaShop: keep your PS online during Shopify import, and at minimum during any Repair images job.

Troubleshooting

Shopify API error: Not Found

First, check the API version field in Settings: it must be 2026-04 (older versions like 2024-10 are retired). Also check that your app is properly installed on the target store in Distribution.

Shopify API error: Invalid API key or access token

The token has expired (CCG: 24 h lifetime, automatically refreshed) or the app has been uninstalled. Click Test connection to force a CCG token refresh. If the error persists, go to Shopify Admin → Apps and sales channels and check that the Migrator app is in the list of installed applications.

This action requires merchant approval for write_X scope

You modified the scopes after the initial app installation, the merchant did not get to approve them. Uninstall the app in Shopify Admin then reinstall it via the Distribution link in the Dev Dashboard. The merchant consent screen will reappear with the new scopes.

shop_not_permitted during CCG exchange

Your Shopify store is not in the same organization as your Dev Dashboard app. Either link the store to your Partners organization, or use an Admin token obtained manually (Authorization Code Grant OAuth, outside the module’s scope).

Cardinality violation: Subquery returns more than 1 row

Bug fixed in v1.2.1. Update to the latest module version.

Many Shopify products arrived without images

This is Shopify’s documented behavior for images pushed via URL. Run the Repair images job in API mode: it detects products with fewer images than PS and republishes everything in base64 (synchronous mode, guaranteed arrival).

Many “missing_variant” entries in Variant images logs

The Shopify variant SKU does not match the PrestaShop product_attribute reference, and the option tuple fallback did not match either. Check that your PS variants have references filled in, or contact DataFirefly support for a custom matching adjustment.

Resources

  • DataFirefly Shopify Migrator product page (downloads, purchase, license)
  • Official Shopify Admin REST API documentation: shopify.dev/docs/api/admin-rest
  • Shopify Client Credentials Grant documentation: shopify.dev/docs/apps/build/authentication-authorization/access-tokens/client-credentials-grant
  • DataFirefly support: hello@datafirefly.com
Was this page helpful?

Still stuck? Contact support