Facets | Yext Hitchhikers Platform

The <Facets /> component gives the end user the ability to further refine search results. Depending on the results that are returned, the user will see facets with a series of options they can select. If no results are returned in the query for a given facet option, that option will not appear.

Users can toggle a facet option checkbox on to further refine the search results. Within a single facet, if multiple options are selected (let’s call them option A and option B) the results will display any entities that contain either option A OR option B.

For more information about what facets are, take a look at the Facets and Filters reference doc.

Here’s what what the <Facets /> component looks like in the UI:

Facet example

Basic Example

To make a field eligible as a facet, we need to make sure it’s set as a facet in the searchableFields attribute in the search configuration. This exposes the field in the API response and allows facets to be applied on that field. For example:

{
  "verticals": {
    "products": {
      "entityTypes": ["product"],
      "searchableFields": {
        "c_color": {
          "facet": true
        },
        "c_size": {
          "facet": true
        }
      }
    }
  }
}

Once that’s done, you can use the <Facets /> component.

<Facets /> are typically placed next to <VerticalResults />. You’ll notice that some additional styling was applied to align the facets next to the results:

import { useSearchActions } from "@yext/search-headless-react";
import {
  SearchBar,
  StandardCard,
  Facets,
  VerticalResults,
} from "@yext/search-ui-react";
import { useEffect } from "react";

function App() {
  const searchActions = useSearchActions();

  useEffect(() => {
    searchActions.setVertical("products");
  }, []);

  return (
    <div className="flex justify-center px-4 py-6">
      <div className="w-full max-w-5xl">
        <SearchBar />
        <div className="flex">
          <Facets 
            customCssClasses={{ facetsContainer: "mr-10" }} 
          />
          <VerticalResults
            CardComponent={StandardCard}
          />
        </div>
      </div>
    </div>
  );
}

export default App;

Overriding Specific Facets

The Facets component will render all configured facets by default. However you might want to edit certain facets and not others. Take the following example:

<Facets>
  <StandardFacet fieldId="c_size" label="Dimensions"/>
<Facets />

This renders all of the configured facets, but changes the label of the size facet to Dimensions.

We distinguish between three different kinds of facets in our platform: Standard Facets , Numerical Facets , and Hierarchical Facets . Each of these types is represented by its own component. For any facet that we want to override, we have to determine which component type to use.

Restricting Facets to Render

We can also restrict which facets render on the frontend. If we only care about a subset of facets for a specific vertical, we can update the above code to only render the relevant facets. We do that by adding the onlyRenderChildren prop. Take the following example:

<Facets onlyRenderChildren={true}>
  <StandardFacet fieldId="c_size" label="Dimensions"/>
<Facets />

The above code will only render the size facet, and no others.

Changing Default Behavior

By default, the searchOnChange prop is true , which means when a user clicks on a facet option, a search is run with that added filter applied to return new results. When searchOnChange is false, we need a way to conduct that search when the user is ready to apply the selected facets.

We can do this by adding an <ApplyFiltersButton /> component:

import {
  useSearchActions,
  useSearchState,
} from "@yext/search-headless-react";
import {
  SearchBar,
  StandardCard,
  Facets,
  VerticalResults,
  ApplyFiltersButton,
} from "@yext/search-ui-react";
import { useEffect } from "react";

function App() {
  const searchActions = useSearchActions();

  const facetOptionCount =
    useSearchState((state) => state.filters.facets?.flatMap((f) => f.options))
      ?.length ?? 0;

  useEffect(() => {
    searchActions.setVertical("locations");
  }, []);

  return (
    <div className="flex justify-center px-4 py-6">
      <div className="w-full max-w-5xl">
        <SearchBar />
        <div className="flex">
          <div>
            <Facets
              customCssClasses={{ facetsContainer: "mr-10" }}
              searchOnChange={false}
            />
            {facetOptionCount > 0 && (
              <ApplyFiltersButton customCssClasses={{ button: "mt-2" }} />
            )}
          </div>
          <VerticalResults
            customCssClasses={{ results: "flex-grow" }}
            CardComponent={StandardCard}
            allowPagination={false}
          />
        </div>
      </div>
    </div>
  );
}

export default App;

Resulting in an experience that looks like so:

customize ApplyFiltersButton component

Customizations

Like the rest of our components, you can customize the elements of the Facets using the customCssClasses prop.

Feedback