FAQs - Common implementation questions

Collection of frequently asked questions on the usage of our APIs. This is based on past conversations and issues we were able to help with our implementations.

Cannot read properties of undefined

If you encounter the following error:

Uncaught (in Promise) TypeError: Cannot read properties of undefined (reading 'General')
	at h.instrument (swym-ext-shopify.js?...om&v=3.95.0:261:357)
	at f.<computed> [as fetch] (swym-ext-shopify.js?....com&v=3.95.0:31:40)
	at eval (Wishlist.svelte:378:19)

This is mostly caused due to an incomplete implementation of our JS APIs. Here are some examples of improper API usage that could potentially throw this error:

Using window._swat to make the API calls might lead to timing issues where not all components of the Swym Storefront JS client have been fully loaded by the time the calls are made. This could explain why the xxxx.General being undefined when your code executes..

To avoid this, the best way is to use our JS APIs in a complete implementation by wrapping every extension with our fully loaded callback function. This ensures that your custom functions are queued in the window.SwymCallbacks array and executed after the Swym app has fully loaded. For detailed guidance on how to implement this, please refer to our help article on using the SwymCallback function.

// create a self-executing anonymous function to avoid leaking variables into the top level scope of window
(function() {
  // Executed after Swym Storefront JS Client has loaded all necessary resources.  
  function onSwymLoadCallback(swat) {  
    // Please make all Swym-related API calls inside this function.  
    // You can use the swat argument within this scope.  
  }  
  if (!window.SwymCallbacks) {  
    window.SwymCallbacks = [];  
  }  
  window.SwymCallbacks.push(onSwymLoadCallback);
})();

Queries regarding outdated API usage

Q1: Why am I receiving API errors?

As of May 24, 2024, the majority of the APIs listed in our older documentation (Swym API Reference ) are outdated. We strongly encourage all developers to transition to our latest API documentation available at Swym Developer Documentation, where the implementation of most API calls is explained in a more comprehensive manner.

Q2: What does outdated mean?

Outdated APIs are those that are no longer supported and will eventually be removed. Using outdated APIs can result in unexpected behaviour and implementation errors.

Q3: Are all the APIs in the old documentation outdated?

Not all APIs in the older documentation are outdated. However, the implementation of the majority of API calls has been explained in a more comprehensive manner in our latest developer documentation. For the best experience and support, we recommend using the latest documentation.

Q4: How can I migrate to the latest APIs?

Please refer to our latest API documentation at Swym Developer Documentation. This documentation provides comprehensive guides, examples, and best practices for implementing our current APIs.

Q5: What if I have already implemented APIs from the older documentation?

If you have already implemented APIs from our older documentation and need assistance transitioning to the latest APIs, please reach out to us at [email protected]. Our support team is available to help you identify the updated API calls and assist with the migration process.

Q6: What if I have questions during the migration process?

For any questions or concerns during the migration process, please contact our support team at [email protected]. We are here to help ensure a smooth transition to the latest API standards.

Social Count implementation on multiple products at once

Issue: Merchants face an issue when implementing the Fetch Wishlist Social Count API on collection pages. The API call is dependent only on the Product ID and not the Variant ID. Therefore, if there are multiple products with the same Product ID but different Variant IDs, the button will appear only once.

Solution: The script should be modified to handle multiple instances of the same Product ID correctly.

Step-by-Step Guide for Implementation Reference:

HTML Button Setup:

Add an HTML span with a similar structure to your collection page. This implementation works only when the EPI button is used. For more information on implementing this button, please refer to this article. For code readability, please place this span along with the EPI button enclosed within a

tag.

<span class="swym-collections-social-count swym-hide-social-count" onclick="event.target.parentElement.querySelector('#swym-collections').click()" data-product-id="{{ <product.id OR card_product.id based on what is used in your code> }}"></span>

JavaScript Code Implementation:

Include this script with a similar structure in your theme files. This script will handle fetching and displaying the social count for each product tile.

<script defer>
  (function() {
    function swymCallbackFn(swat) {
      // Step 1: Collect all product IDs from the buttons
      const productIdArray = [];
			const allSwymCollectionsButtons = document.querySelectorAll('.swym-collections-social-count');
			allSwymCollectionsButtons.forEach((button) => {
  		const productId = button.getAttribute('data-product-id');
  		if (productId) { // Only push if productId is not an empty string
    		productIdArray.push(productId);
  		}
			});
      // Step 2: Function to fetch social count for a given product ID
      function fetchSocialCount(productId) {
        return new Promise((resolve, reject) => {
          swat.wishlist.getSocialCount(
            { empi: productId },
            (data) => resolve({ productId, count: data }),
            (error) => reject({ productId, error })
          );
        });
      }
      // Step 3: Generate an array of promises for fetching social counts
      function generateFetchBody() {
        return productIdArray.map((productId) => fetchSocialCount(productId));
      }
      // Step 4: Execute all fetch requests simultaneously and update the buttons
      Promise.all(generateFetchBody())
        .then((results) => {
          console.log(results, 'results');
          results.forEach((result) => {
            // Find all buttons with the same product ID and update their counts
            const buttons = document.querySelectorAll(`.swym-collections-social-count[data-product-id="${result.productId}"]`);
            buttons.forEach((button) => {
              result.count.data.count ? (button.textContent = result.count.data.count) : (button.textContent = '');
              button.classList.remove('swym-hide-social-count');
            });
            console.log(result, 'result');
          });
        })
        .catch((error) => {
          console.error('Error fetching social counts:', error);
        });
      // Step 5: Update the social count when a product is added to the wishlist
      swat.evtLayer.addEventListener(swat.JSEvents.addedToWishlist, function(product) {
        let productId = product.detail.d.empi;
        let buttonsToUpdate = document.querySelectorAll(`.swym-collections-social-count[data-product-id="${productId}"]`);
        buttonsToUpdate.forEach((buttonToIncrease) => {
          let updatedNumber = Number(buttonToIncrease.textContent) + 1;
          buttonToIncrease.textContent = updatedNumber;
        });
      });
    }
    // Step 6: Ensure the callback function is registered
    if (!window.SwymCallbacks) {
      window.SwymCallbacks = [];
    }
    window.SwymCallbacks.push(swymCallbackFn);
  })();
</script>

A step-by-step Explanation for reference:

  1. Collect Product IDs:
    1. Gather all the collection buttons with a common distinct class swym-collections-social-count has been used in the above example.
    2. Extract and store their data-product-id attribute values in an array.
  2. Fetch Social Count:
    1. Define a function fetchSocialCount that takes a product ID and returns a promise.
    2. This promise resolves with the social count data for the product.
  3. Generate Fetch Requests:
    1. Create an array of promises using the product IDs by mapping each ID to a call to fetchSocialCount.
  4. Execute Fetch Requests:
    1. Use Promise.all to execute all fetch requests simultaneously.
    2. Update the corresponding buttons' text content with the retrieved social count.
    3. Ensure all buttons with the same product ID are updated.
  5. Update on Wishlist Addition:
    1. Add an event listener for the addedToWishlist event.
    2. When a product is added to the wishlist, update the social count for all corresponding buttons.

How to Implement a Custom "Save for Later" Button on Your Cart Page

Follow these steps to add a custom "Save for Later" button to your cart page. This feature allows customers to save items for later purchase. Note that this implementation is functional only on the cart pages. Please note that the Save for Later functionality must be enabled on the Swym Admin for this implementation to function correctly.

Step 1: Add the button HTML

Add the following HTML code to your desired location on the cart page:

<swym-sfl-line-button>
  <button
    id="swym-custom-sfl-btn"
    class="swym-sfl-line-button link"
    type="button"
    data-variant-id="{{ item.variant.id }}" // Insert tag that fetches the variant ID
    data-product-id="{{ item.product_id }}" // Insert tag that fetches the product ID
    data-product-url="{{ shop.url }}{{ item.url }}" // Insert tag that fetches the variant URL
    data-quantity="{{ item.quantity }}" // Insert tag that fetches the count to Save for later
    style="<Insert your custom styling here>"
  >
    Save For Later 
  </button>
</swym-sfl-line-button>

Step 2: Create and Add this Script to swym-custom.liquid

Create a file named swym-custom.liquid and add the following script:

<script>
(function() {
  function sflInit(swat) {
      swat.SaveForLater.init(
          sfl => {
              swat.sfl = sfl;
              swat.sflLid = sfl.listid;
              swat.SaveForLater.fetch(swat.sflLid, function(response){
                  swat.sfl.listcontents = response.items;
              }, err => console.error(err))
          },
          err => console.error(err)
      )
  }
  if (!window.SwymCallbacks) window.SwymCallbacks = [];
  window.SwymCallbacks.push(sflInit);
  class SwymSflLineButton extends HTMLElement {
      constructor() {
        super();
          this.button = this.querySelector('button');
          if(this.button) this.button.addEventListener('click', this._addToSFL.bind(this));
      }
      _addToSFL(evt){
        const product = [{
          'du': this.button.dataset.productUrl,
          'empi': this.button.dataset.productId,
          'epi': this.button.dataset.variantId,
          'qty': this.button.dataset.quantity
        }]
        const cartRemoveButton = this.button.closest('.cart-item').querySelector('cart-remove-button'); // Please modify these selectors according to your store
        _swat.SaveForLater.add(_swat.sflLid, product, res => console.log(res), err => console.error(err));
        cartRemoveButton.dispatchEvent(new CustomEvent('click'));
      }
    }
    customElements.define('swym-sfl-line-button', SwymSflLineButton);
})();
</script>

Step 3: Include the Script in theme.liquid

Add the following line to your theme.liquid file to include the script you created in Step 2:

{ % include 'swym-custom' %}

By following these steps, you can successfully add a "Save for Later" button to your cart page. If you have any further queries regarding this implementation, please reach out to [email protected] and we’ll be more than happy to assist you!

Additional Information

Once the code and script have been added, please add the appropriate CSS for the appearance of the social count.

Integrating Product Object Data to Your Custom Wishlist Page

Introduction:

When merchants build custom Wishlist pages using our JavaScript APIs, they often want to display additional product data such as sale prices, compare-at prices, and other custom information. This data cannot be fetched using Shopify's default tags alone. This article provides a solution for integrating such product data into your custom Wishlist page.

Accessing Product Object Data:

Most of the time, the additional product information can be accessed by appending ".json" to the product URL, thereby retrieving the product object data. The following script can be included in your liquid file to fetch this data and make it available for use.

Script for Fetching Product Data:

Below is a script that fetches product data and allows you to access the necessary information from the response. The script includes a log for viewing all available product data in the console.

<script defer>
    // Executed after SWYM has loaded all necessary resources.
  (function() {
    function onSwymLoadCallback(swat) {
        swat.fetch(async (wishlist) => {
            let wishlistedProducts = await fetchProductData(wishlist);
            console.log("Wishlist items with product details:", wishlistedProducts);
            // Example to fetch "Availability status" for the first product in the array
            console.log(wishlistedProducts[0].productData.available);
        });

        async function fetchProductData(wishlist) {
            let fetchedProducts = await Promise.all(wishlist.map(async (listItem) => {
                let response = await fetch(listItem.du.split('?')[0] + '.js');
                let productData = await response.json();
                listItem.productData = productData;
                return listItem;
            }));
            return fetchedProducts;
        }
    }

    if (!window.SwymCallbacks) {
        window.SwymCallbacks = [];
    }
    window.SwymCallbacks.push(onSwymLoadCallback);
 })();
</script>

Sample Output of Product object data:

Product Object Data

Product Object Data

By following these steps, you can effectively integrate additional product data into your custom Wishlist pages, providing a richer and more informative shopping experience for your customers.


How to Fetch ListID Using the Swym API

Introduction:

To dynamically obtain the list ID ("lid") for each user, you can utilize Swym's API to fetch the list IDs. This guide will walk you through using the Fetch Lists API call to retrieve all existing lists along with their corresponding IDs.

Step-by-Step Guide:

  1. Understanding the Fetch Lists API:

The Fetch Lists API allows you to retrieve all the lists created by a user along with their corresponding IDs. Detailed instructions on how to use this API can be found in the Fetch Lists API documentation.

  1. Adding the Script:

Insert the following script into your liquid file where you need to fetch the list IDs.

<script defer>
  function onSwymLoadCallback(swat) {
    // Define success callback
let onSuccess = function(lists) {
  // Successfully fetched all lists 
  console.log("Fetched all Lists", lists);
}
// Define error callback
let onError = function(error) {
  // Error is an xhrObject
  console.log("Error while fetching all Lists", error);
}
// Call `fetchLists` function
swat.fetchLists({
  callbackFn: onSuccess,
  errorFn: onError
});
  }
  if (!window.SwymCallbacks) {
    window.SwymCallbacks = [];
  }
  window.SwymCallbacks.push(onSwymLoadCallback);
</script>
  1. Fetching the ListID:

The list IDs can be retrieved from the response of the fetchLists API call. The response will include a list of all the lists along with their IDs.

Example Response:

Here is an example of what the response looks like:

In the case of multiple Lists, you can run a for loop to fetch all the ListIDs within the Array.

By following these steps, you can dynamically obtain the list IDs for each user using Swym's Fetch Lists API. This enables you to manage and manipulate user lists efficiently and utilize the LIDs for various other API calls.

For more detailed information, please contact our support team for further assistance.