Dynamic Facets Positioning
On this page
The dynamic facets positioning solution lets you update the display order of your facets based on your users’ search query.
The relevance of specific facets varies based on a user’s search input. For example, if a user types “red shirt”, then color facets become less important than those for brand or size. By repositioning facets based on user queries, you can maximize the relevance of your facets, improve and streamline user experience, and help users find what they’re looking for faster.
Solution requirements
Difficulty |
|
Plan | Premium |
Features | Rules |
Prerequisites | Instant Search 3+ |
Implementation guide
To dynamically implement positioned facets, create a Rule for each query and context whose displayed facets you want to reposition. The Rule’s consequence should return a customData
object that defines a new facet order.
After creating your Rules, make a custom widget with a custom render method. For every query that your user enters, this custom widget checks if the customData
, which contains the facet positions, has been returned. It then sets the order CSS property for each of your facet containers to its corresponding position value.
Creating Rules
Your Rule should be triggered by the queries or contexts for which you want to dynamically reposition facets. These Rules should return a customData
object containing a facetPositions
list. The facetPositions
list should contain objects with two attributes:
name
: the name of the facet you want to reposition,position
: the new position of that facet.
1
2
3
4
5
6
7
8
9
10
11
12
{
"facetPositions": [
{
"name": "facetName1",
"position": 2
},
{
"name": "facetName2",
"position": 1
}
]
}
Using the dashboard
- Select the Rules section from the left sidebar menu in the Algolia dashboard.
- Under the heading Rules, select the index you are adding a Rule to.
- Click the New rule button.
- In the Condition(s) section, keep Query toggled on, select Contains in the dropdown, and enter the keyword whose displayed facets you want to reposition. Whenever this term appears in your user’s search result, your Rule repositions the according to the Rule’s consequence.
- In the Consequence(s) section:
- Click the Add consequence button and select Return Custom Data.
- In the input field that appears, provide the following JSON code:
Copy
1 2 3 4 5 6 7 8 9 10 11 12
{ "facetPositions": [ { "name": "brand", "position": 2 }, { "name": "color", "position": 1 } ] }
- Don’t forget to save your changes.
Repeat this process for each condition which displayed facets you want to reposition.
Using an API client
It’s best to trigger your Rule if a query contains a specific word. Your Rule’s consequence should return a customData
object containing an array of objects with two attributes:
name
: the name of the facet you want to reposition.position
: the new position of that facet.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$rule = [
'objectID' => 'a-rule-id',
'condition' => [
'pattern' => 'dress',
'anchoring' => 'contains',
'alternatives' => true,
],
'consequence' => [
'params' => [
'filters' => 'category = 1',
],
'userData' => [
'facetPositions' => [
[
'name' => 'brand',
'position' => 2,
],
[
'name' => 'color',
'position' => 1,
],
],
],
],
];
$index->saveRule($rule);
Repeat this process for each condition which displayed facets you want to reposition.
Create a dynamic facet positioning rendering widget
Add the display:flex
CSS attribute to your facet container. This lets you use the order
CSS property.
In your instantsearch
widget, add a custom widget. This custom widget only requires a render method, which takes a renderOptions
parameter.
1
2
3
4
5
search.addWidget({
render(renderOptions) {
// ...
}
});
Define three constants:
results
: the search results of your user’s current query.userData
: theuserData
returned with the current results (this is where you store thecustomData
object returned by your Rule).facetsContainer
: the DOM element that contains your facets.
1
2
3
4
5
6
search.addWidget({
render(renderOptions) {
const results = renderOptions.results;
const userData = results.userData;
const facetsContainer = document.querySelector("#facets-container");
});
Revert to the default order of your facets by setting the order
of each facet element to its position in your facetsContainer
. Then, check whether userData
is empty, and return if that’s the case (it would mean that no dynamic faceting Rule was triggered).
1
2
3
4
5
6
7
8
9
10
11
12
search.addWidget({
render(renderOptions) {
// ...
// Revert to default order of facets
Array.from(facetsContainer.children).forEach((node, index) => {
node.style.order = index + 1;
});
if (!userData) return null;
}
});
Your results may contain userData
that is unrelated to facet positions. This means you need to extract your facet positioning customData
, to verify that it exists and that it’s properly formatted.
1
2
3
4
5
6
7
8
9
10
11
12
search.addWidget({
render(renderOptions) {
// ...
// Update order of facets per query
const customFacetsData = userData.find(
data => data.facetPositions && Array.isArray(data.facetPositions)
);
if (!customFacetsData) return null;
}
});
For each facetPosition
object in customData
, a DOM element is selected based on the facet’s name. This element’s order
property is then set to the position defined in your customData
object.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
search.addWidget({
render(renderOptions) {
// ...
customFacetsData.facetPositions.forEach(facet => {
const element = document.getElementById(facet.name);
if (element) {
// Order property is zero-based, so we decrement by one
element.style.order = facet.position - 1;
}
});
}
});