Support storefront filtering
Storefront filtering allows merchants to easily create filters for filtering collection pages. Filters are based on existing product data, like availability, vendor, price, variant options, and more.
In this tutorial, you'll learn how to support storefront filtering in your theme.
Resources
To implement storefront filtering, you'll use the following:
- The
/{locale}/api/collections/{collectionId}/cps
endpoint of the Products of the collection API - The collection object
- The add_root_url filter
- The spz-filter component
- The spz-list component
- The spz-selector component
- The spz-render component
- The spz-dropdown component
- The spz-pagination component
Implementing storefront filtering
To support storefront filtering, you need to implement a filter display for customers to interact with.
Applied filters are reflected through URL parameters, so you should also familiarize yourself with the structure of filter URL parameters.
Note
Before filters can be applied, they need to be created in the Shoplazza admin.
Filter display
The collection filter display should be included in the collection template.
The following example implementation contains several main components:
- A
spz-filter
component to implement filters display and filter functions. - A
spz-list
component to implement product display and refresh the product list when the filter option is changed. - A
spz-pagination
component to implement paging functionality.
<spz-filter id="collection-filter" list-id="collection-list" result-id="filter-result" collection-id="{{ collection.id }}" layout="container">
<div>
<!-- Filter content -->
<div role="content">
<spz-render layout="container" manual as="default" class="filter-content-inner-render">
<template>
<div>
<spz-dropdown id="filter-${data.title}-dropdown" placement="bottomLeft"
overlay-style="top: 20px; left: -12px;" layout='nodisplay' hidden>
<div>
<div>
<div><span role="selectedCount"></span> selected</div>
<div role="reset">Reset</div>
</div>
<spz-selector layout='container' multiple @select="collection-filter.apply(values=event.selectedOptions);" role="items">
<div spz-for="item in data.values" option='${item.value}' value="${item.value}">
<span>${item.label}</span>
</div>
</spz-selector>
</div>
</spz-dropdown>
<div @tap="filter-${data.title}-dropdown.open;">${data.title}</div>
</div>
</template>
</spz-render>
<spz-render layout='container' manual as='price'>
<template>
<div>
<spz-dropdown id='filter-${data.title}-dropdown' placement="bottomLeft"
overlay-style="top: 20px; left: -12px;" layout='nodisplay' hidden>
<div>
<div role="reset">Reset</div>
<div>
<div>
<span>{{ shop.finance_symbol }}</span>
<input type="number" placeholder='From' role="price-min" @input-debounced="collection-filter.apply;">
</div>
<div>
<span>{{ shop.finance_symbol }}</span>
<input type="number" placeholder="To" role="price-max" @input-debounced="collection-filter.apply;">
</div>
</div>
</div>
</spz-dropdown>
<div @tap="filter-${data.title}-dropdown.open;">${data.title}</div>
</div>
</template>
</spz-render>
</div>
<!-- Sort -->
<select name="sort_by" role="sortBy" @change="collection-list.refresh(sort_by=event.value, redo=true);">
<option value="manual" selected>Recommend</option>
<option value="price-ascending">Price, low to high</option>
<option value="price-descending">Price, high to low</option>
<option value="published-descending">Newest in</option>
<option value="best-selling">Total sales, high to low</option>
<option value="add_to_cart_count">Purchases, high to low</option>
<option value="views">Pageviews, high to low</option>
</select>
</div>
<!-- Filter result -->
<div id="filter-result" hidden>
<spz-render as="default" manual layout="container">
<template>
<div role="delete">${data.label}</div>
</template>
</spz-render>
<spz-render as="price" manual layout="container">
<template>
<div spz-if="${!(data.gte == 0 && data.lte == -1)}" role="delete">
<div>
<span spz-if="${data.gte !== 0 && data.lte === -1}">more than</span>
<spz-currency value="${data.gte || 0}" layout="container"></spz-currency>
<span spz-if="${!!data.lte && data.lte !== -1}">-</span>
<spz-currency value="${data.lte}" spz-if="${!!data.lte && data.lte !== -1}"
layout="container"></spz-currency>
</div>
</div>
</template>
</spz-render>
<div role="clearAll">Clear all</div>
</div>
</spz-filter>
<!-- A list of products with active filters -->
<spz-list
id="collection-list"
layout="container"
manual
initial-page="0"
page-size="20"
total="data.count"
list="data.products"
src="{{ collection.id | prepend: '/api/collections/' | append: '/cps' | add_root_url }}?page=0&limit=20"
inherit-url-search="filter,sort_by,page"
record-params-page-plus-one
>
{% paginate collection.products by limit %}
{% for product in collection.products %}
<a href="{{ product.url }}">
<spz-img
layout="responsive"
width="{{ product.image.width }}"
height="{{ product.image.height }}"
src="{{ product.image.src }}"
alt="{{ product.image.alt }}"
></spz-img>
<span>{{ product.title | escape }}</span>
<div>{{ product.price | money }}</div>
</a>
{% endfor %}
{% endpaginate %}
<template>
<a href="${data.url}">
<spz-img
layout="responsive"
width="${data.image.width}"
height="${data.image.height}"
src="${data.image.src}"
alt="${data.image.alt}"
></spz-img>
<span>${data.title}</span>
<spz-currency value="${data.price}" layout="container"></spz-currency>
</a>
</template>
</spz-list>
<spz-pagination list-id="collection-list" layout="container"></spz-pagination>
Updated over 1 year ago