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.
In Spojit, 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. Tracking the last-run timestamp keeps re-runs incremental so 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. Write the Shopify id into a WooCommerce meta_data field (for example shopify_id) so future runs can match on it even if the SKU later changes.
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.