Zoho Creator / Shopify: Get all Active Products

Zoho Creator / Shopify: Get all Active Products

What?
This is an article to document a function used in Zoho Creator to retrieve the Product IDs of all the active products in a client's Shopify.

Why?
The use-case was that I wanted to search Shopify using a Product SKU. Community forums could only suggest looping through all the products.

I then felt that actually I just need the Product IDs. This method could do with some refinement and perhaps if I find a better way to do this, then I'll put it here. But I like this snippet of code albeit a brute force to loop through every active product and list their IDs.

How?
So here's the function I came up with. It loops through a maximum of 2500 products sorted in order of ID ascending (starting with ID=0) retrieving 250 per call and using since_id to not list the same one twice. It then outputs a JSON list as a response and the total record count:
copyraw
void API.fn_ShopifyQuery_GetActiveProducts()
{
	m_Header = Map();
	m_Header.put("Content-Type","application/json");
	// 
	// your shopify details 
	v_ClientID = "<YOUR_CLIENT_ID>";
	v_ClientSecret = "<YOUR_CLIENT_SECRET>";
	v_ShopID = "example.myshopify.com";
	v_ShopifyURL = "https://" + v_ClientID + ":" + v_ClientSecret + "@" + v_ShopID;
	v_ShopifyApiVersion = "2020-01";
	//
	// loop through 2500 records
	v_LastID = 0;
	l_ProductIDs = List();
	l_Pages = {1,2,3,4,5,6,7,8,9,10};
	for each  v_Page in l_Pages
	{
		v_Endpoint = v_ShopifyURL + "/admin/api/" + v_ShopifyApiVersion.toString() + "/products.json?status=active&limit=250&fields=id&order=id+asc&since_id=" + v_LastID;
		r_GetProducts = invokeurl
		[
			url :v_Endpoint
			type :GET
			headers:m_Header
		];
		for each  r_ShopifyProduct in r_GetProducts.get("products")
		{
			if(!isnull(r_ShopifyProduct.get("id")))
			{
				l_ProductIDs.add(r_ShopifyProduct.get("id"));
			}
		}
		l_ProductIDs.sort();
		v_LastID = l_ProductIDs.get(l_ProductIDs.size() - 1);
	}
	//
	// output
	info "[" + l_ProductIDs + "]";
	info l_ProductIDs.size();
}
  1.  void API.fn_ShopifyQuery_GetActiveProducts() 
  2.  { 
  3.      m_Header = Map()
  4.      m_Header.put("Content-Type","application/json")
  5.      // 
  6.      // your shopify details 
  7.      v_ClientID = "<YOUR_CLIENT_ID>"
  8.      v_ClientSecret = "<YOUR_CLIENT_SECRET>"
  9.      v_ShopID = "example.myshopify.com"
  10.      v_ShopifyURL = "https://" + v_ClientID + ":" + v_ClientSecret + "@" + v_ShopID; 
  11.      v_ShopifyApiVersion = "2020-01"
  12.      // 
  13.      // loop through 2500 records 
  14.      v_LastID = 0
  15.      l_ProductIDs = List()
  16.      l_Pages = {1,2,3,4,5,6,7,8,9,10}
  17.      for each  v_Page in l_Pages 
  18.      { 
  19.          v_Endpoint = v_ShopifyURL + "/admin/api/" + v_ShopifyApiVersion.toString() + "/products.json?status=active&limit=250&fields=id&order=id+asc&since_id=" + v_LastID; 
  20.          r_GetProducts = invokeUrl 
  21.          [ 
  22.              url :v_Endpoint 
  23.              type :GET 
  24.              headers:m_Header 
  25.          ]
  26.          for each  r_ShopifyProduct in r_GetProducts.get("products") 
  27.          { 
  28.              if(!isnull(r_ShopifyProduct.get("id"))) 
  29.              { 
  30.                  l_ProductIDs.add(r_ShopifyProduct.get("id"))
  31.              } 
  32.          } 
  33.          l_ProductIDs.sort()
  34.          v_LastID = l_ProductIDs.get(l_ProductIDs.size() - 1)
  35.      } 
  36.      // 
  37.      // output 
  38.      info "[" + l_ProductIDs + "]"
  39.      info l_ProductIDs.size()
  40.  } 
Yields something like:
copyraw
[
  1234567890123,
  2345678901234
]
2
  1.  [ 
  2.    1234567890123, 
  3.    2345678901234 
  4.  ] 
  5.  2 

Well that produces a lot of ID numbers delimited by a comma. However, to match my use-case, I want a list to which I can give it an SKU, and it returns the Shopify Product ID (not of the variant but of the product). In which case, I need to tweak the above function a little to return the Product IDs, the Variant details and then output this to a map:
copyraw
void API.fn_ShopifyQuery_GetActiveProducts()
{
	m_Header = Map();
	m_Header.put("Content-Type","application/json");
	// 
	// your shopify details 
	v_ClientID = "<YOUR_CLIENT_ID>";
	v_ClientSecret = "<YOUR_CLIENT_SECRET>";
	v_ShopID = "example.myshopify.com";
	v_ShopifyURL = "https://" + v_ClientID + ":" + v_ClientSecret + "@" + v_ShopID;
	v_ShopifyApiVersion = "2020-01";
	//
	// loop through active products range
	m_Sku_IDs = Map();
	v_LastID = 0;
	l_Pages = {1,2,3,4,5,6,7,8,9,10};
	for each  v_Page in l_Pages
	{
		v_Endpoint = v_ShopifyURL + "/admin/api/" + v_ShopifyApiVersion.toString() + "/products.json?status=active&limit=250&fields=id,variants&order=id+asc&since_id=" + v_LastID;
		r_GetProducts = invokeurl
		[
			url :v_Endpoint
			type :GET
			headers:m_Header
		];
		for each  r_ShopifyProduct in r_GetProducts.get("products")
		{
			if(!isnull(r_ShopifyProduct.get("id")))
			{
				//
				// an error-prone one-liner so that we don't hit an execution statement limit
				v_ProductSKU = ifnull(r_ShopifyProduct.get("variants").get(0).get("sku"), "UNKNOWN");
				m_Sku_IDs.put(v_ProductSKU, r_ShopifyProduct.get("id"));
				//
				// getting the last ID from the Shopify sort instead of making Zoho sort a list
				v_LastID = r_ShopifyProduct.get("id");
			}
		}
	}
	//
	// output
	info m_Sku_IDs;
	info m_Sku_IDs.size();
}
  1.  void API.fn_ShopifyQuery_GetActiveProducts() 
  2.  { 
  3.      m_Header = Map()
  4.      m_Header.put("Content-Type","application/json")
  5.      // 
  6.      // your shopify details 
  7.      v_ClientID = "<YOUR_CLIENT_ID>"
  8.      v_ClientSecret = "<YOUR_CLIENT_SECRET>"
  9.      v_ShopID = "example.myshopify.com"
  10.      v_ShopifyURL = "https://" + v_ClientID + ":" + v_ClientSecret + "@" + v_ShopID; 
  11.      v_ShopifyApiVersion = "2020-01"
  12.      // 
  13.      // loop through active products range 
  14.      m_Sku_IDs = Map()
  15.      v_LastID = 0
  16.      l_Pages = {1,2,3,4,5,6,7,8,9,10}
  17.      for each  v_Page in l_Pages 
  18.      { 
  19.          v_Endpoint = v_ShopifyURL + "/admin/api/" + v_ShopifyApiVersion.toString() + "/products.json?status=active&limit=250&fields=id,variants&order=id+asc&since_id=" + v_LastID; 
  20.          r_GetProducts = invokeUrl 
  21.          [ 
  22.              url :v_Endpoint 
  23.              type :GET 
  24.              headers:m_Header 
  25.          ]
  26.          for each  r_ShopifyProduct in r_GetProducts.get("products") 
  27.          { 
  28.              if(!isnull(r_ShopifyProduct.get("id"))) 
  29.              { 
  30.                  // 
  31.                  // an error-prone one-liner so that we don't hit an execution statement limit 
  32.                  v_ProductSKU = ifnull(r_ShopifyProduct.get("variants").get(0).get("sku"), "UNKNOWN")
  33.                  m_Sku_IDs.put(v_ProductSKU, r_ShopifyProduct.get("id"))
  34.                  // 
  35.                  // getting the last ID from the Shopify sort instead of making Zoho sort a list 
  36.                  v_LastID = r_ShopifyProduct.get("id")
  37.              } 
  38.          } 
  39.      } 
  40.      // 
  41.      // output 
  42.      info m_Sku_IDs; 
  43.      info m_Sku_IDs.size()
  44.  } 
Yields something like:
copyraw
{
  "TEST001": 1234567890123,
  "TEST002": 2345678901234
}
2
  1.  { 
  2.    "TEST001": 1234567890123, 
  3.    "TEST002": 2345678901234 
  4.  } 
  5.  2 
Which results in a map that I can give a Product SKU to and it will return the Shopify Product ID to me. You may have noted also the precarious method in retrieving the product variant SKU (this will error/fail over if a product doesn't have a variant) and also how I get Shopify to return the last ID (as it is already sorting by ID) instead of getting Zoho to sort a list and retrieve the last element.

At time of print, I ran this to retrieve 1970 active product IDs and their SKUs without erroring by going over the Zoho Deluge statement execution limit.

Additional:
See my other articles for integrating Shopify API with Zoho Creator:
Category: Zoho :: Article: 777

Please publish modules in offcanvas position.