Get number of available products in a Shopify collection - shopify

I realise I can use collection.products_count to get products count for a collection, but is it possible to get the count of available products, e.g. not sold?

You'll need to iterate over the products and check their availability:
{% assign available_products = 0 %}
{% for product in collection.products %}
{% if product.available %}
{% assign available_products = available_products | plus: 1 %}
{% endif %}
{% endfor %}
{{ available_products }}

Related

paginating variant collection in liquid

In my collection template I'm showing product variants if applicable and products if not. This works very well, safe for the fact that it seems impossible to paginate. I've tried creating a custom array of variants/products, but paginate wants nothing to do with it.
Here's the code I'm currently using which works for outputting variants/products in a grid:
{% for product in collection.products %}
{% if product.variants.size == 0 %}
{% include 'product-card-grid2', max_height: max_height %}
{% else %}
{% for variant in product.variants %}
{% include 'product-card-grid2', max_height: max_height %}
{% endfor %}
{% endif %}
{% endfor %}
How do you paginate something like this? Essentially I'd like something like the excellent pimoroni.com.
Liquid seems exceptionally rigid in terms of array construction/manipulation.
I guess the alternative would be to output the list as json and then manually handling it in JS, but it would be nice if that's avoidable.
One page may show 200 and another may show 50. I'd like to normalize that to 20 per page - also to avoid hitting shopify's hard cap on collections.
You can't achieve this only with liquid.
You can paginate the products but the variants will throw the logic of.
So there is not a lot of you can do.
One hacky ways is to overwrite the paginate limit to something crazy to show all the products and create a JS paginate instead of a liquid one.
Example:
{% paginate collection.products by 9999 %}
{% for product in collection.products %}
{% if product.variants.size == 0 %}
{% include 'product-card-grid2', max_height: max_height %}
{% else %}
{% for variant in product.variants %}
{% include 'product-card-grid2', max_height: max_height %}
{% endfor %}
{% endif %}
{% endfor %}
{% endpaginate %}
But if you have a lot of products the load time will be crazy slow for the back-end to process the request.
Another option is to create a GraphQL query with the Storefront API and populate the page via JS. Bu this may be an overkill for such a thing.
Another option is to use some kind of an App that will pull the variants and create the pagination for you. ( via JS once again )
Last option is to describe this to your client and that you don't have an easy/optimised way to handle variants pagination because of Shopify limitations.
Concat only works on arrays. Luckily there are ways to handle that. Array doesn't have the slice method (only strings) so we need to construct that too. Modulo takes care of under/overflow.
At last, success:
{% comment %}
------------------------------------------------------------------------------
Consolidating the product list for later use.
NOTE: It will probably cap over 50 products!!!!!!!!!!!!!!!!!!!!!!!!!!!
Needs to be rewritten at some point to use page number to load only the needed
products.
{% endcomment %}
{% assign productList = "" | split: "" %}
{% assign counter = 0 %}
{% assign variantLimit = 30 %}
{% for product in collection.products %}
{% assign productList = productList | concat: product.variants %}
{% assign counter = counter | plus: product.variants.size %}
{% endfor %}
{% assign maxSize = productList.size %}
{% assign start = current_page | minus: 1 | times: variantLimit %}
{% assign end = current_page | times: variantLimit | minus: 1 %}
{% if end > maxSize %}
{% assign end = productList.size | modulo: variantLimit %}
{% endif %}
{% assign slice = "" | split: "" %}
{% for i in (start..end) %}
{% assign temp = productList[i] | where: "available", true %}
{% assign slice = slice | concat: temp %}
{% endfor %}
{% assign productList = slice %}
And this as product loop
{% for variant in productList %}
{% include 'product-card-grid2', max_height: max_height %}
{% endfor %}
Also remember the next button
{% unless end > maxSize %}
Next Page
{% endunless %}

How scan an Order with Shopify Liquid - for customised Invoice

We are producing Invoices with Shopify's 'Order Printer' app.
and want to customise the Invoice.
For instance, if they have bought a 'book' - we want it to say "Enjoy your book"
and if a 'CD' - "Enjoy the music".
I've found I can test the first item they purchased with 'limit:1' :
{% for line_item in unfulfilled_line_items limit:1 %}
productType: {{ line_item.product.type }} - prodtype:{{product.type}} <br/>
{% if line_item.product.type contains "cd" %}
its a CD <br/>
{% else %}
it's not a CD?)<br/>
{% endif %}
{% endfor %}
But I would really like to scan the whole of the product.type array to determine how many of each product type there are - and output either/both messages - with plural 's' as appropriate.
Any ideas?
You're on the right track instead of limiting though you basically want to count.
{% assign cd_count = 0 %}
{% assign book_count = 0 %}
{% for line_item in unfulfilled_line_items %}
{% if line_item.product.type == "cd" %}
{% assign cd_count = cd_count | plus: 1%}
{% endif %}
{% if line_item.product.type == "book" %}
{% assign book_count = book_count | plus: 1 %}
{% endif %}
{% endfor %}
cd count: {{ cd_count }}
book count: {{ book_count}}
Now that you have a count you should be able to just do an if statement of the count numbers.
Thanks #trowse - solved the zeros issues, they were due to OrderPrinter cache problems and limitations. Just in case anyone needs it. Here's our solution:
<!-- count how many of each product type we are/have????? fullfilling -->
{% assign count_cd = 0 %}
{% assign count_bk = 0 %}
{% for line_item in unfulfilled_line_items %}
{% if line_item.product.type contains "cd" %}
{% assign count_cd = count_cd | plus:1 %}
{% endif %}
{% if line_item.product.type contains "Book" %}
{% assign count_bk = count_bk | plus:1 %}
{% endif %}
{% endfor %}
<!--- end of counting -->
<!-- Enjoy.. message -->
{% if {{count_cd > 0 %}
Enjoy the music
{% if {{count_bk > 0 %}
and the {{ count_bk | pluralize: 'book', 'books' }}<br/>
{% endif %}
{% else %}
{% if {{count_bk > 0 %}
Enjoy the {{ count_bk | pluralize: 'book', 'books' }}<br/>
{% endif %}
{% endif %}

Shopify - How to export Line item prices after discount?

Exporting discounted line items seems to be a common problem. I need to export the line item prices to my accounting software.
I'm trying to check for a coupon AND a specific product TAG, then apply the math with liquid to the actual discounted price.
I feel like I'm close but I'm striking out.
Any Advice would be much appreciated.
{% if line_items.tags contains '001' AND line_items.discounts == true %}
{{ line_item.price | times: .75 }}
{% else %}
{{ line_item.price }}
{% endif %}
Something like this?
{% for line_item in line_items %}
{% if line_item.product.tags contains '001' and line_item.discounts %}
{% assign rebate = 0 %}
{% for discount in line_item.discounts %}
{% if discount.type == 'PercentageDiscount' %}
{% assign rebate = line_item.price | times:discount.amount %}
{% endif %}
{% endfor %}
{{ line_item.price | minus:rebate }}
{% else %}
{{ line_item.price }}
{% endif %}
{% endfor %}

Shopify How to output a product that doesn't have a collection

I am trying to output all the products in a menu up to a certain number than output the collection types when that number is reached. So far that works fine, however I don't know how to output a product if the user does not put the product in a collection, I would like the products not entered into a collection to be in a template that I can link to in the menu that outputs the products not in a collection.
Here is my code so far.
{% for collection in collections %}
{% if shop.products_count <= 5 %}
{% for product in collections.[collection.title].products %}
{% capture productLink %}{{ product.url }}{% endcapture %}
{{product.title}}
{% endfor %}
{% elsif shop.products_count > 5 %}
{% capture collectionLink %}{{ collection.url }}{% endcapture %}
{{collection.title}}
{% else %}
You have no Products
{% endif %}
{% endfor %}
I would probably start by making a collection that contains all products in your shop (a smart collection where Product price > 0).
Then on the page where you want to display the products that are not in any collection (except the one we just created), try something like this:
{% for product in collections.all.products %}
{% if product.collections.size <= 1 %}
This product is not in any collections other than collections.all
{% endif %}
{% endfor %}

Shopify counts per tags

I am new to shopfiy.I have addded tags like Black, Blue, Green etc.
Now i want to show count like
Black(12)
Blue(1)
Green(4)
Does anybody help me out
Thanks
My answer to a similar question might help you with this: Shopify Tags total items
To get a count of all the products with a given tag you need to loop over the products and manually count them.
For example:
{% assign collection = collections.all %}
{% for tag in collection.all_tags %}
{% assign products_count = 0 %}
{% for product in collection.products %}
{% if product.tags contains tag %}
{% assign products_count = products_count | plus: 1 %}
{% endif %}
{% endfor %}
<p>{{ tag }} ({{ products_count }})</p>
{% endfor %}