Product grouping
Product grouping
In an ecommerce interface, you’ll often want to group similar products together. For example, if a certain type of bicycle helmet comes in various colors, you could display those variations as smaller images below the main product image.
The mechanism required for product grouping to apply is filtering (that is, the filterField
and filterFieldRange
query parameters).
In addition, ranking within the group of products is controlled by query ranking expressions (QREs) and can dramatically improve the user experience, but product grouping will work without it.
Grouping field configuration
Grouping is done between products that share the same value for a specific field.
Leading practice
We recommend that you use |
Suppose that in your catalog data, whenever a product comes in different colors, all color variations of that product share the same unique "root" substring in their product IDs. In such a scenario, you could index these root IDs into your grouping field for each product:
Product description | Product identifier value | Desired ec_item_group_id value |
---|---|---|
Bicycle helmet model 001 (gray) |
bhelmet001-gray |
bhelmet001 |
Bicycle helmet model 001 (red) |
bhelmet001-red |
bhelmet001 |
Bicycle helmet model 001 (blue) |
bhelmet001-blue |
bhelmet001 |
Bicycle helmet model 002 (gray) |
bhelmet002-gray |
bhelmet002 |
Bicycle helmet model 002 (red) |
bhelmet002-red |
bhelmet002 |
Bicycle helmet model 002 (blue) |
bhelmet002-blue |
bhelmet002 |
You could then use that field to request grouped products (as explained in the Set up the pipelines section).
Your grouping field must be configured as follows:
-
Must be set as facet.
-
Must be of type
String
.
Set up the pipelines
To request grouped products, you must apply the following filters in your Query Pipelines (platform-ca | platform-eu | platform-au), under the Advanced tab.
Filter field grouping
The filterField
query parameter is used to set the field to execute the grouping and is entered in the Query parameters, directly in the query pipeline.
Filter field range
The filterFieldRange
parameter controls the number of items returned in the group.
This is used to define how many results are returned to the group.
In the following example, we want to return 10
results.
If you want to show all of the items in your group, ensure the number entered is equal to the number of items you have in your biggest product group.
Products from the same group
Products from the same group are retrieved with a disjunction query expression (dq
) that fetches all the products using the same ec_item_group_id
as the one returned by the query.
To create this expression, in the Filters section, click Add rule.
In the Query Parameter dropdown menu, always select dq
, then enter the expression.
To be used with Dynamic facets
(@source=="exampleCatalog")([[@ec_item_group_id]($query) ($originalQuery)($facetsFilter)])
-
@source
is the name of your Catalog source. -
[@ec_item_group_id]
is another item with the sameec_item_group_id
. -
$originalQuery
is the manual query (q parameter) that initially gets sent before modifications. -
$facetsFilter
query expression that represents the filters introduced by the selection of dynamic facets.
To be used with Legacy facets
(@source=="exampleCatalog")([[@ec_item_group_id]($query) ($originalAdvancedQuery)])
-
@source
is the name of your Catalog source. -
[@ec_item_group_id]
is another item with the sameec_item_group_id
. -
$originalAdvancedQuery
is the advanced query that initially gets sent to the platform before any modifications are made by filters or query parameters.
Note
Only Dynamic facets are used within a Coveo Headless-based search interface. |
Product grouping main item
Grouped items aren’t displayed in any particular order. However, you can improve the experience with ranking expressions. You can boost a color field if that value is present in the query. This will move the appropriate product to the top as the main item.
To apply these expressions, select a pipeline from the Query Pipelines (platform-ca | platform-eu | platform-au) page. Under the Result Ranking tab, click Add Rule, and then select Ranking expression.
For example, performing a search for "shoes" will return shoes as a result with their grouped items in no particular order. Performing a search for "red shoes" will return any red shoes as the main item, and place all other colors as grouped items underneath.
Using the @color
field would result in:
@color=$splitValues(text: $query, separator: '\s')
Then, use the slider to increase the boost by 100
In case of a facet selection, this expression can extract the right value from the advanced query and add it to the expression:
@color=$valuesOfField(field: '@color', resultSet: $advancedQuery)
Note
When using Dynamic facets, you would need to replace |
Refer to the product grouping template based on your use case, With JSUI or With Headless.
Product grouping and Coveo Machine Learning
Product grouping with an ART model
When creating an ART model that aims at boosting groups of products on a commerce interface, you must activate the recommendProductGroup
advanced model parameters.
By doing so, this will indicate that the model:
Product grouping within a recommendation component
Recommended product grouping uses the same principles as product grouping, but with additional modifications to the ML model configuration. The group shown is based on the product recommendation (PR) strategies set by the user.
This method should be applied when you’re already returning recommendations, but instead of showing individual products, you want to show the product within a group defined by the ec_item_group_id
field.
The base configurations are the same as product grouping, set the Grouping field configuration and the Filter field grouping query parameters.
In addition, you then need to create a PR model and associate the PR model to your pipeline.
Model configuration
When creating a PR model that recommends groups of products, you must activate the recommendProductGroup
advanced model parameter.
By doing so, this will indicate that the model must return groups of products rather than individual products.
Model association configuration
Once you’ve associated the PR model to your query pipeline, you must edit the PR model association via a JSON configuration to modify the ML model’s configuration by adding the following parameter:
"maxRecommendations":__
Your ec_item_group_id
group contains 7 products and you want there to be enough products to populate a full carousel of items frequently viewed together.
You need to request more items to return less results, as the recommendations are folded under those groups. The value greatly depends on the number of products per group.
{
"id": "<ORG_ID>",
"position": "1",
"modelId": "<MODEL_ID>",
"modelDisplayName": "<MODEL_DISPLAY_NAME>",
"modelEngine": "ecommerce",
"modelStatus": "Updating",
"rankingModifier": 1000,
"maxRecommendations": 50,
"exclusive": true,
"customQueryParameters": {
"strategy": "frequentlyViewed"
},
"useAdvancedConfiguration": true,
}
By grouping products, you filter down the output of the model at the group level, therefore you must request more recommendations to ensure that your component is populated accordingly.
Note
You can request up to a maximum of |
Product grouping template
In the result templates, use a loop to access the child results.
This will show the related items in the same group.
When using the filterField
parameter, the items with the same value for that field appear under childResults
in the search response.
Note
Whether you use a full search interface with a result list or you implement a product recommendation component, you get a results list in both cases. The template usage is identical but the behaviors are slightly different. |
The following example iterates over the child to show the related products.
With JSUI
Here’s the code to produce the previous image:
import {
Component,
ComponentOptions,
IComponentBindings,
Initialization,
} from 'coveo-search-ui';
export interface IRelatedProductsOptions { }
export class RelatedProducts extends Component {
static ID = 'RelatedProducts';
static options: IRelatedProductsOptions = {};
constructor(public element: HTMLElement, public options: IRelatedProductsOptions, public bindings: IComponentBindings, public result: any) {
super(element, RelatedProducts.ID, bindings);
this.options = ComponentOptions.initComponentOptions(element, RelatedProducts, options);
const relatedProducts = result.childResults || [];
if (relatedProducts.length) {
// for each related product, create an array of Html <div> to display it.
const imagesHtml = relatedProducts.map(product => `
<div style="background-image: url(${product.raw.image})" title="${product.raw.color}">
<a href="show.html#p=${product.raw.permanentid}" title="${product.raw.color}"> </a>
</div>
`);
// Show the related products in the HTML for this result.
element.innerHTML = `
<b>Also available in:</b>
<div>
${imagesHtml.join('\n')}
</div>
`;
}
}
}
Initialization.registerAutoCreateComponent(RelatedProducts);
Note
This is a custom component, meant to be used as a |
With Headless
When using the Coveo Headless library, you’ll need to create a special-purpose result template.
The following example code shows a basic use case of the ResultTemplatesManager
and will produce the previous image.
You can access products from the same group by using the childResults
property on the result object.
import { buildResultTemplatesManager,
ResultTemplatesManager,
Result,
ResultTemplatesHelpers } from "@coveo/headless";
import { headlessEngine } from "../Engine";
// ...
export default class ResultList {
// ...
private headlessResultTemplatesManager: ResultTemplatesManager;
// ...
constructor(props: any) {
// ...
this.headlessResultTemplatesManager =
buildResultTemplatesManager(headlessEngine);
this.headlessResultTemplatesManager.registerTemplates(
{
conditions: [],
content: (result: Result) => (
<li>
<h4>{result.title}</h4>
<p>{result.excerpt}</p>
<b>Also available in:</b>
<div>
{
// Use the `childResults` property to get the related products, which we map to their HTML representation in order to display them.
result.childResults.map(product => (
<div style="background-image: url(${product.raw.image})" title="${product.raw.color}">
<a href="show.html#p=${product.raw.permanentid}" title="${product.raw.color}"> </a>
</div>
)
)
}
</div>
</li>
)
},
);
// ...
}
// ...
render() {
return (
<ul>
{this.state.results.map((result: Result) => {
const template =
this.headlessResultTemplatesManager.selectTemplate(result);
return template(result);
})}
</ul>
);
}
}
Limitations
Grouped products are treated as regular items by the Commerce and Search APIs.
For example, if 5 items share the same ec_item_group_id
value, the APIs will return 5 items, even though only 1 appears as a product card in the results list.
This behavior can impact query performance because the per-page limit applies to the number of products shown in the results list, not the total items returned. For example, if the per-page limit is 20 and each product includes 5 grouped items, the API will return 100 items, even though only 20 are displayed in the results list.
For optimal performance, Coveo recommends keeping the total number of items (parents and children combined) returned by a query to 100 or fewer.
Debugging product grouping
You may want to ensure that the product grouping you’ve set up is working as intended. Before proceeding with the following steps, you’ll first need to complete the preceding Grouping field configuration and Set up the pipelines sections.
-
In your Coveo organization, open the Content Browser (platform-ca | platform-eu | platform-au).
-
Open your web browser’s developer tools.
NoteThe examples in this article use the Google Chrome developer tools. For browser-specific information, see:
-
Select the Network tab.
-
Back in the Content Browser, in the Source facet, select the source you are attempting to validate.
-
In the Pipeline dropdown menu, select the pipeline where you set up your filter fields for grouping.
-
Back in your browser’s developer tools, under the Name column, select the latest request to the Search API. The request path should contain
v2
. -
Select the Preview tab. You should now see the query response body.
-
In the query response body, you should see an expandable
results
property. You can expand it to see information about the search results for this query. -
Expand one of the results. (for example, the
0
index). -
Expand its child properties, also known as
childResults
. This should hold a list of results that belong to the same group as the main result.
You can also test whether the keywords give priority to the right item. These adjustments to the ranking expressions can be done to the Product grouping main item.
If you search for "red" in the Content Browser, and the "white" product is returned as the main result, you might want to boost the color
field so that it matches the search box keyword, since it should be given a higher priority compared to its siblings.