Wishlists

A wishlist is a customer's own list of products they want, kept on your storefront and readable from the dashboard. Customers can hold several lists, name them, say how many of something they want, leave a note on an item, and share a list with a public link so other people can buy from it.

Wishlists are rendered by the same script tag as the review widgets, described in Storefront widgets. A wishlist belongs to one shopper, so the widgets do their real work once the storefront identifies them with the customer attributes from Identifying the customer. A shopper who is not signed in can still save: their lists live in the browser until they sign in, and are then moved onto their customer record. See Before signing in.

The quickest way in

Set up wishlists in the sidebar, or /wishlists/setup, asks two questions. There are no records to create, so it writes settings and nothing else:

You answerCascade writes
How many lists a shopper keepsWhether a customer can hold several lists or everything goes on one. See below.
SharingThe sharing switch, which is the master control over every share link in your store, and whether a shared list has prices on it.

Sharing is one question with three answers rather than two switches, because leaving prices out only means anything once lists can be shared at all: customers can share a list, customers can share a list, without prices, or lists stay private.

Both live under Settings → Wishlists afterward, alongside the alerts and the automatic list's name.

The embeds

<script
  src="https://cdn.example.com/cascade/embed.js"
  data-cascade-base-url="https://api.cascade.example.com"
  data-cascade-publishable-key="pk_live_..."
  data-cascade-customer-email="[email protected]"
  data-cascade-timestamp="1735689600"
  data-cascade-signature="48eb876e..."
></script>

<!-- Save this product. Goes on a product page. -->
<div data-cascade-add-to-wishlist="classic-tee"></div>

<!-- The customer's lists, rendered in place. Goes on an account page. -->
<div data-cascade-wishlists></div>

<!-- The same thing behind a button, for a header or a drawer. -->
<div data-cascade-wishlists-modal></div>
AttributeWhat it renders
data-cascade-add-to-wishlistA save button for one product. Its value is the product slug.
data-cascade-wishlistsThe customer's lists and their items, with the controls to rename, share and delete. Takes no value.
data-cascade-wishlists-modalThe same manager behind a button. Takes no value.

Give the modal a different button label with data-cascade-wishlists-modal-label:

<div data-cascade-wishlists-modal data-cascade-wishlists-modal-label="My saved items"></div>

On Shopify

Use the Add to wishlist and Wishlists blocks from the Cascade app instead of the markup above: they fill in the product handle and handle the signed-in shopper for you. See Widgets in your theme.

If you are writing the markup by hand on an older theme, the value of data-cascade-add-to-wishlist is the product slug, which on Shopify is the product handle:

<div data-cascade-add-to-wishlist="{{ product.handle }}"></div>

The widget works for guests too, so there is no need to wrap it in {% if customer %}.

Before signing in

A shopper who is not signed in can use the save button and the list manager anyway. Their lists are kept in the browser, in localStorage, and never touch Cascade's servers: there is no account to attach them to yet. Because of that, sharing, wishlist alerts and purchase marking are not offered until they sign in, and the lists exist only in that browser.

Each guest save remembers a small snapshot of the product for display: its name, image, price and page URL. Give the save button those with four optional attributes on the same element, and the guest's list view can render properly:

<div
  data-cascade-add-to-wishlist="classic-tee"
  data-cascade-product-title="Classic tee"
  data-cascade-product-image="https://shop.example.com/img/classic-tee.jpg"
  data-cascade-product-price="$29.00"
  data-cascade-product-url="https://shop.example.com/products/classic-tee"
></div>

The snapshot is captured when the shopper saves, so a price change later does not update it. That is fine: the snapshot is only for the guest view, and once claimed the items are real wishlist rows backed by your product catalog.

What happens when they sign in

The next time a wishlist widget loads with the customer attributes present, it moves the browser lists onto the customer's record through POST /widgets/wishlists/claim, then clears the browser copy. How depends on Several lists per customer:

  • Several lists allowed: every browser list quietly becomes a wishlist of their own. A name they already use gets a numbered suffix, "Holiday ideas 2".
  • One list per customer: the widget first asks "You saved 3 items before logging in. Want to add them to your wishlist?" and only merges on yes. Everything flattens into their one list, and an item already on it is left exactly as it is.

The claim is all-or-nothing: if anything fails, for example a list cap is reached, the browser copy is kept and the error is shown, so nothing a shopper saved is lost.

One-click saves

Clicking the save button puts the product on the customer's default wishlist. If they don't have one yet, Cascade creates it on the spot, so a first-time saver never has to name a list before they can save anything. The name it gets is Name for the automatic wishlist under Settings, Wishlists; out of the box it is "My wishlist". Customers can rename their list whenever they like, and changing the setting only affects lists created afterward: lists that already exist keep the name they have.

Clicking again takes the product off that list. The arrow beside the button opens the customer's other lists, where they can add the product to a particular one, take it off one, or jump to the manager. "Make default" in the manager moves one-click saves to a different list.

Each customer can hold a generous number of lists, and each list a generous number of items. The caps are there to stop abuse rather than to sell you an upgrade, and the widget says which one was reached if a customer ever meets it.

One list, or several

Several lists per customer under Settings → Wishlists decides whether a customer can keep more than one list at all. Turned off, everything they save goes on the same list, and the storefront widgets fit themselves to that: the save button becomes a plain heart toggle with no list picker, and the list manager skips the overview and opens straight onto the list's items, with no create control and no renaming. It is a choice about how your store works rather than a limit: one list is simpler to explain and is the right answer for most stores, and several is worth it when people shop your store for other people, so a wedding registry can sit beside a wish list.

Turning it off later leaves lists customers already have alone: everything a customer saves from then on goes on their one list, and the storefront hides the controls for creating another. A customer who already holds several lists still sees them all: the manager keeps its overview and the save button keeps its picker, so nothing they saved goes out of reach. Only the control for creating a new list disappears, and creating one through the API is refused with a message saying so. Widgets read the choice from the multipleWishlists field on every widget API wishlist response.

Quantities and notes

An item can carry how many the customer wants and a short note, such as a size or a color preference. Both are optional. A quantity left empty means the customer didn't say, and is treated as one wherever a count is needed.

Notes are shown to anyone the list is shared with, so they read as instructions to a gift buyer rather than private annotations.

Sharing

Sharing is off for each list until the customer turns it on. In the manager, Share opens a dialog offering Private or Anyone with the link, with a copy button for the link itself. Opening Share on a private list makes it shareable straight away, because a share dialog that hands over a dead link helps nobody.

Every wishlist is minted with a share token, and the link is your organization's customer pages subdomain plus that token:

https://acme.pages.example.com/w/9f86d081884c7d659a2feaa0c55ad015

The token is the only credential the page needs, so anyone holding the link can read the list. Nothing else about the customer is on the page: it shows the list's name, the owner's first name, and the items. There is no email address, no order history and none of your internal product fields.

A list that is private answers exactly the same 404 as a token that never existed, so share links can't be probed for lists that were switched back to private.

Replace the link at any time. "Regenerate link" in the share dialog mints a fresh token and the old link stops working immediately. There is no way to bring an old token back, which is the point: it is how a customer takes back a list they shared with the wrong person.

Prices on the shared page

By default the shared page shows each item's price, falling back to the product's cheapest variant where the customer saved a product rather than a variant. Show prices on shared lists under Settings, Wishlists turns that off, for example so gift budgets stay private and buyers go to the product page for the price.

The store-wide switch

Allow shared wishlists under Settings, Wishlists is an organization-wide switch for sharing. Turn it off and every share link in your store stops working at once, sharing can't be turned on from the storefront, and the manager hides its share controls. Each list's own choice is remembered, so turning the switch back on restores the links exactly as customers left them. The two switches beneath it, prices on shared lists and marking items as purchased, only apply while sharing is on.

Purchased items

Two people buying the same present is the problem a shared wishlist creates, so anyone viewing a shared list can mark an item as bought.

Marking takes no account. Anyone with the link can say how many they bought and leave a note for other visitors ("Bought by Aunt B."), and the item moves to an "Already purchased" section of the page. They can undo their own marking for 30 minutes, in case they marked the wrong row. The list's owner is never shown a purchase somebody else made.

An undo is tied to the browser that did the marking, not to an address or a network. One viewer can never undo another's marking, and a family behind one router are treated as different people, which is exactly the case this feature is for.

Items the customer buys themselves count too. When an order comes in, whether from a store sync or a CSV import, Cascade matches its line items against that customer's own wishlists and records what it finds. The match is deliberately narrow, because telling somebody they already own something they don't is worse than saying nothing: same customer, same product, an agreeing variant, and never more than the quantity they asked for. Canceled orders match nothing.

Who sees what

Gifts are hidden from the person the list belongs to. That is the whole point of the feature: a list owner who could see their own list's purchases would have their surprises spoiled by the tool meant to protect them.

Who is lookingSees purchases by other peopleSees the customer's own purchases
Someone with the share linkYesYes
The customer, in the widgetNoYes
You, in the dashboard and the APIYesYes

The customer still sees things they bought themselves, so their own list stays truthful. The shared page shows everything, because gift buyers are who reads it and coordinating them is the job. You see everything, because you are not the one being surprised.

Marking from your own systems

If you detect gift purchases yourself, for example a guest checkout you can tie to a list, POST /wishlists/{id}/items/{itemId}/purchases records one. It counts as a gift, so the list's owner is never shown it. GET on the same path reads the full picture and DELETE clears every purchase recorded against the item, whichever way it arrived.

Purchased state belongs to the customer, so marking or clearing it from the dashboard or the API is written to the audit trail with the item it touched.

Turning it off

Marking has its own switch under Settings, Wishlists, Let visitors mark items as purchased. Turn it off and shared pages keep working, without the mark-as-purchased controls. Purchases already recorded are kept and still shown, so a list that was half coordinated doesn't lose what it knew. Turning sharing off store-wide takes marking with it, since there is no page left to mark from.

Alerts

A wishlist is a list of things somebody wants but hasn't bought, which makes two moments worth an email: the price comes down, or the item is available again. Both are off until you turn them on under Settings, Wishlists: Say when a saved item drops in price and Say when a saved item is back in stock.

AlertSent when
Price dropA saved item's stored price falls by at least your threshold
Back in stockA saved item goes from out of stock to available on a connected store

Both alerts read a change, not a state. Cascade compares what it now holds for a variant against what it held before, so a store sync that rewrites the same catalogue every hour sends nothing. The first time a product arrives it can't be a change, so a newly imported catalogue never mails anybody.

The price-drop threshold

A price-drop alert only goes out when the fall is at least the percentage you set as Smallest drop worth an email, which starts at 10 percent. A fall smaller than that is ignored, so a penny off a large item, a rounding change or a currency adjustment never becomes an email, and the alerts that do arrive are worth opening. Set it lower if you run frequent small promotions, or higher if you would rather only announce real sales.

The comparison is against the price Cascade held before the change, not against a list price or a compare-at price.

What back-in-stock needs

Back-in-stock needs a source that reports availability, which usually means a connected Shopify store. Until Cascade knows a variant's stock, nothing sends. Shopify tells Cascade whether each variant can be bought as part of the product updates it already sends, so there is nothing extra to install. A variant Shopify doesn't track, or one set to keep selling when it runs out, counts as always available and so never restocks.

A catalog imported by CSV or through the API can carry availability too: put true or false in an available column on the variant row. Leave the column out, or the cell empty, and whatever is already stored is kept, so a routine product import never erases what your store reported. Until something says otherwise a variant's availability is simply unknown, and an unknown variant turning available is not treated as a restock.

One email, not one per item

A sync that cuts the price on six things somebody saved sends them one email listing all six, not six emails. Price drops and restocks are separate emails, because they say different things.

Each item is alerted at most once a week per kind. A stock level that flickers, or a price edited three times in an afternoon, still produces a single email. The two kinds keep separate clocks, so a restock is not swallowed by a price drop earlier in the week.

Items the customer has already bought themselves are left out: telling somebody that the thing they own got cheaper is worse than saying nothing. A gift somebody else bought is not counted, since the owner is never told about those.

Who does not get them

Alerts are marketing email, so a customer who has unsubscribed is skipped, and every alert carries its own unsubscribe link. Unsubscribing stops all of Cascade's marketing email for that customer, not just wishlist alerts.

The wording lives in the "Wishlist Price Drop" and "Wishlist Back In Stock" email templates.

In the dashboard

Wishlists is a list screen like any other: filter it, sort it, save a quick filter and export what you're looking at. Opening one shows its items, who owns it, whether it is shared, and what has been bought against each item.

The name and the items belong to the customer, so they are changed from the storefront or by an import, not by hand in the dashboard. What you can change is the sharing state, the share token, your own metadata and your internal notes. Because sharing is the customer's decision, changing it on their behalf is recorded in the audit trail.

The API exposes shareToken and shareUrl on a wishlist. Exports deliberately don't include them: a CSV is a file that gets emailed around, and a live share link is not something to scatter. Read them from the API when you need them.

Importing and exporting

Wishlists move in and out as CSV, one row per item with the list's own columns repeated on each row. See Importing wishlists.