Implementing an eCommerce Collection Products Page
Fast Simon JavaScript SDK allows developers to create a modern ecommerce collection products page that includes Fast Simon advanced BigData AI, Merchandising, Personalization and more.
Using the Fast Simon JavaScript SDK, you can easily implement the following collection products page capabilities:
Displaying collection results: Retrieves collection results rendered in a product grid.
Filtering collection results: Allows applying filters to refine the collection results.
Navigating through collection results: Support collection results pages either in an infinite single scroll down page manner or as separate pages.
Reporting Shopper Activity: Records activities to enable Fast Simon analytics and improve collection results relevancy.
Getting Collection Results
The smartCollections method allows you to get the collection results for a given collection.
The collection method utilizes the Fast Simon functionality to execute the operation based on the shopper's input. It communicates with the Fast Simon SDK to retrieve the corresponding collection results, filter data, and pagination details.
In the collection input the shopper defines what they are looking for, which is implemented using the categoryID parameter. The callback function contains the relevant products and filters matching the shopper term.
window.FastSimonSDK.smartCollections({
categoryID: category_id,
page: this.page,
productsPerPage: 48,
narrowBy: this.narrowBy,
sortBy: this.sortBy,
onFacetsLoaded: (response) => {
this.renderFacets(response.payload.facets);
},
onProductsLoaded: (response) => {
this.renderProducts(response.payload.products);
windows.FastSimonSDK.event({
eventName: windows.FastSimonEventName.SmartCollectionPreformed,
data: {
categoryID: category_id,
narrowBy: this.narrowBy,
sortBy: this.sortBy,
products: response.payload.products.map(({id}) => id).toString(),
rescount: response.payload.totalResults,
pagenum: Math.ceil(response.payload.totalResults / 48)
}
});
},
inventoryCallback: (response) => {
if (response.payload.productsInventory.length > 0) {
this.renderInventorySection(response.payload.productsInventory);
}
}
});
The smartCollections method options:
Option | Type | Description |
---|---|---|
categoryID | string (required) | collection ID. |
onProductsLoaded | response void (required) | Callback to handler the collection products results. |
onFacetsLoaded | response void (required) | Callback to handler the collection facets results. |
page | number Default: 1 | Page number to retrieve. |
productsPerPage | Number Default: 40 | Determines how many products are displayed on each page. Note: Make sure that the productsPerPage is the same on all pages. |
sortBy | sortBy Default: relevency | Determines the sort order by which the shopper sorts the list of products. example of Sorting Results |
narrowBy | narrowBy Default: [] | Determines what filters are used to narrow the results. example of narrowBy |
facets | boolean Default: true | Determines whether to fetch filters (to allow shoppers to narrowBy parameter). |
withAttributes | boolean Default: false | Determines whether to include attributes in the product response. Note: might increase latency, so use only if you need product tags or attributes. |
inventoryCallback | response void | Callback to handler the inventory results. |
withProductTypes | boolean Default: false | Determines whether to include Product Types in the response. |
searchWithinSearch | string (required) | Search bar within the filters menu to refine results. |
Getting Collection Results and Reporting Shopper Activity
Having a fast rendered collection results is key to optimizing user experience and conversion optimization. Below is a short code snippet illustrating getting collection results, rendering products and filters and reporting on shopper activity.
window.FastSimonSDK.smartCollections({
categoryID: category_id,
page: this.page,
productsPerPage: 48,
narrowBy: this.narrowBy,
sortBy: this.sortBy,
onFacetsLoaded: (response) => {
this.renderFacets(response.payload.facets);
},
onProductsLoaded: (response) => {
this.renderProducts(response.payload.products);
if(response.payload.bannerHTML) {
this.renderBanner(response.payload.bannerHTML)
}
windows.FastSimonSDK.event({
eventName: windows.FastSimonEventName.SmartCollectionPreformed,
data: {
categoryID: category_id,
narrowBy: this.narrowBy,
sortBy: this.sortBy,
products: response.payload.products.map(({id}) => id).toString(),
rescount: response.payload.totalResults,
pagenum: Math.ceil(response.payload.totalResults / 48)
}
});
}
});
Notice that the callback function can be fired once or twice depending whether the server completed the facets results. Here are the possible situations for you to prepare to;
response.action Value | Description |
---|---|
“products” | Render collection results products in a grid. |
“facet and products” | Rending pages facets (filters). |
Getting Collection Results with searchWithinSearch
and Reporting Shopper Activity
Rendering fast collection results is key to enhancing user experience and driving conversions. The searchWithinSearch
feature allows users to refine their results further by entering a query in a search bar available within the collection page.
Expected UI Flow:
- Initial Load: The collection page is rendered with the full set of products based on the initial parameters.
- Search Bar Within Collection: A search bar appears on the collection page, allowing users to perform a secondary search to filter the displayed results further.
Code Example:
// Function to handle collection requests and render results
function loadCollection({ searchWithinSearch = "" } = {}) {
window.FastSimonSDK.smartCollections({
categoryID: category_id,
page: this.page,
productsPerPage: 48,
narrowBy: this.narrowBy,
sortBy: this.sortBy,
searchWithinSearch, // Pass the search query if available
onFacetsLoaded: (response) => {
this.renderFacets(response.payload.facets);
},
onProductsLoaded: (response) => {
this.renderProducts(response.payload.products);
if (response.payload.bannerHTML) {
this.renderBanner(response.payload.bannerHTML);
}
window.FastSimonSDK.event({
eventName: searchWithinSearch
? window.FastSimonEventName.SearchWithinPerformed
: window.FastSimonEventName.SmartCollectionPreformed,
data: {
categoryID: category_id,
narrowBy: this.narrowBy,
sortBy: this.sortBy,
searchWithinSearch,
products: response.payload.products.map(({ id }) => id).toString(),
rescount: response.payload.totalResults,
pagenum: Math.ceil(response.payload.totalResults / 48),
},
});
},
});
}
// Initial collection load
loadCollection();
// Search Within Results
const searchBar = document.getElementById("search-within-results-bar");
searchBar.addEventListener("input", (event) => {
const searchQuery = event.target.value;
loadCollection({ searchWithinSearch: searchQuery });
});
# Rendering collection results in a Product Grid
A product grid is a layout or display format used to present products. It is a structured arrangement of product thumbnails or tiles, organized in a grid-like pattern.
The product grid is designed to provide shoppers with the available products and data allowing them to browse and compare items quickly.
## What data to include in the product grid
With Fast Simon SDK you can create a product grid that displays the following product properties:
```javascript
interface Product {
c: string // currency
d: string // description
f: number // product merch stuff
id: string // product id
iso: boolean // is sold out
l: string // product title
p: string // price
p_c: string // comapre price
p_max: string
p_max_c: string
p_min: string
p_min_c: string
p_spl: number
review: number // review score
reviews_count: number // review count
s: string // sku (shopify foramt)
sku: string // sku
skus: string[] // skus
t: string // main image
t2: string // fallback image
u: string // url
v_c: number // varaint count
vra: Variant[] //product variants
vrc: object
att?: Attribute[] // product attribiutes
alt?: AlternativeProduct[] // alternative (sibiling) products
}
type Variant = [string, VariantData[]]
type VariantData = [string, string[]]
type Attribute = [string, AttributeData[]]
type AttributeData = [string, string[]]
export type AlternativeProduct = [AlternativeProductName, AlternativeProductURL, productID?]
type AlternativeProductName = string
type AlternativeProductURL = string
type productID = number
The product grid options:
Option | Type | Description |
---|---|---|
c | string | Product currency |
d | string | Product description |
f | number | Product merch stuff |
id | string | Product ID |
iso | boolean | Product is sold out or not |
l | string | Product main title |
p | string | Product price |
p_c | string | Product compare price in case of sale |
p_max | string | Variant max price range |
p_max_c | string | Compare variant max price range |
p_min | string | Variant min price range |
p_min_c | string | Compare variant min price range |
p_spl | number | · 1 if the product has variants · 0 in case of no variants |
p_spl_id | string | The ID of the product with variants |
review | number | Review number out of score rate between 0 – 100 |
review_count | number | The number of people reviewed the product |
s | string | SKU Shopify format codes that you can use internally to track your inventory and report on your sales. |
sku | string | SKU regular format |
skus | string | List of variant skus related to product. |
t | string | URL product main image |
t2 | string | URL fall back generic image presented only when the main URL is not accessible. |
u | string | Product location URL |
v_c | number | Variants count number |
vra | Variant[] | Product variants list |
vrc | object | Defined attributes for variant list. |
att? | Attribute[] | Product attributes such as tags custom defined per customer. |
alt? | AlternativeProduct[] | Alternative (sibling) products linked to the main product as viewed alternative selections. |
In addition, you can incorporate various features and interactions within the product grid, such as sorting options, filtering capabilities, and pagination, to enhance the browsing experience and help shoppers find desired products efficiently. To implement product grid characteristics Use the data in response.payload.products.product.vra The 'vra' property comprises a list of product variants, with each variant containing information about its specific options (e.g., Size and Color).
For example:
{
"vra": [
[39746014183484, [["Barcode", ["WFTOP391-1-XS"]], ["Price", ["USD:44.99"]], ["Product-sku", ["WFTOP391-1-XS"]], ["Sellable", [true]], ["Size", ["XS"]], ["Weight", ["130"]]]],
[39746014216252, [["Barcode", ["WFTOP391-1-S"]], ["Price", ["USD:44.99"]], ["Product-sku", ["WFTOP391-1-S"]], ["Sellable", [true]], ["Size", ["S"]], ["Weight", ["130"]]]],
[39746014249020, [["Barcode", ["WFTOP391-1-M"]], ["Price", ["USD:44.99"]], ["Product-sku", ["WFTOP391-1-M"]], ["Sellable", [true]], ["Size", ["M"]], ["Weight", ["130"]]]],
[39746014281788, [["Barcode", ["WFTOP391-1-L"]], ["Price", ["USD:44.99"]], ["Product-sku", ["WFTOP391-1-L"]], ["Sellable", [true]], ["Size", ["L"]], ["Weight", ["130"]]]],
[39746014314556, [["Barcode", ["WFTOP391-1-XL"]], ["Price", ["USD:44.99"]], ["Product-sku", ["WFTOP391-1-XL"]], ["Sellable", [false]], ["Size", ["XL"]], ["Weight", ["130"]]]]]
}
Implementation Examples
The full example of implementation you can find in the Fast Simon GitHub: Fast-Simon-Sample-JavaScript-SDK
HTML:
<div id="productGrid"></div>
JavaScript:
// Render product grid
renderProductGrid(response.payload.products);
function renderProductGrid(products) {
productGrid.innerHTML = ''; //remove previous results
products.forEach((product) => {
// Render product card
const productCard= document.createElement('div');
productCard.setAttribute('id', product.id);*// product id*
const title = document.createElement('div');
title.innerText = product.l; *// product title*
const image= document.createElement('img');
image.src = product.l; *// main image*
const price = document.createElement('span');
title.innerText = product.p; *// price*
productCard.appendChild(image);
productCard.appendChild(title);
productCard.appendChild(price);
productGrid.appendChild(productCard);
});
}
Implementing a Routing Manager
A routing manager handles navigation and routing within an ecommerce website. It plays an important role in processing incoming requests and user interactions, ensuring they are directed to the appropriate URL destinations.
A routing manager is used to manage the navigation between different pages or views. It updates the URLs when filters or pagination options are selected. This results in URLs that contain the necessary data to easily select the desired page and apply specific filters whenever needed.
By implementing routing manager, the website's URLs become consistent for given queries and filters. This allows shoppers to conveniently revisit previous collection results or specific filtered views by simply accessing the saved URL (or shared by shoppers for other people).
Suggested structure:
- Listener to the URL changes.
- URL Parser that can get the URL and build the query, filters, pagination, sortBy values.
- URL Generator which should build the URL every time a user uses a query, filters, pagination, or sortBy.
What data you get in inventory callback response
With Fast Simon SDK you can create a product grid that displays the inventory details:
interface InventoryResponse {
action: "products inventory"
payload: {
productsInventory: {
id: string;
totalInventory: number;
}[];
}
}
Rendering Collection Results Filters
Fast Simon SDK provides the ability to present filters for shoppers per a given collection. Facets are versatile filtering options that allow them to refine their collection results based on specific attributes of the collection results.
Facets are typically displayed as a set of options that shoppers can interact with to narrow down their collection results and find the most relevant information or products.
With Fast Simon SDK you can retrieve the data to implement the following facet types:
Facet Type | Illusration |
---|---|
Checkbox | |
Price slider | |
Color swatches |
Working with Facets
Render filters: You can render the search term facets found in the response.payload.facets.
Narrow results: Perform a search after the shopper selects a facet option and performs a collection request with the narrowBy: parameter.
Implementation examples
The full example of implementation you can find in the Fast Simon GitHub: Fast-Simon-Sample-JavaScript-SDK
The following are simple implementation examples.
HTML:
<div id="filters"></div>
JavaScript:
renderFilters(response.payload.facets);
function renderFilters(facets) {
const filtersContainer = document.getElementById("filters");
filtersContainer.innerHTML = ''; // Clear previous filters
const filterContainer = document.createElement("div"); // Create a container div for the filter
filterContainer.classList.add('fs_filter_container');
const labelElement = document.createElement("label"); // Create a label element for the filter
labelElement.classList.add('fs_label_element');
labelElement.setAttribute("name", `${facet[0]}`);
labelElement.textContent = facet[2]; //you can change this name in the dashboard
// Create checkboxes for each filter option
for (let j = 0; j < facet[1].length; j++) {
const option = facet[1][j][0]; // Value of the checkbox
const count = facet[1][j][1]; // Number of products matching this filter
const checkboxWrap = document.createElement("div");
const checkboxCount = document.createElement("span");
checkboxCount.innerText = `(${count})`;
const checkboxElement = document.createElement("input");
checkboxElement.type = "checkbox";
checkboxElement.value = option;
checkboxElement.setAttribute("key", `${facet[0]}`);
checkboxElement.setAttribute("name", `${facet[2]}`);
// Add event listener to handle checkbox selection
checkboxElement.addEventListener("change", () => handleCheckboxSelection(checkboxElement));
const optionLabel = document.createElement("label");
optionLabel.textContent = option;
optionLabel.textContent = option; // for categories use:facet[1][j] [2];
checkboxWrap.appendChild(checkboxElement);
checkboxWrap.appendChild(optionLabel);
checkboxWrap.appendChild(checkboxCount);
filterContainer.appendChild(checkboxWrap);
}
}
Sorting Results
A sortBy function allows to organize the products on a page according to different parameters, which enables finding what the shoppers are looking for faster and easier.
By providing a simple and easy-to-use sorting capability, businesses can enhance user experience and potentially increase sales.
Here are the possible sorting options (notice they first need to be turned on in the Fast Simon Dashboard in the collection results Configuration)
const FastSimonSortBy = {
PriceHighToLow: "price_max_to_min",
PriceLowToHigh: "price_min_to_max",
NewFirst: "creation_date",
OldFirst: "creation_date_oldest",
Popularity: "popularity",
Reviews: "reviews",
AtoZ: "a_to_z",
ZtoA: "z_to_a",
relevancy: "relevency"
};
Fast Simon provides the following sorting options:
Option | Value | Description |
---|---|---|
PriceHighToLow | "price_max_to_min" | Sorts results by product price from high to low. |
PriceLowToHigh | "price_min_to_max" | Sorts results by product price from low to high. |
NewFirst | "creation_date" | Sorts results by latest product insertion by date. |
OldFirst | "creation_date_oldest" | Sorts results by oldest product insertion by date. |
Popularity | "popularity" | Sorts results by product popularity calculated by number of clicks, visits, and sells. |
Reviews | "reviews" | Reviews number out of score rate between 0 – 100. |
AtoZ | "a_to_z" | Sorts results by product name in an ascending order. |
ZtoA | "z_to_a" | Sorts results by product name in a descending order. |
relevancy | "relevency" | When the URL returns without the sortBy value, the default result page is displayed. Note: The word relevency in the code appears with a typo. |
Related Categories
An array of related categories that can be used to show a top wheel of related collections.
Implementation examples
HTML:
<div class="related-categories">
<div class="related-categories-container" id="relatedCategoriesContainer"></div>
</div>
JavaScript:
window.FastSimonSDK.smartCollections({
categoryID: category_id,
page: this.page,
productsPerPage: 48,
narrowBy: this.narrowBy,
sortBy: this.sortBy,
onFacetsLoaded: (response) => {
this.renderFacets(response.payload.facets);
},
onProductsLoaded: (response) => {
this.renderProducts(response.payload.products);
if(response.payload.relatedCategories?.length) {
// Render product grid
const container = document.getElementById('relatedCategoriesContainer');
relatedCategories.forEach(category => {
const categoryItem = document.createElement('div');
categoryItem.className = 'category-item';
categoryItem.innerHTML = `
<a href="${category.url}">
<img src="${category.image}" alt="${category.title}">
<div class="category-item-title">${category.title}</div>
</a>
`;
container.appendChild(categoryItem);
});
}
windows.FastSimonSDK.event({
eventName: windows.FastSimonEventName.SmartCollectionPreformed,
data: {
categoryID: category_id,
narrowBy: this.narrowBy,
sortBy: this.sortBy,
products: response.payload.products.map(({id}) => id).toString(),
rescount: response.payload.totalResults,
pagenum: Math.ceil(response.payload.totalResults / 48)
}
});
},
inventoryCallback: (response) => {
if (response.payload.productsInventory.length > 0) {
this.renderInventorySection(response.payload.productsInventory);
}
}
});
export interface RelatedCategory {
id: string
title: string
image: string
url: string
}
const relatedCategories: RelatedCategory[] = [
{
id: "1",
title: "Dresses",
image: "https://example.com/image1.jpg",
url: "https://example.com/category1"
},
{
id: "2",
title: "Top Shirt",
image: "https://example.com/image2.jpg",
url: "https://example.com/category2"
}
];
Pagination
Pagination helps improve user experience by making large amounts of data more manageable and navigable. The following pagination options are available:
Dividing collection results into pages, which can then be navigated using controls usually found at the bottom of the page.
Using an infinite scroll, where collection results are automatically loaded and added to the bottom of the page when the user reaches the end.
Fast Simon SDK automatically identifies the browser behavior for displaying products either through separate pages with their related URLs or through an infinite scroll on a single page. In the case of infinite scroll, the URL is updated every time a page of products is loaded.
Reporting Shopper Activity
Every time a shopper visits a collection page, and the smartCollections method was called an event type smartCollectionPerformed should be fired to make sure Fast Simon dashboard statistics and relevancy keeps being up to date.
window.FastSimonSDK.event({
eventName: window.FastSimonEventName.SmartCollectionPreformed,
data: {
categoryID: this.category_id,
narrowBy: this.narrowBy,
sortBy: this.sortBy,
products: response.payload.products.map(({id}) => id).toString(),
rescount: response.payload.totalResults,
pagenum: Math.ceil(response.payload.totalResults / 48)
}
)};
Event type smartCollectionPerformed mandatory options:
Option | Value | Description |
---|---|---|
categoryID | string | (Required) The viewed category ID |
narrowBy | narrowBy | Set of filters sent |
sortBy | sortBy | Sort method selected |
products | string | List of product IDs |
rescount | string | Number of total results matches in the current event search |
pagenum | number Default: 1 | The current page number |
Product Click Event
Every click on a product in the collection products page, an event type CollectionProductClicked created send update statistics to the admin dashboard.
window.FastSimonSDK.event({
eventName: window.FastSimonEventName.CollectionProductClicked,
data: {
collectionID: "23232", // (Required)
productID: "11223344", // (Required)
position: 5, // counting starting at 1
imageID: "asdfsdfsf" // If Image Optimization is used
}
)};
CollectionProductClicked options:
Option | Value | Description |
---|---|---|
collectionID | string | Query string used |
productID | number | Product identification ID |
position | number | Position of the product from the beginning of the presented products from the collection results |
imageID | number | Optimizations usage send ID in the response back |
Quick View Event
Shopper clicked on product in quick view link and redirected to product page, this creates event type QuickViewProductClicked.
window.FastSimonSDK.event({
eventName: window.FastSimonEventName.QuickViewProductClicked,
data: {
productID: "11223344", // (Required)
originalProduct: "2342432" , // Required)
position: 7 // counting starting at 1
}
)};
QuickViewProductClicked options:
Option | Value | Description |
---|---|---|
productID | number | Product identification ID |
originalProduct | number | Internal ID |
position | number | Position of the product from the beginning of the presented products from the collection results |