Importing and exporting wishlists

Bringing saved lists across from another platform is a CSV upload. Open Wishlists, 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.

Export works the same way in reverse: choose Export and the finished CSV appears under Settings, Exports. It uses the columns below, so an export can be edited and imported straight back in. An export covers what you are looking at, so any filter or search on the screen applies to the file as well.

Before you start

Wishlist items are attached to products that already exist in Cascade, matched by product slug, or by the Shopify ID a connected store recorded. Import your products first, otherwise every list will be skipped for want of something to save. Customers are matched by email address, and one the import has never seen is created from the email, so a customers import is optional. Import customers first anyway if you want names and other details on the new records.

Columns

One row per saved item. Repeat the wishlist's own columns on each of its rows: rows that share a customer and a name are one wishlist, wherever they sit in the file.

ColumnRequiredDescription
customerYesEmail address of the customer the wishlist belongs to. A customer Cascade has never seen is created from the email.
nameYesThe wishlist's name. Together with customer it is what identifies the list.
isDefaultNotrue marks this as the customer's one default list, the one the storefront saves to with one click. See below.
productNoSlug of the product saved on this row. It must already exist. Leave the row's product columns all blank for a wishlist with nothing on it.
productExternalIdNoThe product's ID in the platform you are leaving, used when the row has no slug. Matched against the Shopify product ID on a connected store.
productUrlNoThe product's page URL on your storefront, used when the row has no slug. The last path segment is read as the slug.
productVariantNoSlug of the variant saved, if the customer chose one. Leave it blank to save the product as a whole.
productVariantExternalIdNoThe variant's ID in the platform you are leaving, used when the row has no variant slug.
createdAtNoWhen the customer saved this item. Without it the item is dated from the import. The list itself is dated from its earliest item.
quantityNoHow many of this item the customer wants. Leave it blank if they did not say.
noteNoThe customer's note about this item, such as a size or color preference.
sharedNotrue or false. Leave the cell blank to leave an existing list's sharing alone. New lists arrive private.
metadataNoA JSON object of your own string key/value pairs.

A two-item list looks like this:

customer,name,product,productVariant,quantity,note
[email protected],Birthday list,classic-tee,classic-tee-black,2,Size M please
[email protected],Birthday list,wireless-headphones,,1,

Column order doesn't matter, and columns you have nothing to say about can be left out of the file entirely.

One row per item

Every row carries its whole wishlist, 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 wishlist disagree on a list-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 wishlist said.

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

The default list

A customer has at most one default wishlist: the list the storefront saves to when a shopper clicks the heart without picking a list. Set isDefault to true and the row goes into that list. If the customer already has one, the row is imported into it whatever it is called and name is only used to create the list when there isn't one yet.

That is what a migration from a platform with a single unnamed list per customer needs. It is also what keeps the customer from ending up with two lists the first time they save something on your storefront after the import.

New default lists are named after Default wishlist name under Settings, Wishlists. Leave that setting alone while a migration is in flight: changing it between two runs of the same file gives the second run a different name to create, and the customer ends up with a list they never made.

A wishlist with nothing on it

An empty list is a row with customer and name filled in and product left blank. That is how exports represent one, so a customer who made a list and never saved anything survives a round trip rather than disappearing from the file.

Running it twice

A wishlist is identified by its customer and its name, so importing the same file again updates those lists in place instead of adding a second copy of each. Renaming a list in the file creates a new one and leaves the old one alone, because from the outside a rename and a new list look identical. A row with isDefault set carries no name of its own to change, so it lands on the same list every time.

An item keeps the date it was first imported with. A second run does not restamp the items that were already there, so createdAt is worth getting right on the first upload.

The items in the file replace the list's items. Anything that isn't in the file is taken off the list, which is what makes a corrected re-import land exactly what the file says. Send the full set every time, not just the rows you changed.

Two more things follow from a re-import writing the whole record:

  • A blank metadata cell clears whatever metadata was stored. Include the column in the file if you want to keep it.
  • Your internal notes on the wishlist are cleared. They are yours rather than the customer's and they are not part of the format, so copy anything you need out first.

What the file leaves out

Share links are not in the format. An export never carries a live share token, and an import never sets or rotates one: a list keeps the link it already had, and a new list is minted a fresh one. Read shareToken and shareUrl from the API when you need them.

Purchased state is not in the format either. An import replaces a list's items wholesale, so carrying purchases through a file would let a re-upload wipe the gift purchases the list's owner is not even allowed to see, and there is no sensible way to merge them. Read purchased state from the API instead, or from the detail pane in the dashboard. See Wishlists.

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 product with the slug "discontinued-widget". The wishlist "Birthday list" was skipped.
Row 5: The "shared" value on this row differs from an earlier row for the same wishlist. The first value in the file was used.

One unusable item skips its whole wishlist, because importing the rest would replace the list's items with a partial set. Fix those rows and import the file again.

Migrating from a named platform

The Format picker on the import dialog reads a competitor's export as it comes, so you do not have to rename a column before you upload. Pick the platform, upload the file, and Cascade maps the columns for you.

Warning

These mappings were written from each platform's published documentation, not from a real export file, and confidence is not even across the four. Swym's short keys (empi, epi, du, qty, lname) are its documented API vocabulary and are the surest of them; every human-readable header, and everything for Growave and Wishlist Hero, is our best reading of their help pages. Compare the table for your platform against your own export before you upload. If a column name differs, tell us and we will fix the mapping; in the meantime, rename the column in a spreadsheet, or reshape the file and use the Cascade format.

Five things are true of every named format:

  • The picker is not a guess. Cascade uses the format you picked, and refuses the file if its columns are not that format's. Nothing is imported when it does.
  • Columns are matched loosely on case and punctuation. Product Handle, product_handle and productHandle are the same column.
  • Nothing is dropped quietly. Every column the mapping does not carry into Cascade is listed on the import job under Settings, Imports, with the reason. A completed job with a list of notices is normal for a competitor import.
  • All four keep one list per customer. None of them has a list name to give us unless the export carries one, so a row without one goes into the customer's default list. Read The default list before your first upload: it is what makes a second run safe.
  • All four name products by Shopify ID. Connect your store first. Without it there is nothing to resolve a product or a variant ID against, and every list is skipped for want of a product unless the export also carries handles or URLs that match your slugs. Cascade warns you and still lets you upload, because a custom store whose slugs happen to line up is a fine reason to go ahead.

What none of them can bring across

Three things are lost on every one of these migrations, and they are worth knowing before you tell your customers the move is done.

Share links change. Some of these apps export a public share URL or token. Cascade mints its own link for every wishlist and cannot be given someone else's, so any link a customer already emailed to a friend stops working. Read the new shareUrl from the API if you need to send replacements. The shared flag itself does come across where the export carries one, so a list that was public stays public, at a new address.

Purchased state resets. Every item arrives unpurchased. An import replaces a list's items wholesale, so carrying purchases through a file would let a re-upload wipe gift purchases the list's owner is not even allowed to see, and there is no sensible way to merge them.

Guest lists cannot come across. A list kept against a browser rather than a customer has no email address to attach it to. Those rows are skipped, and each one is reported with its row number on the import job so you can see exactly how much of the file went nowhere:

Row 41: This row is a guest wishlist, kept against a browser rather than a customer, so there is no email address to attach it to. It was skipped.

Migrating from Swym Wishlist Plus

Export your wishlist data from Swym and upload the file with Format set to Swym Wishlist Plus.

Swym columnBecomesNotes
email, user_email or customer_emailcustomerRequired. A customer Cascade has not seen is created.
empi, product_id or external_master_product_idproductExternalIdRequired. Matched against the Shopify product ID.
epi, variant_id, external_product_idproductVariantExternalIdThe saved size or color.
product_handle, handleproductUsed first when the export carries it.
du, product_url, uriproductUrlThe fallback when the ID does not resolve.
lname, list_name, wishlist_namenameWithout it the row goes to the customer's default list.
qty, quantityquantity
note, notesnote
date_added, added_on, created_at, crdtcreatedAtA bare Unix timestamp is read as one.
shared, is_public, publicshared
dt, product_name, product_titleNot importedThe product Cascade holds supplies the title.
iu, image_url, product_imageNot importedThe product supplies the image.
pr, price, variant_priceNot importedPrices are read live from your catalog.
deviceid, device_id, uuid, anonymous_id, session_idNot importedGuest rows are reported and skipped.
cprops, custom_propertiesNot importedPut the ones you need in a metadata column as JSON.
share_url, share_link, share_idNot importedCascade mints its own share link.
lid, list_idNot importedA list is identified by its customer and its name.
purchased, is_purchased, purchased_atNot importedRead purchased state from the API.
bis, notify_me, back_in_stockNot importedAlerts follow your own wishlist settings.

Swym is the one export where a list name is likely. Wishlist Plus supports several lists per customer, so check for an lname column before you upload. Without it every row for a customer lands in one list, which is the right answer for a single-list store and the wrong one for a store whose customers kept a list per occasion.

Migrating from Wishlist King

Export your wishlist data from Wishlist King and upload the file with Format set to Wishlist King.

Wishlist King columnBecomesNotes
customer_email or emailcustomerRequired.
product_idproductExternalIdRequired. Matched against the Shopify product ID.
variant_idproductVariantExternalId
product_handle, handleproductUsed first when the export carries it.
product_urlproductUrl
wishlist_name, list_name, listnameWithout it the row goes to the customer's default list.
quantityquantity
note, notesnote
date_added, created_at, added_atcreatedAt
public, is_public, sharedshared
customer_id, shopify_customer_idNot importedCustomers are matched on the email address.
customer_name, first_name, last_nameNot importedNames belong to the customer record.
product_title, variant_titleNot importedThe product Cascade holds supplies the title.
image_url, product_imageNot importedThe product supplies the image.
price, variant_priceNot importedPrices are read live from your catalog.
available, in_stockNot importedAlerts follow your own wishlist settings.
device_id, visitor_id, session_idNot importedGuest rows are reported and skipped.
share_url, share_linkNot importedCascade mints its own share link.
wishlist_id, list_idNot importedA list is identified by its customer and its name.
purchased, is_purchasedNot importedRead purchased state from the API.

Migrating from Growave

Export your wishlist report from Growave and upload the file with Format set to Growave. Growave bundles wishlists with reviews and loyalty, so make sure you are exporting the wishlist report rather than a combined one: columns from the others are reported as columns Cascade did not recognize.

Growave columnBecomesNotes
email or customer_emailcustomerRequired.
product_idproductExternalIdRequired. Matched against the Shopify product ID.
variant_idproductVariantExternalId
product_handle, handleproductUsed first when the export carries it.
product_urlproductUrl
wishlist_name, list_name, collectionnameWithout it the row goes to the customer's default list.
quantityquantity
note, notesnote
date_added, added_date, created_at, datecreatedAt
public, is_public, sharedshared
customer_name, full_nameNot importedNames belong to the customer record.
product_title, product_nameNot importedThe product Cascade holds supplies the title.
image, image_url, product_imageNot importedThe product supplies the image.
priceNot importedPrices are read live from your catalog.
device_id, session_id, visitor_idNot importedGuest rows are reported and skipped.
share_url, share_linkNot importedCascade mints its own share link.
wishlist_id, list_idNot importedA list is identified by its customer and its name.
purchased, is_purchasedNot importedRead purchased state from the API.

Migrating from Wishlist Hero

Export your wishlist data from Wishlist Hero and upload the file with Format set to Wishlist Hero.

Wishlist Hero columnBecomesNotes
email or customer_emailcustomerRequired.
product_idproductExternalIdRequired. Matched against the Shopify product ID.
variant_idproductVariantExternalId
product_handle, handleproductUsed first when the export carries it.
product_urlproductUrl
wishlist_name, list_namenameWithout it the row goes to the customer's default list.
quantityquantity
note, notesnote
date_added, created_at, added_oncreatedAt
public, is_public, sharedshared
customer_name, first_name, last_nameNot importedNames belong to the customer record.
product_title, variant_titleNot importedThe product Cascade holds supplies the title.
image_url, product_imageNot importedThe product supplies the image.
price, product_priceNot importedPrices are read live from your catalog.
guest_id, device_id, visitor_id, session_idNot importedGuest rows are reported and skipped.
share_url, share_link, share_tokenNot importedCascade mints its own share link.
wishlist_id, list_idNot importedA list is identified by its customer and its name.
purchased, is_purchasedNot importedRead purchased state from the API.
notify_price_drop, notify_back_in_stockNot importedAlerts follow your own wishlist settings.

When Cascade refuses the file

If the columns are not the format's, the import fails before it writes anything and the job says what it looked for and what it found:

This file does not look like a Growave export.
Missing the customer email column: expected "email" or "customer_email".
Missing the product id column: expected "product_id".
Your file has: "Wishlist", "SKU".
Check that the Format picker matches the file you uploaded. The migration guide lists the
columns each format expects.

That is almost always the wrong format picked, or the wrong export downloaded. Nothing is imported, so fix whichever it was and upload again.