Discuss and resolve questions on Liquid, JavaScript, themes, sales channels, and site speed enhancements.
Consider the following scenario:
I have a custom JSON array metafield added to products like so to highlight hotspots on an image:
{ "my_json_array": [ { "settings": { "my_product_id": 1000090788054, "x_axis_id": 17, "y_axis_id": 55 } }, { "settings": { "my_product_id": 1000090853590, "x_axis_id": 61, "y_axis_id": 51 } }, { "settings": { "my_product_id": 1000090919126, "x_axis_id": 30, "y_axis_id": 36 } }, { "settings": { "my_product_id": 1000090886358, "x_axis_id": 85, "y_axis_id": 34 } } ] }
In theory all I should have to do in Liquid to GET that product...
could be as elegant and simple as this:
{% for hotspot in my_json_array %}
{% assign this_product = all_products[hotspot.settings.my_product_id] %}
{{ this_product.title }}
{% endfor %}
But that 'not work'...
Lets then examine some methods to GET any product by ID
OPTION #1
{% for product in collections.all.products %} {% if product.id == 1000090788054 %} {% assign this_product = product %} {% endif %} {% endfor %}
FLAWED: because collections.all.products is limited (not really the full catalog, limited to 10-100 I think)
###
OPTION #2
{% for product in collections.all.products %}
{% case product.id %}
{% when 1000090788054 %}
{% assign this_product = product %}
{% endcase %}
{% endfor %}
FLAWED: because again collections.all.products is limited (again, not the full catalog)
###
OPTION #3
{%- liquid
paginate collections.all.products by 1000
for product in collections.all.products
if product.id == 1000090788054
assign this_product = product
endif
endfor
endpaginate
-%}
WORKS...
BUT FLAWED: because now collections.all.products is looping through 1000 products via an overly elaborate method to paginate, and if the catalog go's above 1000 we are going to have a problem.
Note- perhaps my concern here for server load, efficiency and speed is a mis-qualified unfounded fear?
In other words: can I go above paginate by 1000, lets say paginate by 25,000 ?
Should I just 'not worry' about efficiency and speed of a shop?
(So far, this does not seem to slow the template down)
###
Observations:
###
A good question:
How else am I supposed to GET just 1 single product by ID when I have the ID value of that product?
My conclusion:
There is NO OTHER WAY to accomplish this task (other than Option #3 for a large catalog up to 1000 products)
Furthermore, once a catalog reaches greater than 1000+ products its then going to be a problem to just get 1 product in Liquid and I will have a worse problem.
@cfc_webmaster wrote:
GET a product by HANDLE is the worst possible way to set this up (because handles change)GET any product by a unique ID is the best possible way to approach any catalog or database
Forcing us to loop over a 1000 catalog pagination seems vastly inefficient and illogical
These are key flaws and assumptions.
Your assuming a product id is permanent and cannot be deleted , and ignoring that a product may be duplicated getting a new id and a new handle .
Your assuming the frontend of a shopify store is a database, this is not SQL, php,ruby or even javascript.
The view of illogically having to loop over 1000 items is based on the bad previous assumptions leading to that viewpoint.
Whatever is generating that JSON and getting shopify-product-ids should be just as capable of getting the product handle for use on the FRONTEND.
If your programatically setting a JSON metafield also consider setting up product-reference type metafields, or a metafield list of references then through that get the products.
If you must get products by id for the FRONTEND you can try workarounds to do it by the ajax/storefront apis.
Other workaround the ajax cart can accept variant.ids and through that can get a product handle.
Note- perhaps my concern here for server load, efficiency and speed is a mis-qualified unfounded fear?
In other words: can I go above paginate by 1000, lets say paginate by 25,000 ?
Should I just 'not worry' about efficiency and speed of a shop?
(So far, this does not seem to slow the template down)
Pagination max are discussed in other topics, ~1000 is a max
https://community.shopify.com/c/shopify-design/paginate-above-1000-products/td-p/930138
In general increasing pagination counts isn't a good idea and is code smell indicating a deeper design/architecture problem in whatever is being implemented.
This varies wildly and really you have to just have to test it
https://shopify.dev/themes/best-practices/performance
https://shopify.dev/themes/tools/theme-inspector
Contact paull.newton+shopifyforum@gmail.com for the solutions you need
Save time & money ,Ask Questions The Smart Way
Problem Solved? ✔Accept and Like solutions to help future merchants
Answers powered by coffee Thank Paul with a ☕ Coffee for more answers or donate to eff.org
Whatever is generating that JSON and getting shopify-product-ids should be just as capable of getting the product handle for use on the FRONTEND.
If your programatically setting a JSON metafield also consider setting up product-reference type metafields, or a metafield list of references then through that get the products.
ME - human typing - I am "generating" that JSON array using the vanilla JSON metafield
I see no other way to stuff in the 2 vars circled here using the Shopify "product" selector metafield.
The simplest way to present this problem is:
"What's the best way in LIQUID to GET a product by ID"
###
Your assuming a product id is permanent and cannot be deleted , and ignoring that a product may be duplicated getting a new id and a new handle .
Irrelevant.
The product ID's in this case will NEVER change
And if a product is "duplicated" it's not the same product then and should not appear at all in the X/Y cords I have indicated.
The fact that product HANDLE changes makes it useless and unreliable in this usage case. Our Handles will be changing based on SEO needs and the way our INVENTORY system works. We use FISHBOWL Inventory with the Shopify Plugin and all of our SEO handles need to change for various reasons after import, future updates and seo related optimization.
ERGO: a PRODUCT ID that is unchanging is needed here.
It seems to me perhaps my only option here is to somehow merge the JSON metafield with yet another product list metafield and loop through both of those or merge them somehow...
it just seems like such a strange problem.
Why make ALL products available by HANDLE within all_products[handle]
- but not make them available by ID in the same object or a new one like all_products_by_ID[id] ?
all_products[handle] is essentially a "database"
But why choose something for a "unique primary key" like HANDLE that can change?
Paul,
Ive carefully examined your reply here, the API, the forums and explored some tests.
If I have interpreted your reply correctly, then the solution I have here in this video:
https://www.screencast.com/t/hzUxFFj1o
seems to me to be the only way to accomplish the main goal in LIQUID?
Let me know what you think...
Thank you for your time.
I ran into this same fun issue today. I didn't find a solution unfortunately. I had to do a loop and use the paginate tag on the all product collection. I tried all_products with handles, but that could only output around 20 products before it stops.
Shopify and our financial partners regularly review and update verification requiremen...
By Jacqui Mar 14, 2025Unlock the potential of marketing on your business growth with Shopify Academy's late...
By Shopify Mar 12, 2025Learn how to increase conversion rates in every stage of the customer journey by enroll...
By Shopify Mar 5, 2025