Using Clerk to show full category pages

See how to use our Category Recommendations logics to show all products on category pages.

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:

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 store
  • limit: The amount of products to return
  • category: The ID of the category currently browsed
  • offset: The index to start the result set from. Used with limit for pagination.
  • orderby: An attribute to sort the results on. If not sent, Clerk will order by best selling items
  • order: Can be either asc or desc. Sorts the products in ascending or descending order
  • attributes: 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 IDs
  • filter: A string that configures Clerk to only return a subset of products. Used with existing filters on the page or Clerks facets to allow customers to narrow down results
  • facets: A list of attributes to be returned as product options that can then be converted to a filter when a visitor selects it
  • labels: The label(s) associated with the category page. Used for identifying performance in my.clerk.io
  • visitor: 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 and offset parameters are used together for pagination
  • limit controls the amount of products to return for each call
  • offset controls the starting point in the full list of results
  • The first call should have offset: 0, and each consecutive call offset: offset + limit
    • Page 1: limit: 60, offset: 0
    • Page 2: limit: 60, offset: 60
    • Page 3: limit: 60, offset: 120
    • … and so on
  • The count key from the API response contains the total amount of products in the category, regardless of limit. It can be used to calculate the amount of pages by dividing count with limit 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 the data- 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>