Custom Wishlist Experience
Build custom wishlist experiences using the Swym JS SDK without any default UI.
SDK-Only Mode
Build a fully custom wishlist experience using the Swym JS SDK — no default Swym UI, total creative control.
SDK-only mode loads the Swym JavaScript SDK (window._swat) on your storefront without rendering any default UI (buttons, drawer, header icon, notifications). You get full API access and build your own UI from scratch.
When to Use SDK-Only Mode
- Agencies building custom storefronts for Shopify Plus merchants
- Headless / composable commerce builds (Hydrogen, Next.js, custom frontends)
- Merchants who want complete design control over their wishlist experience
- Developers integrating wishlist data into custom themes or apps
What You Get
| Available in SDK-Only Mode | NOT available (you build these) |
|---|---|
window._swat — full SDK instance | Wishlist buttons on product pages |
| All JavaScript APIs (add, remove, fetch, lists) | Wishlist page UI |
| Event system for real-time updates | Collection page buttons |
| Back-in-stock subscription APIs | Header icon with count badge |
| Multi-wishlist support | Consent popup (if GDPR-required) |
| Shared wishlist APIs | Toast notifications |
Prerequisites
- Swym Wishlist Plus app installed on your Shopify store
- In your Shopify theme editor (Online Store > Customize > App Embeds):
Wishlist App Embedmust be enabled (this loads the SDK)Storefront UI Elementsmust be present with "Show UI" unchecked
Verify SDK-Only Mode
Open your storefront in a browser and run these in the console:
// Run these in your browser console (verification only — not for production code)
window._SwymSDKOnlyMode; // true — SDK-only mode is active
typeof window._swat; // "object" — SDK is loadedIf _swat is undefined, the SDK may still be loading. Always use the SwymCallbacks pattern instead of accessing _swat directly.
The SwymCallbacks Pattern
This is the canonical entry point for all custom code. Never access window._swat directly — always use SwymCallbacks to ensure the SDK is ready. All swat API calls must happen inside this callback.
window.SwymCallbacks = window.SwymCallbacks || [];
window.SwymCallbacks.push(function(swat) {
// swat === window._swat — fully initialized
// ALL API calls MUST go inside this callback
});Rule: Every code example in this guide wraps all
swatcalls insideSwymCallbacks. Your custom code must do the same.
Product Data Shape
Every wishlist item uses this data structure:
| Field | Type | Description | Shopify Liquid Source |
|---|---|---|---|
epi | Number | Variant ID | {{ variant.id }} |
empi | Number | Product ID | {{ product.id }} |
du | String | Product URL (absolute) | {{ shop.url }}{{ product.url }} |
dt | String | Product title | {{ product.title }} |
iu | String | Product image URL | {{ product.featured_image | image_url }} |
pr | Number | Price (cents) | {{ variant.price }} |
stk | Number | Stock (1 = in stock, 0 = OOS) | {% if variant.available %}1{% else %}0{% endif %} |
qty | Number | Quantity (optional, defaults to 1) | N/A (set in code) |
note | String | Custom note (optional) | N/A (set in code) |
cprops | Object | Custom properties — arbitrary key-value pairs (optional) | N/A (set in code) |
source | String | Tracking source (optional). Valid: pdp, collections-grid, quick-view, featured-grid, recommendations, search-results, plp | N/A (set in code) |
Extracting Product Data in Liquid
<div id="swym-product-data"
data-product-id="{{ product.id }}"
data-variant-id="{{ product.selected_or_first_available_variant.id }}"
data-product-url="{{ shop.url }}{{ product.url }}"
data-product-title="{{ product.title | escape }}"
data-product-image="{{ product.featured_image | image_url: width: 400 }}"
data-product-price="{{ product.selected_or_first_available_variant.price }}"
style="display:none;">
</div>
SwymPageData: On product pages, Swym's SDK automatically setswindow.SwymPageDatawith the current product data. You can use this instead of extracting from Liquid data attributes.
SwymProductVariants:window.SwymProductVariantsis a lookup by variant ID — use it to get variant-specific data when the user changes variants.GDPR Note: In SDK-only mode, the Swym consent popup does not render. If your store requires marketing consent (EU, UK, etc.), implement your own consent gate before making SDK API calls.
Theme Architecture Detection
Before writing any code, determine your theme's architecture — this affects how you inject the wishlist button.
Read your product section file (found via templates/product.json → section type):
| Theme | Section type | File |
|---|---|---|
| Dawn | main-product | sections/main-product.liquid |
| Ritual | product-information | sections/product-information.liquid |
| Prestige | main-product-detail | sections/main-product-detail.liquid |
Then check if it uses block loops:
{% for block in section.blocks %}- Block-based themes (Ritual, Prestige, Impact, Symmetry): Product form elements are rendered inside block loops. You cannot drop a
<button>in the Liquid — it will render outside the product grid. Use JavaScript-based injection instead. - Template-based themes (Dawn, Craft, Colorblock): Product info is rendered inline. You can add Liquid markup directly near the buy buttons.
Rule: Always read your product section file before choosing an approach. The Wishlist Button guide covers both approaches.
Identity & Guest-to-Login Sync
The SDK automatically handles guest-to-logged-in user wishlist sync. No custom code is needed for Shopify Liquid themes.
How it works
- Guest visits — SDK assigns a unique device ID (RegID) via cookie and tracks their wishlist
- Guest logs in — Swym's Liquid snippet (loaded by the App Embed) reads Shopify's
{{ customer }}object and setswindow.swymCustomerId = "{{ customer.id }}". This is Shopify's standard Liquid customer object — it's only available when a customer is logged in. - SDK detects the login — on init, the SDK reads
window.swymCustomerIdand calls the backend sync endpoint - Backend merges — guest's wishlist items are merged into the customer's account
- SDK updates — local identity is refreshed,
customerInfoRefreshedevent fires
Checking login status in your code
Use the SDK's built-in method — don't check window.swymCustomerId directly:
window.SwymCallbacks = window.SwymCallbacks || [];
window.SwymCallbacks.push(function(swat) {
var isLoggedIn = swat.platform.isLoggedIn();
// Use this for login nudges, gated features, etc.
});How it works under the hood: Swym's Liquid snippet contains
window.swymCustomerId = {% if customer %}"{{ customer.id }}"{% else %}null{% endif %}. Thecustomerobject is Shopify's built-in Liquid variable — it's only truthy when a customer is logged in. The SDK reads this on initialization.swat.platform.isLoggedIn()is the canonical way to check this state.
This runs on every page load, so it also handles:
- Customer switching (different account logs in) — clears device state, re-syncs
- Logout — clears identity, re-registers as guest
- Email detection — if a guest enters their email in a third-party form (Klaviyo, Privy, etc.), the SDK detects it and links their wishlist to that email
Listening for identity changes
window.SwymCallbacks = window.SwymCallbacks || [];
window.SwymCallbacks.push(function(swat) {
if (swat.evtLayer) {
swat.evtLayer.addEventListener('sw:customerInfoRefreshed', function() {
// Identity synced — refresh your wishlist UI
// e.g., re-fetch wishlisted items, update count badge
});
}
});Headless builds — manual sync required
If you're not using Shopify Liquid (Hydrogen, Next.js, custom frontend), the theme won't set window.swymCustomerId for you. You must do it manually:
// Set this BEFORE the SDK initializes, or call validateUserLogin after
window.swymCustomerId = YOUR_SHOPIFY_CUSTOMER_ID;Or, if the SDK is already loaded, trigger the sync explicitly:
window.SwymCallbacks = window.SwymCallbacks || [];
window.SwymCallbacks.push(function(swat) {
// Call this when your app detects a login
swat.validateUserLogin('shopify', YOUR_SHOPIFY_CUSTOMER_ID, function() {
// Sync complete — guest wishlist merged into customer account
});
});Important: For headless builds, ensure
window.swymCustomerIdis set on every page load when the customer is logged in — the SDK checks it each time to detect login/logout transitions.
Guides
Build each component independently — pick what you need:
- Wishlist Button (PDP) — Add/remove toggle on product pages
- Collection Page Buttons — Heart overlays on product cards
- Wishlist Page — Dedicated page with theme-native cards, login nudge, conversion prompts, remove + add-to-cart
- Header Icon — Count badge that updates in real-time
- Advanced Patterns — Multi-wishlist, back-in-stock, events
Updated about 7 hours ago