Connecting Shopify Wishlist Apps

Prev Next

There are several wishlist apps that allow shoppers to create lists of products they'd like to purchase later, essentially creating a "favorites" or "want" list, often without logging into an account. Each wishlist app handles integrations in their own way or logic, so there is no one fit all solution. We currently support wishlist apps that provide snippets for code injection and API scripts that can be pasted into our XRecommend Widget Customization section shown below.

Options for selecting wishlist type and customizing outline and background colors.

Snippet Integration

For wishlist widgets that integrate with a snippet, choose the wishlist type as ‘snippet,’ then add the initialization JS code and html code on the widget html block, you can get these from your wishlist app support or integration page.

API Integration

For wishlist widgets that integrate with an API, choose the wishlist type as ‘API’ and define the outline and active background color of your wishlist icon.  Your wishlist provider offers the functions or the url API to add, remove or update the wishlist item. The XGEN product card automatically adds the heart icon.

Shopify Developer Responsibility

The app only handles the UI part. It is the shopify developer's responsibility to integrate these APIs or JS events

Event Triggers

In order for the wishlist icon to trigger event tracking, reference these tags to give product data like ID, handle, options, variants, and images for the clicked product card.

xgen-wishlist-added  This gets triggered whenever the heart icon or wishlist icon has been pressed on the product card

xgen-wishlist-removed This gets triggered whenever the heart icon or wishlist icon has been pressed on the product card which is already added in the wishlist

Preferred Wishlist Integrations

Swish (formerly Wishlist King)

Here’s the api integration for the Swish app

<script>
  async function makeRequest(creds, endpoint, method = "GET", payload = null) {
    const url = ${creds.host}${endpoint};
    const sessionId = window.localStorage.getItem('wk_session_id') || "";
    const options = {
      method,
      headers: {...creds.headers,"x-appmate-sid": sessionId}
    };
    // Include payload in body for POST and DELETE (since your API expects it)
    if ((method.toUpperCase() === "POST" || method.toUpperCase() === "DELETE") && payload) {
      options.body = JSON.stringify(payload);
    }
    try {
      const response = await fetch(url, options);
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      // If DELETE typically returns empty, handle that gracefully
      const contentType = response.headers.get('content-type');
      if (contentType && contentType.indexOf('application/json') !== -1) {
        return await response.json();
      }
      return null;
    } catch (error) {
      console.error("Fetch error:", error);
      throw error;
    }
  }
  function saveItemsToLocalStorage(items) {
    if (!items) return;
    const map = {};
    items.forEach(item => {
      map[item.productId] = item;
    });
    localStorage.setItem('xgen-wishlistItemsMap', JSON.stringify(map));
  }
  async function getAndSaveWishlist() {
    const creds = window.WishlistKing?.apis?.wishlist;
    if (!creds) {
      console.warn("Wishlist credentials not found");
      return;
    }
    const wishlistRes = await makeRequest(creds, "/wishlists/mine");
    const items = wishlistRes?.wishlist?.items || [];
    saveItemsToLocalStorage(items);
    return items;
  }
  // Initial load
  getAndSaveWishlist();
  window.addEventListener('xgen-wishlist-added', async (ev) => {
    const creds = window.WishlistKing?.apis?.wishlist;
    if (!creds) {
      console.warn("Wishlist credentials not found");
      return;
    }
    const productData = ev.detail.product;
    const payload = {
      variantId: productData?.variants[0]?.id,
      productId: productData?.id
    };
    try {
      const res = await makeRequest(creds, "/wishlists/mine/items", "POST", payload);
      const sessionId = res.sessionId;
      if(sessionId) {
        window.localStorage.setItem('wk_session_id', sessionId)
      }
      await getAndSaveWishlist();
    } catch (err) {
      console.error("Error adding to wishlist:", err);
    }
  });
  window.addEventListener('xgen-wishlist-removed', async (ev) => {
    const creds = window.WishlistKing?.apis?.wishlist;
    if (!creds) {
      console.warn("Wishlist credentials not found");
      return;
    }
    const productData = ev.detail.product;
    const items = await getAndSaveWishlist();
    const removedItem = items.find(item => item.productId == productData.id);
    if (!removedItem) {
      console.warn("Item to remove not found in wishlist");
      return;
    }
    const payload = { wishlistItemId: removedItem.id };
    try {
      await makeRequest(creds, "/wishlists/mine/items", "DELETE", payload);
      await getAndSaveWishlist();
    } catch (err) {
      console.error("Error removing from wishlist:", err);
    }
  });
</script>