How to Sync Shopify Products to WooCommerce
Keep your product catalog in sync between Shopify and WooCommerce automatically.
What This Integration Does
Running two storefronts on different platforms is common - Shopify for the main brand site, WooCommerce for a wholesale or regional sub-site. Maintaining the catalog by hand on both is a guaranteed source of drift. This workflow takes Shopify as the source of truth and propagates create and update events to WooCommerce on a schedule.
The workflow runs every hour (or whatever cadence suits), reads products updated since the last run, and creates or updates the matching WooCommerce product keyed by SKU. State is cached locally so re-runs are idempotent and a one-off backfill doesn't double-write the catalog.
Prerequisites
- A Shopify connection with
read_productsscope. - A WooCommerce connection (REST API consumer key + secret) with product write access.
- An agreement on SKU as the cross-platform natural key.
Step 1: Schedule Trigger
Add a Trigger node of type Schedule. Hourly is a sane default. Capture since as the last successful run timestamp so the workflow is incremental.
Step 2: List Updated Shopify Products
Add a Connector node calling shopify list-products with updated_at_min={{ since }}. Page through results until empty - Shopify caps at 250 per page on REST.
Step 3: Loop and Find by SKU in WooCommerce
Wrap subsequent steps in a Loop. For each Shopify product, pick the first variant's SKU and call woocommerce list-products with sku={{ sku }}. Branch on whether a product comes back via a Condition node.
Step 4: Transform Shopify Shape to WooCommerce Shape
Use a Transform node to map fields:
- Shopify
titleto WooCommercename. - Shopify
body_htmlto WooCommercedescription. - Shopify
vendorto a WooCommerce custom attribute or meta field. - Shopify
variants[].priceto WooCommerceregular_price(as string). - Shopify
images[].srcto WooCommerceimages[].src.
For products with multiple variants, set WooCommerce type to variable and prepare a variations array to PUT after the parent is created.
Step 5: Create or Update in WooCommerce
On the "not found" branch, call woocommerce create-product:
{
"name": "{{ shopify.title }}",
"type": "{{ wcType }}",
"sku": "{{ shopify.variants[0].sku }}",
"regular_price": "{{ shopify.variants[0].price }}",
"description": "{{ shopify.body_html }}",
"images": {{ images }}
}
On the "found" branch, call woocommerce update-product with the existing id and the same body. Cache the Shopify-id-to-WooCommerce-id mapping in MongoDB so subsequent runs skip the lookup.
Step 6: Summary and Error Routing
After the loop, post counts (created, updated, skipped, failed) to slack send-message. Per-item failures get logged individually so one malformed product doesn't break the batch.
Tips
- WooCommerce prices are strings in the REST API. Convert numerics to strings in the Transform step or you'll get cryptic 400s.
- WooCommerce variations are a child resource - create the parent first, then POST each variation. Use
raw-api-requestwhen batch operations help. - For very large catalogs, run the initial backfill with the loop limited to 100 items at a time and a backoff between batches.
Common Pitfalls
- SKU mismatch - If you ever change a SKU in Shopify, the next sync will create a brand-new WooCommerce product instead of updating the old one. Sync state caches help detect this; consider also matching by
meta_data.shopify_id. - Image bandwidth - Shopify CDN URLs are public, but WooCommerce downloads each one on create. Throttle to avoid hammering both servers during a backfill.
- HTML sanitisation - WooCommerce strips unsafe tags. Custom inline CSS in Shopify descriptions won't survive - test on a representative sample first.
Testing
Hard-limit the loop to a single Shopify product (one simple and one variable) and run manually. Open the resulting WooCommerce products in the admin UI and check name, price, SKU, description, images, and variations. Re-run to verify the update path doesn't duplicate.