Customizing Coveo Atomic With Headless

July 22, 2023

By Ryan Allan

Customizing Coveo Atomic with Headless

Coveo Atomic is great. It lets you make an entire search page extremely quickly, with good out-of-the box-styling, accessibility, and well done UI. You can build out your results to look however you like, add filters in moments, and so on.

That’s great, no questions asked. There might be things you want to customize or special use cases that you need, though. For those, you can reach down into the underlying technology, Coveo Headless. Coveo atomic is a wonderful presentation layer that’s built on top of Headless, and every little widget and setting is accessible if you need or want to change it.

The Coveo Headless Setup

The basic method is fairly simple. You find the headless component you want, and import it into the top of your Atomic javascript. Like so:

import { buildFacet } from 'https://static.cloud.coveo.com/atomic/v2/headless/headless.esm.js';

In this case, we’re using a facet as the example. The most important point here is that “buildFacet” doesn’t build the facet again. You can think of it as locating the facets you’ve already got, or building a controller to access them. This applies to all of the various components.

You can see the list of atomic components here and the corresponding headless components here.

How to Use the Coveo Headless Component

After we’ve imported the component we want, then we build the controller to use it.

First, we need the headless “engine” to bind the controller too.

const engine = searchInterface.engine;

const facetController = buildFacet(engine, { options: 
  { facetId: "locationFacet", field: "location" }
});

Then we use the engine, and an options object to instantiate the controller. The facet controller needs to know which ID and which field to bind to. We need the options object or the controller will look for all the potential arguments instead of using the default values.

Our facet looks like this:

<atomic-facet
    facet-id="locationFacet" 
    field="location"
    label="Location"
    sort-criteria="occurrences"
    with-search="false"
    >
</atomic-facet>

For simplicity’s sake, we’re going to say our search page is has a special section where the logo of each location is shown. When the user changes the facet value, a new location shows up. The various null checks have been left out for brevity.

facetController.subscribe(() => { 
  const state = facetController.state;
  const val = state?.values?[0]; //for example, assume the values are sorted with the selected one first

  if(val.value && val.state==='selected'){
    ShowLocation(val.value);
  } else {
    //the facet is blank
    ShowDefaultLocation();
  }
});

The ShowLocation and ShowDefaultLocation methods are up to you. A potential improvement is searching the values for the selected value, too.

That’s the End!

That’s all you need. Any of the components can be used this way, like buildRedirectController or even buildFacetManager if you want to add new facets on the fly.



Ryan

Ryan Allan

Senior Developer

Ryan is a seasoned Senior Developer at Fishtank and is Sitecore Developer Certified. In a nutshell, he describes his role as "building extremely fancy websites". Ryan has a degree in Mechanical Engineering and previously worked on power plants and compressors, and now builds websites for the same company as a client! Outside of work, his interests are science + physics and spending time with his kids.