Insights

How to Create Facets for Your Sitecore Search Component

Learn how to create facets and configuring them for your Sitecore Search results

What are Facets?

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.

Setting up Facets in the Customer Engagement Console (CEC)

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.

Screenshot highlighting the steps to access Domain Settings in an admin panel.

Screenshot displaying a list of attributes in a content management system.

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.

Screenshot showing attribute settings such as Display Name, Attribute Name, Placement, and Data Type.

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

  1. Display Name - the text that will be displayed on your widget on the frontend.
  2. Attribute Name - the value you will have to check when checking facets.
  3. Placement - you will have to set this to Standard
  4. Data Type - has a list of possible types like string, array of strings, float, boolean and etc.

If you decide that it’s an attribute that should appear as a facet then open Use For Features and check the Facets checkbox.

Screenshot of an interface with checkboxes for selecting Facets and other features.

Click Save and move the the Feature Configuration tab and open the Facets accordion.

Screenshot of facet configuration options in a digital content settings interface.

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.

Screenshot showing attribute and label modifications in a content management system.

Integrating Our Facet Into Our Widget

Let’s now setup the Facets in our widgets by navigating to Widgets > Variant.

Screenshot of a user interface for customizing search widget options.

Screenshot depicting the configuration of search result widget settings.

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.

Screenshot of a digital interface for adjusting search settings and viewing attribute coverage.

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.

Screenshot showing the settings interface for managing tags.

After everything, don’t forget to save and publish all the changes we’ve done.

Integrating Facets in Our Frontend Widget

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.



Meet John Flores

Front-End Developer

🪴🐩📷

John is a Front-End Developer who is passionate about design and development. Outside of work, John has wide range of hobbies, from his plant collection, being a dog daddy, and a foodie.

Connect with John