Guides
This guide covers a code-based approach for migrating data from WooCommerce to Swell, and how to handle some of the quirks specific to WooCommerce and WordPress. It's intended to accompany our Migrate to Swell guide, which covers the general order of operations, Swell IDs, custom fields, and the $migrate flag.
We'll use the WooCommerce REST API to read your store data. To create credentials, go to WooCommerce → Settings → Advanced → REST API in your WordPress admin and add a key with Read permission. You'll receive a consumer key (ck_...) and consumer secret (cs_...), which authenticate as basic auth credentials over HTTPS.
Create a Node.js script with two API clients — one reading from WooCommerce, one writing to Swell:
const axios = require('axios');
const swell = require('swell-node').createClient(
'your-store-id',
'your-secret-key'
);
const woo = axios.create({
baseURL: 'https://your-site.com/wp-json/wc/v3',
auth: {
username: 'ck_...',
password: 'cs_...',
},
});The WooCommerce API returns up to 100 records per request using the per_page and page parameters, which the examples below use to paginate through each collection. Following the recommended migration order, we'll cover products, then customers, then orders.
let page = 1;
while (true) {
const { data: products } = await woo.get('/products', {
params: { per_page: 100, page, status: 'publish' },
});
if (!products.length) break;
for (const product of products) {
await swell.post('/products', {
name: product.name,
slug: product.slug,
sku: product.sku || undefined,
price: parseFloat(product.price || 0),
description: product.description,
active: false,
stock_tracking: product.manage_stock,
stock_level: product.stock_quantity || 0,
images: product.images.map((image) => ({
file: { url: image.src },
})),
woocommerce_id: product.id,
});
}
page++;
}A few things to note:
- The WooCommerce product id is retained as a woocommerce_id custom field — the orders script below uses it to reconnect line items to the migrated products.
- Products are created with active: false so you can review them before they become visible to customers.
- Images are referenced by their WordPress-hosted URLs. Verify your images have been fully imported into Swell before retiring the WordPress site or its media library.
- For variable products, fetch each product's variations from /products/{id}/variations and map the WooCommerce attributes into Swell product options and variants. Only enable variant generation for options where stock is tracked per variation.
- WooCommerce product categories are comparable to Swell categories. Like other platforms, they aren't assigned automatically — create your categories in the Swell dashboard and assign products in bulk after migrating.
let page = 1;
while (true) {
const { data: customers } = await woo.get('/customers', {
params: { per_page: 100, page },
});
if (!customers.length) break;
for (const customer of customers) {
await swell.post('/accounts', {
email: customer.email,
first_name: customer.first_name,
last_name: customer.last_name,
phone: customer.billing?.phone || undefined,
shipping: customer.shipping?.address_1
? {
address1: customer.shipping.address_1,
address2: customer.shipping.address_2 || undefined,
city: customer.shipping.city,
state: customer.shipping.state,
zip: customer.shipping.postcode,
country: customer.shipping.country,
}
: undefined,
woocommerce_id: customer.id,
});
}
page++;
}WordPress password hashes cannot be transferred to Swell, so customers will be prompted to reset their password the first time they log in to their account after migration. Billing addresses and saved payment methods are handled separately — see the payment migration section of the Migrate to Swell guide.
Orders reference the products and customers you've already migrated, using the woocommerce_id fields to look up the new Swell records:
let page = 1;
while (true) {
const { data: orders } = await woo.get('/orders', {
params: { per_page: 100, page },
});
if (!orders.length) break;
for (const order of orders) {
const account = await swell.get('/accounts/:first', {
woocommerce_id: order.customer_id,
});
const items = [];
for (const lineItem of order.line_items) {
const product = await swell.get('/products/:first', {
woocommerce_id: lineItem.product_id,
});
if (!product) continue;
items.push({
product_id: product.id,
quantity: lineItem.quantity,
price: parseFloat(lineItem.price),
});
}
await swell.post('/orders', {
$migrate: true,
account_id: account?.id,
items,
date_created: `${order.date_created_gmt}Z`,
woocommerce_id: order.id,
});
}
page++;
}The $migrate flag allows setting the original date_created and skips validation, events, and webhooks for historical records — see the Migrate to Swell guide for its tradeoffs. Depending on your needs, you can map additional order fields such as totals, taxes, and payment status from the WooCommerce order data. To maintain order number continuity, set your starting order number under Settings → General in the Swell dashboard.
That covers the core WooCommerce data. For shipments, subscriptions, gift cards, and coupons, see the Migrate to Swell guide, which covers each data type in detail along with the recommended migration order.