In Sitecore Search, facets are used to classify your content. These usually contain values that are strings, numbers and possible even a range. In general, these allow users to narrow down results to a more specific set based on certain classification.
In order to get our facets we’ll need to do more configuration in the Customer Engagement Console (CEC). Always remember to double check if all the configurations are done here before applying it on your frontend widget. A little tip as well is to start here as well when debugging any problems on your Sitecore Search, you might realize you have the setup wrong and it has nothing to do with your code.
First thing to do is look at the attributes list in the Customer Engagement Console. Attributes are the important metadata that we specify to collect and use in Sitecore Search. These data are used to help display certain results, create analysis and help improve the whole search experience. To navigate to the list you’ll have to click on Administration > Domain Settings > Attributes.
Always give your best judgment on what attributes are best used as facets. I don’t advise to decide and make most of everything a facet just to help the users. Allowing the user to sift and filter every part of each item doesn’t really mean it’s a good search experience. These attributes are usually a page category, page type, certain organizational criteria that can group together content.
Now, let’s try and add a new attribute which allows it to be used as a facet. Click on the + Add Attribute and you will see a form with the following fields
If you decide that it’s an attribute that should appear as a facet then open Use For Features and check the Facets checkbox.
Click Save and move the the Feature Configuration tab and open the Facets accordion.
You will see the list of the different attributes which have Facets enabled. By default, you don’t have to worry a lot since the default setup will be there once you created your attribute.
Let’s now setup the Facets in our widgets by navigating to Widgets > Variant.
Go further into the specific variation you would like to modify. The steps here will be similar to how we setup the Sort Options. Open the Last icon on the left sidebar to see all the different features available. By default the Facets should be the first tab. Here you will see all the possible Facets available and which ones are enabled.
If you need to enable or disable a facet just expand the attribute, then you will see three icons on the right side. Make sure to click on the right most. It will have either the enable or disable button.
After everything, don’t forget to save and publish all the changes we’ve done.
We are now capable of adding the facets into our widget on the frontend. Here’s how to configure your Frontend
Widget to get the facets working. On the widget file, locate the piece of code that uses the
useSearchResults
and make sure to add the necessary parts based on the code below. These are the actions
onFacetClick
, onRemoveFilter
and the data section of the queryResult which should have the
facet
array.
const {
widgetRef,
actions: { onFacetClick, onRemoveFilter }, // CODE RELATED TO FACET SETUP
state: { page, itemsPerPage },
queryResult: {
isLoading,
isFetching,
data: {
facet: facets = [], // CODE RELATED TO FACET SETUP
} = {},
},
} = useSearchResults({
query: (query) => { query.getRequest() },
state: {
page: defaultPage,
itemsPerPage: defaultItemsPerPage,
keyphrase: defaultKeyphrase,
},
});
To make your life easier, @sitecore-search/react
has a hook that gets all the facets that are enabled on
your widget. This will be useful for displaying all the facets the user has active.
import { useSearchResultsSelectedFilters } from '@sitecore-search/react';
const selectedFacetsFromApi = useSearchResultsSelectedFilters();
The code below is an example of how the facets is added. We can further break it down and explain each part.
{selectedFacetsFromApi?.length > 0 && (
<div className="flex flex-col gap-3">
<span className="eyebrow text-neutral-100">Filters</span>
{facets.map((selectedFacet) => (
<span
key={`${selectedFacet.facetId}${selectedFacet.facetLabel}${selectedFacet.valueLabel}`}
>
<div className="flex gap-3 justify-center items-center label-regular shadow-one bg-transparent border-1 border-neutral-70 text-neutral-70 w-fit h-7 rounded-5 px-2.5">
<span>{selectedFacet.valueLabel}</span>
<span
className="cursor-pointer"
onClick={() => onRemoveFilter(selectedFacet)}
>
X
</span>
</div>
</span>
))}
</div>
)}
<SearchResultsAccordionFacets
defaultFacetTypesExpandedList={[]}
onFacetTypesExpandedListChange={() => null}
onFacetValueClick={onFacetClick}
>
{facets.map((f) => (
<AccordionFacets.Facet className="" facetId={f.name} key={f.name}>
<AccordionFacets.Header className="border-b border-neutral-10 items-center flex">
<AccordionFacets.Trigger className="label-regular text-neutral-100">
{f.label}
</AccordionFacets.Trigger>
<Caret />
</AccordionFacets.Header>
<AccordionFacets.Content>
<AccordionFacets.ValueList className="py-3">
{f.value.map((v, index) => (
<FacetItem
{...{ index, facetValueId: v.id }}
key={v.id}
>
<AccordionFacets.ItemCheckbox>
<AccordionFacets.ItemCheckboxIndicator />
</AccordionFacets.ItemCheckbox>
<AccordionFacets.ItemLabel className="body-medium text-neutral-100 cursor-pointer pl-2">
{v.text} {v.count && `(${v.count})`}
</AccordionFacets.ItemLabel>
</FacetItem>
))}
</AccordionFacets.ValueList>
</AccordionFacets.Content>
</AccordionFacets.Facet>
))}
</SearchResultsAccordionFacets>
The first piece of code returns all the active facets and uses the action onRemoveFilter
which removes
the active facet.
{selectedFacetsFromApi?.length > 0 && (
<div className="flex flex-col gap-3">
<span className="eyebrow text-neutral-100">Filters</span>
{facets.map((selectedFacet) => (
<span
key={`${selectedFacet.facetId}${selectedFacet.facetLabel}${selectedFacet.valueLabel}`}
>
<div>
<span>{selectedFacet.valueLabel}</span>
<span
className="cursor-pointer"
onClick={() => onRemoveFilter(selectedFacet)}
>
X
</span>
</div>
</span>
))}
</div>
)}
The 2nd piece of code sets up the multiple accordion of facets and the available values you can select under them.
<SearchResultsAccordionFacets
defaultFacetTypesExpandedList={[]}
onFacetTypesExpandedListChange={() => null}
onFacetValueClick={onFacetClick}
>
{facets.map((f) => (
<AccordionFacets.Facet className="" facetId={f.name} key={f.name}>
<AccordionFacets.Header className="border-b border-neutral-10 items-center flex">
<AccordionFacets.Trigger>
{f.label}
</AccordionFacets.Trigger>
<Caret />
</AccordionFacets.Header>
<AccordionFacets.Content>
<AccordionFacets.ValueList className="py-3">
{f.value.map((v, index) => (
<FacetItem
{...{ index, facetValueId: v.id }}
key={v.id}
>
<AccordionFacets.ItemCheckbox>
<AccordionFacets.ItemCheckboxIndicator />
</AccordionFacets.ItemCheckbox>
<AccordionFacets.ItemLabel>
{v.text} {v.count && `(${v.count})`}
</AccordionFacets.ItemLabel>
</FacetItem>
))}
</AccordionFacets.ValueList>
</AccordionFacets.Content>
</AccordionFacets.Facet>
))}
</SearchResultsAccordionFacets>
Facets play an important role in helping narrow down search results for users. When we have setup our search data correctly and allow smooth setup with Sitecore Search you will help users a lot by allowing them to get the results they want in a short amount of time. Sitecore Search has a lot more features you can setup for your search page which can help put more power to the users and allowing them to navigate through the search even better. Stay tuned and check out other Sitecore Search articles we’ve written.