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:
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(); }
- 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();
- }
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:
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(); }
- 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();
- }
{ "TEST001": 1234567890123, "TEST002": 2345678901234 } 2
- {
- "TEST001": 1234567890123,
- "TEST002": 2345678901234
- }
- 2
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:
- Zoho Deluge - Push Item to Shopify
- Zoho Creator - Integration with Shopify Checkout Storefront API
- Zoho Creator - Receive JSON via a Shopify Webhook