Filter product collection loop with featured products and custom frontmatter

In context of the question, I have 3 sections on a product page that lists all the products via a _product collection. The layout is very similar to

  1. One product will be headline or stickied product.

  2. Four other products will be featured.

  3. The rest of the products will display 6 more smaller product displays. Similar to how raspberry pi displays its product page.

  • If more than 10 products, a new page will be created with paginatorv2.
  • All product core attributes will be stored in a _data/products.yml file for speedy updates.

This is what I was wanting to do or thought how it would work using psuedo code…but I found out creating custom frontmatter variables and loops are a bit tricky for what I am wanting to do. I didn’t plan on creating a separate loop for each section, but am at the point I may do this to move forward with other parts of the website. The problem or challenge with creating separate loops for each section, I do not want to have duplicate posts. I would like to be able to filter all ‘stickied’ posts and populate them later, rather than updating the yml for that post when I want a new sticky post headline.

{% for post in paginator.posts %}

	{% if post.sticky == 'yes' %}
		...populate one most recent product that is stickied...
	{% elsif post.featured == 'Yes' %}
		...populate all products that are featured...
	{% else %}
		...populate all products != featured or sticky...
	{% endif %}

{% endfor %}

Right now, I have this:

{%- for product in site.products limit: 1 -%}
{%- endfor -%}

It displays the most recent product collections.

If I copy the code and do this for 4 featured posts as an example, it will copy the same stickied headline post and create a duplicate post.

{%- for product in site.products limit: 4 -%}
{%- endfor -%}

I tested a variable then doing the loop, but had no luck.

`{% assign product = site.products | where:'featured', true %}`
    {%- for product in site.products limit: 1 -%}
    {%- endfor -%}

Then, I added featured: true to file frontmatter.

If your problem is code duplication then use a layout or includes file approach.

For example you can have an includes file that takes an array of items given to it as a bullet list or as a table.

{% assign featured_products = ... %}
{% include render_products.html products=featured_products %}

{% assign basic_products = ... %}
{% include render_products.html products=basic_products %}

Your use of post in the code doesnt make sense if you are dealing with a collection.

It is also confusing where you have product data stored in .md files with flags but also have a YAML data file.

You have also called your collection products and your data products which is confusing.

As the first is accessed as


And the other as

And if you do have blog posts they are under


Break out your where filter to see what is going on there.

Here I leave out the filter and just get one item and view its data.

{% assign product = site.products | first %}
- Title {{ product.title }}
- Name {{ }}
- Featured: {{ product.featured }}
- {{ product | inspect }}

The last will show you all your fields as keys and values

Also remember to set booleans without quotes in YAML

featured: true
1 Like

As mentioned in the previous answer, the solution to avoid duplication is by using includes to render every section after the featured product.
To facilitate easier maintenance, you need to merge your _products collection and products data file into one of either type — either collection of product documents or a folder of individual data files. (Yes, _data/products/product_a.yml, _data/products/product_b.yml, etc) is perfectly valid.

Since your posts need to be rendered in the ratio of 1:4:6, make sure you have configured the site to paginate posts by 11 items.

Then use {% assign --- %} tag and slice filter to manipulate the list of posts.

## Sticky Post
### {{ paginator.posts[0].title }}

## Featured Posts
{% assign featured_posts = paginator.posts | slice: 1, 4 %}
{% for post in featured_posts %}
### {{ post.title }}
{% endfor %}

## More products
{% assign rest = paginator.posts | slice: 5, 6 %}
{% for post in rest %}
### {{ post.title }}
{% endfor %}

Move the forloops to includes if you don’t want duplication.


I am grateful for your expertise and sharing.

Your solution provided both the sections and included pagination for each page. Making use of slice simplified what I was seeking.

I moved all my products into the collection _products; I will have to edit each file, but this will also be easy to update and allow less room for error.

To increase modularization, I added each section as an include file.

I am still learning paginatorv2; at the moment, I have a pages directory with a blog and products folder that includes a base index.html for each page to aid in organization of different types of pages. To make use of paginatorv2, I included only the yaml information for the index.html, then make use of a shop.html layout to be used for a list of products, then on click of that product, a shop_single.html is used to populate the

Now, to add a product, all I or another has to do is add a file to the _product collection and all the products on the product page will be updated. One challenge I may have in the future is what if I want to sticky a headline product & disable that product from being moved. I found a plugin for this from Alex Ibrado Blog; I may make use of this in the future, in the mean time, I will simply manipulate the date.

Again, super thanks and high fives for the guidance.

Here is the layout shop.html

layout: post
{% comment %}
	This layout is the shop index of products with pagination & collections.
{% endcomment %}

<!-- Title -->
<header class="major special">
  <h1>{{ page.title }}</h1>
  <p>{{ page.sub_title }}</p>

<!-- Sticky Post -->
{%- include product_headline.html -%}

<!--  Featured Posts -->
<section class="row">
	{%- assign featured_posts = paginator.posts | slice: 1, 4 -%}
	{%- for post in featured_posts -%}
		{%- include product_featured.html -%}
	{%- endfor -%}

<!--  More products -->
<section class="row">
{%- assign rest = paginator.posts | slice: 5, 11 -%}
{%- for post in rest -%}
		{%- include product_rest.html -%}
{%- endfor -%}

You’re welcome :slight_smile:
Happy Jekyllin’!