Using Clerk to show full category pages
Products:
IMPORTANT: Replacing your category products requires technical expertise, and we recommend seeking assistance from your own developer. Please be aware that our internal developers at Clerk.io are not able to perform this task for you.
Overview
Clerk can be used to render all results on a category page, allowing for smart sorting of results, and using Merchandising for a high degree of control over which products are prioritised.
This article describes the use of our API and Clerk.js library as two different ways of handling this rendering.
API endpoints
Our category recommendations endpoints work exactly the same as our search page endpoint. The only difference is that these endpoints rely on a category ID rather than a search query.
Due to this, they can be used to render all products on category pages by replacing any existing webshop logic for fetching products, with Clerks API. If using a serverside API setup, you can usually keep the existing styling by simply getting the product data from Clerk, while rendering the visuals through the webshops code.
These are the two available endpoints:
- recommendations/category/popular
(Ranked by best selling items - changes occassionally) - recommendations/category/trending
(Ranked by products that are trending in sales - changes often)
The best endpoint to use depends on the type of business.
Many fashion stores with inventory that changes often, generally gets the most out of trending products. Stores with catalogues where customers tend to purchase the same items multiple times, like supplements or food stores, should generally use bestsellers.
API endpoint parameters
Here is a breakdown of what each argument does when making a call to a category endpoint
key
: The public key for the storelimit
: The amount of products to returncategory
: The ID of the category currently browsedoffset
: The index to start the result set from. Used withlimit
for pagination.orderby
: An attribute to sort the results on. If not sent, Clerk will order by best selling itemsorder
: Can be eitherasc
ordesc
. Sorts the products in ascending or descending orderattributes
: A list of attributes that Clerk should return. Useful for speedy setups where all product data is returned from Clerk. If not set, Clerk only returns product IDsfilter
: A string that configures Clerk to only return a subset of products. Used with existing filters on the page or Clerksfacets
to allow customers to narrow down resultsfacets
: A list of attributes to be returned as product options that can then be converted to a filter when a visitor selects itlabels
: The label(s) associated with the category page. Used for identifying performance in my.clerk.iovisitor
: The visitor ID of the current visitor browsing
Filtering results
- When sending
facets
in the request, Clerk will return a list of the possible filter options for that result set. E.g. if the cheapest product in the category is €10 and the most expensive one is €500, the lowest price bucket could be €10-50, and the highest €450+ or similar. One category might have 10 different brands and another only 3 in the facets. - When a visitor selects an option, it should be converted into a filter that is sent in the next API call. E.g.
filter=’(price > 10 and price < 100) and brand=”Swarovski"'
- We recommend creating a graphical interface based on Clerks facets and listing them as selectable options as this automatically keeps track of which options are available in each category.
- It can also be done using an existing filter GUI, as long as the visitors choices can be converted to a filter string
- Read more about filters here
Paginating results
- The
limit
andoffset
parameters are used together for pagination limit
controls the amount of products to return for each calloffset
controls the starting point in the full list of results- The first call should have
offset: 0
, and each consecutive calloffset: offset + limit
- Page 1:
limit: 60
,offset: 0
- Page 2:
limit: 60
,offset: 60
- Page 3:
limit: 60
,offset: 120
- … and so on
- Page 1:
- The
count
key from the API response contains the total amount of products in the category, regardless oflimit
. It can be used to calculate the amount of pages by dividingcount
withlimit
and rounding up. E.g:pages = ceil(count / limit)
Full API request & response example
Here is a full example of a call and response to display products on a category.
It’s configured display:
- Products from the category with ID 13
- 50 products on the second page using limit and offset of 50
- Products with the type “Star Wars” using filters
- Ordered by price low-high using orderby price with ascending order
- Facets for the price and category
// Request
curl --request POST \
--url 'https://api.clerk.io/v2/recommendations/category/popular' \
--header 'accept: application/json' \
--header 'content-type: application/json'
-d '{"key": "Ipkv9tKfxRdpLv3mpMhqxfWGNdqugE0c",
"limit": 50,
"category": 13,
"offset": 50,
"orderby": "price",
"order": "asc",
"attributes": ["id","name","image","price", "url"],
"filter": "type = \"Star Wars\"",
"facets": ["price", "category"]
"labels": ["Category Page Grid - Popular"],
"visitor": "xfgu47fd2"
}'
// Response
{
"status": "ok",
"result": [
27988,
25629,
22482,
26994,
27001,
28098,
22484,
25623,
27746,
28097
],
"count": 11,
"facets": {
"categories": [
{
"type": "unit",
"name": "Home Accessories",
"value": 81,
"count": 1
},
{
"type": "unit",
"name": "Swarovski",
"value": 3436,
"count": 5
},
{
"type": "unit",
"name": "Home Accessories",
"value": 3418,
"count": 5
}
],
"price": [
{
"type": "range",
"name": "50 - 99",
"min": 50,
"max": 99.99,
"count": 1
},
{
"type": "range",
"name": "100 - 149",
"min": 100,
"max": 149.99,
"count": 3
},
{
"type": "range",
"name": "200 - 249",
"min": 200,
"max": 249.99,
"count": 1
},
{
"type": "range",
"name": "300 <",
"min": 299.99,
"max": 383,
"count": 6
}
]
},
"product_data": [
{
"id": 27988,
"image": "https://warstars.com/images/star_wars_tie_fighter_ornament.jpg",
"name": "Swarovski Star Wars Tie Fighter Ornament ",
"price": 76,
"url": "https://warstars.com/products/star_wars_tie_fighter_ornament"
},
{
"id": 25629,
"image": "https://warstars.com/images/swarovski_star_wars_mandalorian_the_child.jpg",
"name": "Swarovski Star Wars Mandalorian, The Child",
"price": 112.5,
"url": "https://warstars.com/products/star_wars_mandalorian_the_child"
},
{
"id": 22482,
"image": "https://warstars.com/images/swarovski_star_wars_master_yoda.jpg",
"name": "Swarovski Star Wars Master Yoda",
"price": 131.52,
"url": "https://warstars.com/products/star_wars_master_yoda"
},
{
"id": 26994,
"image": "https://warstars.com/images/swarovski_star_wars_ewok_wicket.jpg",
"name": "Swarovski Star Wars Ewok Wicket",
"price": 132,
"url": "https://warstars.com/products/star_wars_ewok_wicket"
},
{
"id": 27001,
"image": "https://warstars.com/images/swarovski_star_wars_han_solo.jpg",
"name": "Swarovski Star Wars Han Solo",
"price": 212.5,
"url": "https://warstars.com/products/star_wars_han_solo"
},
{
"id": 28098,
"image": "https://warstars.com/images/swarovski_star_wars_boba_fett.jpg",
"name": "Swarovski Disney Star Wars Boba Fett",
"price": 300,
"url": "https://warstars.com/products/star_wars_boba_fett"
},
{
"id": 22484,
"image": "https://warstars.com/images/swarovski_star_wars_darth_vader.jpg",
"name": "Swarovski Star Wars Darth Vader",
"price": 320,
"url": "https://warstars.com/products/star_wars_darth_vader"
},
{
"id": 25623,
"image": "https://warstars.com/images/swarovski_star_wars_x_wing_starfighter.jpg",
"name": "Swarovski Star Wars X-Wing Starfighter",
"price": 320,
"url": "https://warstars.com/products/star_wars_x_wing_starfighter"
},
{
"id": 27746,
"image": "https://warstars.com/images/swarovski_star_wars_chewbacca.jpg",
"name": "Swarovski Star Wars Chewbacca",
"price": 340,
"url": "https://warstars.com/products/star_wars_chewbacca"
},
{
"id": 28097,
"image": "https://warstars.com/images/swarovski_star_wars_obi_wan_kenobi.jpg",
"name": "Swarovski Disney Star Wars Obi-Wan Kenobi",
"price": 350,
"url": "https://warstars.com/products/star_wars_obi_wan_kenobi"
}
]
}
Using Clerk.js
Clerk.js is a library that makes it easy to call Clerks API, apply tracking and handling styling.
- The setup works very similarly, although API calls are done from the frontend, using HTML snippets
- By including the Clerk.js script in your header, you can use snippets directly in your frontend
- If you use any of extensions or plugins (e.g. for Magento2 or WooCommerce), Clerk.js will likely already be included
- Clerk.js scans the website for any snippets with the class
clerk
, and makes API calls using thedata-
parameters - Styling can be done with the Liquid templating language, inside the snippet
- Clerk.js can handle pagination without extra coding, by loading more results on the page at the click of a button, using this function:
Clerk('content', '#SNIPPET_ID', 'more', LIMIT);
- Facets HTML is generated by configuring the snippet with the facets, their translations and a target HTML block to insert them in. Read more about Clerk.js facets here
Full snippet example:
<div id="clerk-category-filters"></div>
<span
id="clerk-category-products"
class="clerk"
data-category="113"
data-facets-target="#clerk-category-filters"
data-facets-attributes='["price","categories"]'
data-facets-titles='{"price": "Pricing", "categories": "Collections", "brand": "Vendor"}'
data-facets-price-prepend="€"
data-facets-in-url="true"
data-facets-view-more-text="View More"
data-facets-searchbox-text="Search for ">
<div class="product-search-result-list">
{% for product in products %}
<div class="product">
<h2 class="product-name">{{ product.name }}</h2>
<img src="{{ product.image }}" title="{{ product.name }}" />
<div class="price">${{ product.price | money }}</div>
<a href="{{ product.url }}">Buy Now</a>
</div>
{% endfor %}
{% if count > products.length %}
<div class="clerk-load-more-button"
onclick="Clerk('content', '#clerk-category-products', 'more', 60);">
Show More Results
</div>
{% endif %}
</div>
</span>