Re: Build liquid dynamic section with on product page with list of filtered products

Build liquid dynamic section with on product page with list of filtered products

disual
Shopify Partner
5 0 0

Hello community,

 

Since some days i try to implement this functionality without success:

I have a product with custom metafield which contains values can be grouped to obtain set of products. For example: custom_field - "model" value AA11. I have different products with the same values (but different colors) and i need show this products in product page (as grid) - similar than featured products.

I've installed app "Search & discovery" and i've made my custom filter and works well on collections but i don't know if is possible to use on product page. I've tryed also to group in the collections (best solution) but my catalog has more then 5.000 groups (max limit of collections) so i can't use this solution. Another solutions i've tryed is make a smaller collection of product (for example by manufacturer) and loop over products to find with the same metafield but loop is limited to firs 50 products, so also this solution not working.

NB: I have over 50k products on my catalog, and 1200 collections (manufacturers and navigation)

 

Can someone help me to find working solution for this problem?

Any suggestion will be very appreciated.

 

Alberto 

 

 

Replies 7 (7)

Guleria
Shopify Partner
4112 804 1155

Hello Alberto,

Custom solutions will work here.
You need to use Javascript and fetch all the products . Once you have all the products then you have to make it conditional so you will get the products which match the defined condition.

And lastly you need to add the html in it. 

 


Sample code but keep note it need lot of modification a/to your need:

let storeProducts = [];
let fetchCalls = [];
// For 50k products I use ( i <= 20; ) change it a/to your need.
for (let i = 1; i <= 20; i++) {
    fetchCalls.push(fetch('/products.json/?limit=250&page=' + i));
}
Promise.all(fetchCalls)
    .then(responses => Promise.all(responses.map(response => response.json())))
    .then(productsArray => {
        // Flatten the array of arrays into a single array
        storeProducts = productsArray.flat();
        storeProducts.forEach(productsObj => {
            if (productsObj.products) {
                productsObj.products.forEach(product => {
                    // Check if the product title matches any element in the array
                    // You need to replace it with the metafield 
                    if (lineBreakCount.includes(product.title)) {
                        // Log the match
                        console.log('Match found for product with title:', product);
 
                    }
                });
            } else {
                console.log('Invalid products structure in storeProducts');
            }
        });

    })
    .catch(error => console.error('Error:', error));

 

Thanks

 

- Custom themes, UI/UX design, ongoing maintenance & support.
- Drop an email   if you are looking for quick fix or any customization
- Email: guleriathakur43@gmail.com Skype: live:navrocks1
- Try GEMPAGES a great page builder
disual
Shopify Partner
5 0 0
This is very gift for Christmas. Thank you a lot, i’ll try and send feedback

Alberto
PaulNewton
Shopify Partner
7725 678 1629

This is not the way to do this.

DO NOT force a customers browser to preload 50k items worth of information.

That type of behavior kills performance and conversion, read: lose money.

 

Use the section rendering api and just get a paginated collection with products

https://shopify.dev/api/section-rendering 

 

See the dawn theme for examples of client-side section rendering.

 


@disual wrote:
 I've tryed also to group in the collections (best solution) but my catalog has more then 5.000 groups (max limit of collections) so i can't use this solution

This often indicates something went very wrong with the businesses information architecture.

You can use tag filtering with collections to represent groups as a tradeoff in not redlining resource limits.

https://shopify.dev/docs/themes/navigation-search/filtering/tag-filtering 

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


Guleria
Shopify Partner
4112 804 1155

I don't think I force anyone to use it. It's an idea and helpful for those who know how Javascript works.


btw can you please let us know how much time Javascript takes for 50k products? 


And can you let us know how we can do comparison using section rendering api ?

- Custom themes, UI/UX design, ongoing maintenance & support.
- Drop an email   if you are looking for quick fix or any customization
- Email: guleriathakur43@gmail.com Skype: live:navrocks1
- Try GEMPAGES a great page builder
disual
Shopify Partner
5 0 0

This solution work with this code: (using tag not metafield)

{%- liquid
assign code = section.settings.code | handleize // code is dynamic source from product
assign codeTag = 'code_of_color:' | append: code
-%}
 
<script>
var codeTag = {{ codeTag | json }}
</script>
 
{% javascript %}
let storeProducts = [];
let fetchCalls = [];
// For 50k products I use ( i <= 20; ) change it a/to your need.
for (let i = 1; i <= 20; i++) {
fetchCalls.push(fetch('/products.json/?limit=250&page=' + i));
}
Promise.all(fetchCalls)
.then(responses => Promise.all(responses.map(response => response.json())))
.then(productsArray => {
// Flatten the array of arrays into a single array
storeProducts = productsArray.flat();
storeProducts.forEach(productsObj => {
if (productsObj.products) {
productsObj.products.forEach(product => {
// Check if the product title matches any element in the array
// You need to replace it with the metafield
if (product.tags.includes(codeTag)) {
console.log('Match found:', product);
}
});
} else {
console.log('Invalid products structure in storeProducts');
}
});

})
.catch(error => console.error('Error:', error));
{% endjavascript %}
 
Obviously is slow but working!
Now I have array of products. I need render result in grid (same template as featured). How I can use this result in template?
 
Some considerations. I'm wondering about Shopify have no direct solution for this scenarios (I think is very common).
Here is my demo:
https://quivedo.myshopify.com/collections/featured-ray-ban/products/ray-ban-wayfarer-rb-2140-901 (here is my actual page but "Altri colori" is not exact, must be like this result (obtain from app "Search & Discovery":
 
 
 
 

bilaalmirza
Tourist
4 0 1

Consider utilizing a custom filter through the "Search & discovery" app, as it works effectively on collections. Unfortunately, the product page grid display might have limitations. If possible, explore grouping products in smaller collections or consider optimizing the loop approach for better efficiency. Keep in mind the constraints posed by the 50-product limit in the loop. Your detailed catalog structure and requirements may benefit from tailored solutions or adjustments based on specific needs.

disual
Shopify Partner
5 0 0

Hi,

 

Yesterday I've found solution using graphql inside javascript&colon;

 
<script>
const manufacturerHandle = "{{ manufacturerHandle }}";
const colorCode = "{{ code }}";
const codeTag = "{{ codeTag }}";
</script>

{% javascript %}

const query = `query ManufacturerProductsByColor {
collection(handle: "${manufacturerHandle}") {
handle
products(
first: 100
filters: {productMetafield: {namespace: "custom", key: "codice_occhiale", value: "${colorCode}"}}
) {
nodes {
handle
title
featuredImage {
src
height
width
}
variants(first: 100) {
nodes {
price {
amount
}
compareAtPrice {
amount
}
title
selectedOptions {
name
value
}
availableForSale
}
}
}
}
}
}`

function apiCall(query) {
return fetch('/api/graphql.json', {
method: 'POST',
headers: {
'Content-Type': 'application/graphql',
"Access-Control-Origin": "*",
'X-Shopify-Storefront-Access-Token': "3f77b0dd30bcdf13841a8c6626axxxx"
},
"body": query
}).then(response => response.json());
}

apiCall(query).then(response => {
console.log(response);
});
{% endjavascript %}
 
This is efficent solution. Now I need build HTML section with results. I some way to use existing template or I must build from scratch?