Importing orders

Bringing order history across from another platform is a CSV upload. Open Orders, choose Import from the actions menu, and pick your file. The import runs in the background, so you can leave the page. Progress and any problems show up under Settings, Imports.

Two switches sit on the import dialog. Send review requests checks your survey flows against each imported order and emails the customers whose orders match. Earn loyalty rewards gives imported orders points and stamps. Both are off by default, so importing history never mints points or mails your customers by accident.

Before you start

Orders are attached to customers and products that already exist in Cascade, matched by email address and product slug. Import your customers and products first, otherwise every order will be skipped for want of something to attach to.

Columns

One row per line item. Repeat the order's own columns on each of its rows: rows that share a remoteId are one order, wherever they sit in the file.

ColumnRequiredDescription
customerYesEmail address of the customer who placed the order. They must already exist.
remoteIdYesThe order's ID in the system you are migrating from. It is what ties the rows of one order together.
numberYesThe order number shown to the customer.
totalCentsYesThe order total in the smallest unit of its currency, so 5999 for $59.99.
productNoSlug of the product bought on this row. It must already exist. Leave it blank for an order with no line items.
productVariantNoSlug of the variant bought, if the product has variants.
quantityNoHow many units of the product were bought. Required when product is filled.
unitPriceCentsNoPrice of a single unit, in the smallest unit of the order's currency. Required when product is filled.
siteNoSlug of the site the order was placed on. Leave it out and your first site is used.
subtotalCentsNoThe discounted subtotal excluding shipping and tax. Loyalty earning uses it as the basis where it is given.
shippingCentsNoThe shipping charged.
taxCentsNoThe tax charged.
currencyCodeNoISO 4217 code such as USD. Defaults to USD.
shippedAtNoWhen the order shipped, for example 2024-01-15T10:30:00Z. Leave it blank if it has not.
deliveredAtNoWhen the order was delivered.
cancelledAtNoWhen the order was canceled.
metadataNoA JSON object of your own string key/value pairs.

A two-item order looks like this:

customer,remoteId,number,totalCents,product,quantity,unitPriceCents
[email protected],1001,ORD-1001,5998,classic-tee,1,1999
[email protected],1001,ORD-1001,5998,plant-pot,1,3999

One row per line item

Every row carries its whole order, so no row depends on the ones above it. You can sort, filter or pivot the file in a spreadsheet and it still imports the same way.

Where two rows of one order disagree on an order-level value, the first non-empty value in the file wins and the row that was ignored is reported. A blank cell means "not specified" rather than "empty", so it never overwrites what another row of the same order said.

Files written in the older format, where a full row starts an order and the rows below it carry only their line item, still import unchanged: a row that leaves remoteId blank belongs to the order above it.

Running it twice

remoteId is what makes an import safe to repeat. Importing the same file again updates those orders in place, replacing their line items with the ones in the file, instead of adding a second copy of each.

When a row doesn't match

An import doesn't stop at the first bad row. Rows that can't be placed are skipped, and each one is listed with its row number on the import job under Settings, Imports:

Row 3: No customer with the email "[email protected]".
Row 4: No product with the slug "discontinued-widget". The order "ORD-1004" was skipped.

One unusable line item skips its whole order, because importing the rest would leave the order with a partial set of items. Fix those rows and import the file again.