window.SwishOptions before the embed runs to customize behavior and appearance:
window.SwishOptions or directly to createSwish().
storefront
Credentials for the Shopify Storefront API. The SDK uses these to load product data, images, and recommendations.
string
required
Your
.myshopify.com domain (e.g. my-store.myshopify.com). This is the same
value as context.myshopifyDomain.string
required
A Shopify Storefront API access token with read access to products.
The Storefront API access token is not generated automatically - you need to create one in your Shopify admin.
- Go to Settings > Apps and sales channels > Develop apps.
- Create a new app (or select an existing one).
- Under Configuration, enable the Storefront API and grant at minimum the
unauthenticated_read_product_listingsscope. - Install the app and copy the Storefront API access token from the API credentials tab.
NEXT_PUBLIC_SHOPIFY_STOREFRONT_TOKEN) rather than hardcoding it.context
Information about the current customer and storefront environment.
Customer
string | null
required
Shopify customer ID, or
null for guest visitors.string | null
required
Customer email address.
string | null
required
Customer first name.
string | null
required
Customer last name.
boolean | null
required
Whether the customer is a B2B customer.
string[] | null
Shopify customer tags. Used to target content blocks at a subset of shoppers. Optional — omit it and tag-targeted blocks simply never match.
Localization
string
required
ISO country code (e.g.
"US").string
required
ISO language code (e.g.
"EN").string
required
Shopify market handle.
Other context
string
required
Your
.myshopify.com domain.string
Your store’s name, as shoppers know it. The drawer header shows it when you
have set neither a title nor a logo — see Drawer.
On Shopify themes this is
shop.name and the app embed passes it for you.string
The store’s currency format, as set under Settings → General → Currency
formatting. Only its decimal placeholder is read: a format using
amount_no_decimals (any variant) drops the cents from every price Swish
renders. The currency symbol, its position and the thousands separator come
from Swish’s own per-currency formats either way. On Shopify themes this is
shop.money_format and the app embed passes it for you.boolean
required
Whether the store uses Shopify’s new customer accounts.
string
required
URL path for the customer account page.
string
default:"/"
Root URL for the storefront. Useful for multi-language stores with prefixed
paths.
string
default:"/apps/wishlist"
URL path for the full-page list detail view.
auth
string
default:"/apps/wishlist/api/profiles/token"
URL the SDK calls to create auth tokens. On Shopify themes this is the default
app proxy token endpoint. For headless setups, set this to the route where you
host the auth proxy.
features
"none" | "save" | "view" | "all"
default:"none"
Require the customer to be signed in to perform specific actions.
"save"
requires sign-in to save an item, "view" requires sign-in to open the
drawer, and "all" requires it for every action Swish can gate, including
any gated in a later release. See the
Account guide for details.integrations
Third-party destinations the SDK sends events to from the storefront. The theme sets these through window.SwishOptions; they are not part of the setup yet.
boolean
default:"true"
Send every save to the store’s Meta Pixel as an
AddToWishlist event, through
the theme’s fbq when the customer allows marketing or, without one, as a
swish-add-to-wishlist customer event for a custom pixel to forward. See the
Meta Pixel integration.metafields
Fetch additional Shopify metafields alongside product data. Metafields are specified in namespace.key format. See the Metafields guide for usage examples.
string[]
default:"[]"
Product metafields to fetch.
string[]
default:"[]"
Variant metafields to fetch.
transforms
Transform functions that customize how product, variant, and option data is displayed in the Swish UI. See the Transforms guide for usage examples.
A
Badge can be a plain string or an object with id, label, and optional style.
productImage returns an image object with at least a url, such as one of product.images.nodes. Returning undefined or null keeps defaultImage.
recommendations receives and returns product references carrying only id - the recommendations query fetches nothing else, and each card re-fetches full product data per item. It may return a promise, so it’s the one transform that can do async work.
addToCartButton defaults to true, so supply it only to hide cart buttons
for particular products - add-to-cart on the product detail view, the buy
button on cards, and the quick-buy button. The section options
(showBuyButton, showQuickBuyButton) gate the same buttons independently:
both the section option and this transform must allow a button for it to
render.This transform is per product, not per view, so it cannot keep the product
detail button while removing quick-buy from cards. Use
ui.productCard.showQuickBuyButton for that.Only
addToCartButton, linkToProductPage, combinedListingParent, and
hideOption tolerate a non-function value - a literal such as
linkToProductPage: true is wrapped into a constant function. The other
transforms are called directly, so passing a non-function (for example
productPrice: false) throws on every render.intents
Behavioral options that control how specific intents interact with the customer.
saveProduct
unsaveProduct
editSavedProduct
initiateQuickBuy
Whether the quick-buy button on a product card adds straight to cart or opens the quick buy dialog.
By default, a card that knows its variant, such as an item saved with one, adds that variant to the cart directly without invoking
initiate:quick-buy. Cards without a variant always open the dialog. Set to true to open the dialog for every card. initiate:quick-buy invoked from your own code follows the same option.
createCartLine
removeCartLine
saveCartLine
placements
Declare placements upfront so the SDK automatically mounts them at initialization. Each entry uses the same placement spec as swish.placements.create().
swish.placements.list - an array of { spec, mount, unmount } objects you can use to unmount individual placements programmatically.
For the full placement spec reference, see Placements.
ui
UI options control the visual layout and behavior of every view in the Swish drawer. Pass view-specific sections arrays to customize the layout.
For a detailed guide with examples, see Views.
Global options
Product cards
ui.productCard applies to every product card, in every view. showQuickBuyButton and linkToProductPage have no default - leave one unset and the layer below it decides.
boolean
Whether cards show the quick-buy button (the floating cart button over the card
image). Set
false to hide it on every card - the saves grid, both list
detail views, product recommendations and featured collections - while leaving
add to cart on the product detail view untouched. This is the only way to hide
quick-buy store-wide without also removing the product detail button, which is
what transforms.addToCartButton would do.It is a hard off switch, not a fallback: a section that sets
showQuickBuyButton: true cannot re-show the button while this is false.
Sections that expose their own toggle can still hide it in just their view.This switch is code-only. In the customiser, you turn quick-buy on per view
with that view’s Show quick buy button.boolean
Whether a card is a hard link to its PDP rather than opening the in-drawer
product view. It is the only setting for this: no section has its own
linkToProductPage. When it is unset,
transforms.linkToProductPage
decides. The standalone Wishlist page ignores both and always links to the
PDP. Set it in the customiser under Global → Preferences → Product cards."image" | "title"
default:"\"image\""
Where a card’s save button sits.
"image" keeps it over the bottom corner of
the card image. "title" moves it beside the product title and price, as a
plain icon in the card title colour, outlined until saved and filled once
saved. The save button’s On image settings do not apply there. Only the
save button moves: quick buy and badges stay on the image. Applies to the
drawer and the standalone Wishlist page. Set it in the customiser under
Global → Preferences → Product cards → Save button position.Save button
"none" | "pulse" | "jello" | "particles"
default:"\"none\""
The animation a save button plays when a customer taps it to save an item.
"pulse" shrinks the icon and springs it back, "jello" squashes and
stretches it, and "particles" bursts small copies of the icon out of it.
It plays once the save goes through, never for an item that is already
saved, and not at all for customers who turn on reduced motion in their
system settings. It applies to every save button: placed buttons, and the
hearts in the drawer and on the Wishlist page. A value it doesn’t know plays
nothing. Set it in the customiser under Global → Save button → Save
animation.Product badges
ui.badges.rules is the product badge priority list for product cards and the product detail view. Each product shows one badge: the first enabled row, in list order, that applies to it. Set it in the customiser under Global → Preferences → Product badges. The chosen badge then goes through transforms.productBadges as defaultBadges.
The list holds Swish’s built-in badges, { type: "sold-out" }, { type: "sale" } and { type: "low-stock" }, and your own { type: "custom" } rows. It defaults to the three built-ins in that order, with Low stock hidden, which is how badges worked before the list existed. A list that leaves a built-in out gets it appended as in the default: Sold out and Sale shown, Low stock hidden. Set enabled: false to hide a built-in, and enabled: true to show Low stock.
"sold-out" | "sale" | "low-stock" | "custom"
required
"sold-out" applies when the product or selected variant can’t be bought,
"sale" when its compare-at price is above its price, and "low-stock" when
1 to max units are left. The built-in badges show translated text
(productCard.badges.soldOut, productCard.badges.sale,
productCard.badges.lowStock), which you change per language in
translations. "custom" applies when its
condition matches.boolean
default:"true"
Set
false to hide the badge. The next matching row shows instead. The Low
stock row defaults to false.number
default:"5"
Low stock row only. The badge shows when 1 to
max units are left. It reads
the selected variant when there is one; without one it reads the product’s
total stock. It never applies to a sold-out product or a variant selling on
backorder. Swish fetches stock levels only while this row is shown.string
default:"\"\""
The badge text, as plain text. On a custom row it is required: a blank label
shows nothing. On a built-in row, blank keeps the translated text and a value
replaces it in every language; to change a built-in badge’s text per
language, use translations instead. The
badge keeps its
badge-sold_out / badge-sale / badge-low_stock class
either way.object
Custom rows only.
{ type: "tag", tag } matches a product tag, ignoring case.
{ type: "metafield", metafield, operator, value } reads a product metafield
named namespace.key. operator is "exists" (any value, the default),
"equals" or "contains", all ignoring case. "contains" also matches one
item of a list metafield. Swish adds every metafield a row names to
metafields.product for you.{ type: "discount", minPercent } applies when the price is at least
minPercent below the compare-at price (default 20). It reads the selected
variant when there is one, otherwise the product.{ type: "published-within", days } applies for days days after the
product was published to your storefront’s sales channel (default 30), so
a New badge drops off by itself. It reads the product’s publishedAt
date, so every variant of a product shows the same result.string
default:"\"\""
The badge background. Blank uses the badge colours from
ui.design.string
default:"\"\""
The badge text colour. Blank uses the badge colours from
ui.design.Wishlist
ui.wishlist covers how the wishlist itself works, as opposed to how any one view looks. Set both fields in the customiser under Global → Preferences → Wishlist experience, where experience is Wishlist surface.
"drawer" | "classic-page"
default:"\"drawer\""
"classic-page" replaces the drawer with your standalone wishlist page. Every
navigation intent (view:home, view:saves, view:list, …) sends the
customer to context.routes.listDetailPagePath instead of opening the drawer,
carrying ?list-id= when a list is targeted. It implies multipleLists: false: the save toast drops its Add to list action and unsaving no longer
asks which list to remove from.boolean
default:"true"
Whether customers can keep more than one saved list. With
false, the save
toast’s action opens ui.defaultView instead of the list picker, and unsaving
skips the picker regardless of intents.unsaveProduct.selectList. Reach for
it when you want a single list and the drawer, since
experience: "classic-page" already implies one on its own. See
Single list only."home" | "saves" | "lists" | "notifications" | "orders" | "profile"
default:"\"home\""
The view the drawer opens on.
view:home resolves to it, so every generic
entry point - a swish-intent="view:home" button, a #swish link, the header
button - lands there without any theme changes, and so does the save toast’s
View action. It is also the drawer’s root: the Back chevron is hidden
there, and Back from any other view returns to it. The Home view stays
reachable through the footer Home tab; a store running Swish as a pure
wishlist sets this to "saves" and turns that tab off. Set it in the
customiser under Global → Preferences → Wishlist experience.Views
Each view accepts asections array. See Views for the full configuration reference with defaults and examples.
drawer-header
The drawer’s top bar. See Drawer for examples.ui.drawer.sections[].options
sign-in
The sign-in callout shown to signed-out shoppers. Used byui.home, ui.saves and ui.lists, each with its own copy. It renders above the rest of the view, so a guest’s own saves and lists stay visible below it, and hidden: true removes it from that view.
ui.home.sections[].options, ui.saves.sections[].options, ui.lists.sections[].options
page-header
The standalone Wishlist page’s header: the title, then the page’s actions. Used byui.listDetailPage only. See the List detail page guide for which actions appear on which view.
ui.listDetailPage.sections[].options
list-items-grid
Renders a list’s items, either as a product grid (layout: "gallery") or as one full-width row per item (layout: "card"). Used by both ui.listDetail (in-drawer) and ui.listDetailPage (standalone full-page). Each view exposes a different subset of options.
Card layout puts the image on the left and the vendor, title, price, variant and an Add to cart button on the right. The image renders square in that layout rather than following the Global → Components → Product cards → Card image aspect ratio, so rows stay compact.
Neither list detail view exposes layout in the Swish admin, so both render the gallery layout unless you set the option in code. The all-items-grid section below still offers the choice.
Neither view has a linkToProductPage option. In the drawer, cards follow ui.productCard.linkToProductPage. The standalone page always links its cards to the PDP.
ui.listDetailPage.sections[].options
ui.listDetail.sections[].options
all-items-grid
Renders the customer’s saved items, either as a product grid (layout: "gallery") or as one full-width row per item (layout: "card"). Used by ui.saves, and by the All Items screen that the grid’s heading links to — both read this one section.
Card layout puts the image on the left and the vendor, title, price, variant and an Add to cart button on the right. The image renders square in that layout rather than following the Global → Components → Product cards → Card image aspect ratio, so rows stay compact.