Implement facets
Implement facets
This is for:
DeveloperA search interface often includes facets that allow the user to narrow down a query to a specific subset of result items by selecting one or more dynamic filter values. This article provides guidelines for implementing facets on your own, assuming that you can’t use the Coveo JavaScript Search Framework or the Atomic or Headless libraries in your custom search integration with the Coveo Platform.
Note
As a reference, you may want to look at the source code of the |
Prior to September 2024, these guidelines instructed users to log facet-specific |
Standard facet actions
The following table lists some actions that you may want to make available in a facet implementation.
Every action belongs to a specific Coveo Usage Analytics (Coveo UA) event category, and each entry indicates the actionCause
, eventType
and eventValue
values that must be logged when the action is performed.
Each entry also includes a link to the corresponding implementation guidelines.
Facet action | UA event | actionCause |
eventType |
eventValue |
Implementation guidelines |
---|---|---|---|---|---|
Select a value |
Search |
|
N/A |
N/A |
|
Un-select a value |
Search |
|
N/A |
N/A |
|
Reset selected |
Search |
|
N/A |
N/A |
|
Request more values |
Custom |
|
|
|
|
Request less values |
Custom |
|
|
|
|
Search for a value |
N/A |
N/A |
N/A |
N/A |
Note
It’s important to use the correct
|
Request and render facets
Conceptually, a facet relies on an existing field (for example, @bookauthor
) to render a sorted list of facet values (for example, Ernest Hemingway
, Mark Twain
), each of which is accompanied by an estimated number of occurrences in the current query result set.
You can request the necessary data to render one or more facets through the facets
query parameter.
Each valid object you include in the facets
query parameter will populate a distinct object in the facets
array of that query response body.
Most of the time, when a query is sent from a faceted search interface, you’ll want to request and render or update facets. To do so, prepare a new query. In the request body:
-
In the query response body, retrieve the object in the
facets
array whosefield
value matches the field on which the facet relies. -
Use the
value
,numberOfResults
, andstate
attributes of each object in thevalues
array from the query response to render or update the facet.
Call the UA Write API to log the corresponding search event.
In the request body, include an object containing the following key-value pairs in the facetState
property for each non-idle facet value:
-
"facetType": <TYPE>
-
"field": <FIELDNAME>
-
"id": <ID>
-
"state": <STATE>
-
"value": <VALUE>
-
"displayValue": <DISPLAY_VALUE>
(optional) -
"facetPosition": <FACET_POSITION>
(optional) -
"title": <TITLE>
(optional) -
"valuePosition": <VALUE_POSITION>
(optional)
where:
-
<TYPE>
(string) is the facet data type (for example,specific
). -
<FIELDNAME>
(string) is the@
-prefixed name of the field that this facet is based on (for example,@booklength
). -
<ID>
(string) is the unique identifier of the facet in which one or more values were toggled. Typically, this is the@
-prefixed name of the field that this facet is based on (for example,@booklength
). -
<STATE>
(string) is the current state of the facet value (eitherauto_selected
orselected
). -
<VALUE>
(string) is the name of the toggled facet value (for example,Hardcover
). -
<DISPLAY_VALUE>
(string) is the display name of the facet value (for example,Hardcover
). -
<FACET_POSITION>
(integer) is the 1-based position of the facet (for example,1
). -
<TITLE>
(string) is the facet title (for example,Format
) -
<VALUE_POSITION>
(integer) is the 1-based position of the value in the facet (for example,2
).
Examples of requesting and rendering facets
-
A customer accesses the Books4Fun search interface. Once loaded, the search interface retrieves and renders the Book Format and Author facets with the following request:
POST https://platform.cloud.coveo.com/rest/search/v2 HTTP/1.1 Accept: application/json Content-Type: application/json Authorization: Bearer **********-****-****-****-************
Payload (excerpt)
{ ... "q": "Doctor Sleep", "cq": "NOT @source==\"Movies4Fun\"", ... "facets": [ { "facetId": "@bookformat", "field": "bookformat", "type": "specific", "currentValues": [], ... }, { "field": "bookauthor", "facetId": "@bookauthor", "type": "specific", "currentValues": [], ... } ], ... }
200 OK response body (excerpt)
{ ... "facets": [ { "facetId": "@bookformat", "field": "bookformat", "moreValuesAvailable": true, "values": [ { "value": "Hardcover", "state": "idle", "numberOfResults": 83 }, { "value": "Softcover", "state": "idle", "numberOfResults": 47 }, ... ], "indexScore": 0.435 }, { "facetId": "@bookauthor", "field": "bookauthor", "moreValuesAvailable": true, "values": [ { "value": "Charles Dickens", "state": "idle", "numberOfResults": 24 }, { "value": "Ernest Hemingway", "state": "idle", "numberOfResults": 26 }, { "value": "Mark Twain", "state": "idle", "numberOfResults": 23 }, ... ], "indexScore": 0.435 } ], ... }
-
Logging a search event for this action:
POST https://analytics.cloud.coveo.com/rest/ua/v15/analytics/searches?visitor=********-****-****-******** HTTP/1.1 Accept: application/json Content-Type: application/json Authorization: Bearer **********-****-****-****-************
Payload (excerpt)
[ { "actionCause": "interfaceLoad", ... "facetState": [] } ]
Toggle facet values
In a typical faceted search interface, the user can toggle (that is, select or un-select) any number of facet values to alter the facets
query parameter.
When the user interacts with a facet in this way, prepare a new query.
For each facet currently displayed in the search interface, include a corresponding object in the facets
query parameter:
-
Set
facetId
to the unique identifier of the facet. -
Set
field
to the name of the field the facet is based on. -
Set
type
tospecific
. -
If the facet is the one that was just interacted with, set
freezeCurrentValues
totrue
. -
If more than the originally specified
numberOfResults
are being requested for the facet, setisFieldExpanded
totrue
(see Request additional facet values). -
For each value currently displayed in the facet, include a corresponding object in the
currentValues
array:-
Set the
value
property to the value of the current facet. -
Set the
state
property toidle
if the facet isn’t selected, or set it toselected
otherwise. -
Set
preventAutoSelect
property tofalse
to ensure that Coveo ML automatically selects the facet value.
-
-
Call the Search API to execute this query.
When the Search API returns, call the UA Write API to log the corresponding search event. In the request body:
-
Set the
actionCause
property to:-
facetSelect
if the user has selected a single facet value. -
facetUnselect
if the user has un-selected a single facet value. -
facetClearAll
if the user has cleared all previously selected values.
-
-
For each non-idle facet, include an object containing the following key-value pairs in the
facetState
property:-
"facetType": <TYPE>
-
"field": <FIELDNAME>
-
"id": <ID>
-
"state": <STATE>
-
"value": <VALUE>
-
"displayValue": <DISPLAY_VALUE>
(optional) -
"facetPosition": <FACET_POSITION>
(optional) -
"title": <TITLE>
(optional) -
"valuePosition": <VALUE_POSITION>
(optional)
where:
-
<TYPE>
(string) is the facet data type (for example,specific
). -
<FIELDNAME>
(string) is the@
-prefixed name of the field that this facet is based on (for example,@booklength
). -
<ID>
(string) is the unique identifier of the facet in which one or more values were toggled. Typically, this is the@
-prefixed name of the field that this facet is based on (for example,@booklength
). -
<STATE>
(string) is the current state of the facet value (eitherauto_selected
orselected
). -
<VALUE>
(string) is the name of the toggled facet value (for example,Hardcover
). -
<DISPLAY_VALUE>
(string) is the display name of the facet value (for example,Hardcover
). -
<FACET_POSITION>
(integer) is the 1-based position of the facet (for example,1
). -
<TITLE>
(string) is the facet title (for example,Format
) -
<VALUE_POSITION>
(integer) is the 1-based position of the value in the facet (for example,2
).
-
-
Set other required or optional properties as needed, such as
language
,originLevel1
, ororiginLevel2
.
When the UA Write API returns successfully:
-
Update all of the facets in the search interface.
Interact with a facet indirectly
The Coveo JavaScript Search Framework includes components that allow users to interact with facets indirectly, such as the Breadcrumb
and FieldValue
components.
If you implement your own components, be sure to use the appropriate actionCause
value when logging a search event after the user has indirectly toggled one or more facet values:
Action | actionCause |
---|---|
Select or un-select a single facet value by interacting with a query result |
|
Un-select a single facet value by interacting with breadcrumbs |
|
Clear all selected facet values by interacting with breadcrumbs |
|
Examples of toggling facet values
-
A customer is browsing products on the Books4Fun site. They select the
Hardcover
value from the Book Format facet, which executes the following query:POST https://platform.cloud.coveo.com/rest/search/v2 HTTP/1.1 Accept: application/json Content-Type: application/json Authorization: Bearer **********-****-****-****-************
Payload (excerpt)
{ ... "q": "Doctor Sleep", "cq": "NOT @source==\"Movies4Fun\"", ... "facets": [ { "facetId": "@bookformat", "field": "bookformat", "type": "specific", "currentValues": [ { "value": "Hardcover", "state": "selected", "preventAutoSelect": false } { "value": "Softcover", "state": "idle", "preventAutoSelect": false }, ... ], "numberOfValues": 3, ... }, { "field": "bookauthor", "facetId": "@bookauthor", "type": "specific", "currentValues": [ { "value": "Ernest Hemingway", "state": "idle", "preventAutoSelect": false }, { "value": "Mark Twain", "state": "idle", "preventAutoSelect": false } ], "numberOfValues": 3, ... } ], ... "language": "en", "originLevel1": "Books4FunSearch", "originLevel2": "All", ... }
200 OK response body (excerpt)
{ ... "facets": [ { "facetId": "@bookformat", "field": "bookformat", "moreValuesAvailable": true, "values": [ { "value": "Hardcover", "state": "selected", "numberOfResults": 83 }, { "value": "Softcover", "state": "idle", "numberOfResults": 47 }, ... ], "indexScore": 0.435 }, { "facetId": "@bookauthor", "field": "bookauthor", "moreValuesAvailable": true, "values": [ { "value": "Charles Dickens", "state": "idle", "numberOfResults": 24 }, { "value": "Ernest Hemingway", "state": "idle", "numberOfResults": 26 }, { "value": "Mark Twain", "state": "idle", "numberOfResults": 23 }, ... ], "indexScore": 0.435 } ], ... }
-
Logging a search event for this action:
POST https://analytics.cloud.coveo.com/rest/ua/v15/analytics/searches?visitor=********-****-****-******** HTTP/1.1 Accept: application/json Content-Type: application/json Authorization: Bearer **********-****-****-****-************
Payload (excerpt)
[ { "actionCause": "facetSelect", "eventType": "dynamicFacet", ... "facetState": [ { "field": "@bookformat", "id": "@bookformat", "title": "Format", "facetType": "specific", "facetPosition": 1, "value": "Hardcover", "valuePosition": 2, "displayValue": "Hardcover", "state": "selected" } ] } ]
Request additional facet values
The numberOfValues
facet request parameter lets you specify the maximum number of facet values that the index may retrieve to populate the values
array of a given facet
object (the default value is 8
).
You may also want to allow the user to autonomously request to display more values in a facet. When the user interacts with a facet in this way, prepare a new query:
-
Set the
numberOfResults
query parameter to0
. -
In the
facets
query parameter, include thefacet
object for which the user has requested additional values. -
In the
facet
object operation, setfield
to the name of the field that the facet is based on (for example,@bookauthor
). -
For each value currently displayed in the facet, include a corresponding object in the
currentValues
array:-
Set the
value
property to the value of the current facet. -
Set the
state
property toidle
if the facet isn’t selected, or set it toselected
otherwise. -
Set
preventAutoSelect
property tofalse
to ensure that Coveo ML automatically selects the facet value.
-
-
Set
numberOfValues
to a higher value than the one that was specified the last time the facet was requested (for example,16
). -
Set
isFieldExpanded
totrue
. -
Set all of the other facet request parameters to the same values as the last time the facet was requested.
NoteAlthough this query isn’t meant to return actual result items, you should include the other search request parameters as usual. This way, it will represent the current state of the search interface, aside from
numberOfResults
being forcefully set to0
andfacets
not necessarily containing all of the operations required to update facets. Otherwise, the retrievedfacets
object may not contain accurate or consistent facet values or occurrence counts. -
Call the Search API to execute this query.
When the Search API returns, call the UA Write API to log the corresponding custom event. In the request body:
-
Set the
actionCause
property toshowMoreFacetResults
when showing more results orshowLessFacetResults
when showing less. -
Set the
eventType
property todynamicFacet
. -
Set the
eventValue
property toshowMoreFacetResults
when showing more results orshowLessFacetResults
when showing less. -
Set other required or optional properties as needed, such as
language
,originLevel1
, ororiginLevel2
.
When the UA Write API returns successfully, re-render the facet as appropriate.
Examples of requesting additional facet values
-
A customer is browsing products on the Books4Fun site. They can’t find their favourite author among the currently rendered values in the Author facet, so they request to display more values. This interaction executes the following request:
POST https://platform.cloud.coveo.com/rest/search/v2 HTTP/1.1 Accept: application/json Content-Type: application/json Authorization: Bearer **********-****-****-****-************
Payload (excerpt)
{ ... "q": "Doctor Sleep", "cq": "NOT @source==\"Movies4Fun\"", "numberOfResults": 0, ... "facets": [ { "facetId": "@bookformat", "field": "bookformat", "type": "specific", "currentValues": [ { "value": "Hardcover", "state": "selected", "preventAutoSelect": false } { "value": "Softcover", "state": "idle", "preventAutoSelect": false }, ... ], "numberOfValues": 3, ... }, { "field": "bookauthor", "facetId": "@bookauthor", "type": "specific", "currentValues": [ { "value": "Ernest Hemingway", "state": "idle", "preventAutoSelect": false }, { "value": "Mark Twain", "state": "idle", "preventAutoSelect": false } ], "numberOfValues": 6, "isFieldExpanded": true, ... } ], ... "language": "en", "originLevel1": "Books4FunSearch", "originLevel2": "All", ... }
200 OK response body (excerpt)
{ ... "facets": [ { "facetId": "@bookformat", "field": "bookformat", "moreValuesAvailable": true, "values": [ { "value": "Hardcover", "state": "selected", "numberOfResults": 83 }, { "value": "Softcover", "state": "idle", "numberOfResults": 47 }, ... ], "indexScore": 0.435 }, { "facetId": "@bookauthor", "field": "bookauthor", "moreValuesAvailable": true, "values": [ { "value": "Charles Dickens", "state": "idle", "numberOfResults": 24 }, { "value": "Ernest Hemingway", "state": "idle", "numberOfResults": 26 }, { "value": "Mark Twain", "state": "idle", "numberOfResults": 23 }, { "value": "Stephen King", "state": "idle", "numberOfResults": 14 }, ... ], "indexScore": 0.435 } ], ... }
-
Logging a custom event for this action:
POST https://analytics.cloud.coveo.com/rest/ua/v15/analytics/custom?visitor=********-****-****-******** HTTP/1.1 Accept: application/json Content-Type: application/json Authorization: Bearer **********-****-****-****-************
Payload (excerpt)
[ { "actionCause": "showMoreFacetResults", "eventType": "dynamicFacet", "eventValue": "showMoreFacetResults", ... "facetState": [ { "field": "@bookformat", "id": "@bookformat", "title": "Format", "facetType": "specific", "facetPosition": 1, "value": "Hardcover", "valuePosition": 2, "displayValue": "Hardcover", "state": "selected" } ] } ]
Perform facet search
Note
The following guidelines suggest a facet search implementation which is similar to that of the Coveo JavaScript Search Framework (that is, wildcard pattern matching as the user types). You may opt to use an entirely different approach for your own implementation. |
You may want to allow the user to look for specific facet values by typing into a dedicated search input within a facet. When the user interacts with a facet in this way, on each valid keystroke:
-
Retrieve the current value from the facet search input (for example,
a
). -
Prepare a new facet search request. In the request body:
-
Set the
field
property to the name of the field that the facet being searched is based on (for example,bookauthor
). -
Set the
query
property to the-prefixed and
-suffixed value that was retrieved in step 1 (for example,
a
becomesa
). -
Set the
numberOfValues
property to the maximum number of matching values to retrieve through facet search (for example,4
). The default value is10
. -
Set other optional properties as needed, such as
ignoreValues
orcaptions
.
-
-
Set all of the other facet request parameters to the same values as the last time the facet was requested.
NoteAlthough this query isn’t meant to return actual result items, you should include the other search request parameters as usual. This way, it will represent the current state of the search interface, aside from
numberOfResults
being forcefully set to0
andfacets
not necessarily containing all of the operations required to update facets. Otherwise, the retrievedfacets
object may not contain accurate or consistent facet values or occurrence counts. -
Call the Search API to execute this query.
-
When the Search API returns, render the retrieved facet values using the
displayValue
andcount
values of each object in thevalues
array in the response body.
Example of performing facet search
A customer is browsing products on the Books4Fun site. They can’t find their favourite author among the currently rendered values in the Author facet, so they begin typing the author’s name into the facet search box. This interaction executes the following request:
POST https://myorganizationid9sd8df7s.org.coveo.com/rest/search/v2/facet HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer **********-****-****-****-************
Payload (excerpt)
{
"field": "bookauthor",
"numberOfValues": 4,
"query": "*W*"
}
200 OK response body (excerpt)
{
"values": [
{
"displayValue": "William Shakespeare",
"rawValue": "William Shakespeare",
"count": 10
},
{
"displayValue": "William Faulkner",
"rawValue": "William Faulkner",
"count": 5
},
...
],
"moreValuesAvailable": false
}