Provide search box suggestions

This is for:

Developer

The JavaScript Search Framework supports different kinds of search box suggestions:

Coveo Machine Learning (Coveo ML) Query Suggestions (QS) models can recommend contextually relevant queries based on previously recorded usage analytics data. To leverage Coveo ML QS in a search interface:

  1. Use the Searchbox component to initialize an Omnibox.

    Unless you’re configuring a standalone search box, you should also initialize an Analytics component.

EXAMPLE
<div id="search" class="CoveoSearchInterface">
  <div class="CoveoAnalytics" data-search-hub="CommunitySearch"></div>
  <div class="coveo-search-section">
    <div class="CoveoSearchbox"></div>
  </div>
</div>
  1. Create a QS model.

  2. Associate the QS model with the query pipeline which processes search requests originating from the search interface.

Note

If the search box is still providing no query suggestions, ensure that enough usage analytics data is available to feed your QS model.

Requesting query suggestions only when the search box is non-empty

By default, trending Coveo ML query suggestions are requested and rendered whenever focus is on the search box input.

To change this behavior, set the querySuggestCharacterThreshold option of the Omnibox component to a value greater than 0.

EXAMPLE

The following configuration ensures that query suggestions only get rendered from the moment the end user starts entering a query in the search box.

<div class="CoveoSearchbox" data-query-suggest-character-threshold="1"></div>

Rendering query suggestion result previews

In some search interfaces, particularly in the context of commerce, you may want to render previews of the most relevant results when focus is on a query suggestion. To do so, your search interface must initialize a QuerySuggestPreview component.

Note

The QuerySuggestPreview component isn’t compatible with field value suggestions.

EXAMPLE

With the following configuration, when focus is on a query suggestion for 200 milliseconds[1], the QuerySuggestPreview component requests the top three[2] results matching the focused query, and renders those results using a simple default template[3].

<!-- ... -->
<div class="CoveoQuerySuggestPreview"></div>
<div class="CoveoSearchbox"></div>
<!-- ... -->
</div>
QuerySuggestPreview demo | Coveo JavaScript Search Framework

Using custom Query Suggest Preview result templates

Two options are available to customize the way the QuerySuggestPreview component visually renders results:

  • Option 1: Use the resultTemplate option to specify a previously registered template to apply to all results.

EXAMPLE
<div class="CoveoQuerySuggestPreview"
  data-result-template-id="qsp-template"></div>
  <!-- ... -->
<script id="qsp-template" class="result-template" type="text/html">
  <!-- ... -->
</script>
  • Option 2: Embed a set of conditional templates inside the element bound to the QuerySuggestPreview component instance. This is essentially the same approach you would use to specify custom result templates for a ResultList component.

    By using this approach, for each result to render, the first template whose condition is satisfied by the result will apply. Therefore, the last embedded template should typically have no condition, and be considered the default template.

EXAMPLE
<div class="CoveoQuerySuggestPreview">
  <script id="qsp-template-products" class="result-template" type="text/html"
          data-field-documenttype="Product">
    <!-- ... -->
  </script>
  <script id="qsp-template-services" class="result-template" type="text/html"
          data-field-documenttype="Service">
    <!-- ... -->
  </script>
  <script id="qsp-template-default" class="result-template" type="text/html">
    <!-- ... -->
  </script>
</div>

For more information on result templates, see JavaScript Search Framework result templates.

Providing facet value suggestions

You can use the FacetValueSuggestions component to provide end users with scoped query suggestions based on the values of a specific facet-enabled field.

Basic usage

The following code sample provides a minimal working example of a FacetValueSuggestions component:

<!DOCTYPE html>
<html>
<head>
  <!-- The component requires JS Search Framework v2.4094.8 or above -->
  <link rel="stylesheet" href="https://static.cloud.coveo.com/searchui/v2.4094/css/CoveoFullSearch.css"/>
  <script class="coveo-script" src="https://static.cloud.coveo.com/searchui/v2.4094/js/CoveoJsSearch.Lazy.min.js"></script>
  <script>
    document.addEventListener("DOMContentLoaded", () => {
      Coveo.SearchEndpoint.configureSampleEndpointV2();
      Coveo.init(document.getElementById("search"));
    });
  </script>
</head>
<body id="search" class="CoveoSearchInterface">
  <div class="coveo-search-section">
    <!-- See note 1 below -->
    <div class="CoveoSearchbox">
      <!-- See note 2 below -->
      <div class="CoveoFacetValueSuggestions" data-field="@author"></div>
      <!-- See note 3 below -->
      <!-- <div class="CoveoFacetValueSuggestions"
                data-field="@author"
                data-use-query-suggestions="false"></div> -->
    </div>
  </div>
  <div class="coveo-main-section">
    <!-- See note 4 below -->
    <div class="coveo-facet-column">
      <div class="CoveoFacet" data-field="@author" data-title="Author"></div>
    </div>
    <div class="coveo-results-column">
      <div class="CoveoResultList"></div>
    </div>
  </div>
  <!-- See note 5 below -->
  <!-- <div class="CoveoHiddenQuery"></div> -->
</body>
</html>
Notes
  1. The FacetValueSuggestions component requires an Omnibox to work. By default, the Searchbox initializes an Omnibox.

  2. Minimally, you must set the field option of a FacetValueSuggestions component to the @-prefixed name of a field whose Facet option is enabled (for example, data-field="@author"). If the target field has high cardinality (that is, if it has many possible values), you can enable its Use cache for nested queries option to improve performance. You can initialize many FacetValueSuggestions components in the same search interface, as long as each instance references its own unique field.

  3. The useQuerySuggestions option of the FacetValueSuggestions component is set to true by default and sends an additional POST HTTP call to https://platform.cloud.coveo.com/rest/search/v2/querySuggest (see Get query suggestions). The FacetValueSuggestions component normally requires that the enableQuerySuggestAddon option be set to true on the Omnibox, which is the case by default. This implies that a Coveo ML QS model must be available in the target query pipeline. If these conditions aren’t satisfied, you must set the useQuerySuggestions option of each FacetValueSuggestions component to false, or the components won’t work.

  4. While not mandatory, we recommend that you include a corresponding Facet component for each FacetValueSuggestions component. This will allow end users to intuitively interact with the filters that apply when selecting a scoped query suggestion.

  5. If you can’t or don’t want to use facets in your search interface, include a HiddenQuery component instead. Otherwise, selecting a scoped query suggestion provided by a FacetValueSuggestions component won’t have the desired effect, as no additional filter will be applied.

Providing scoped query suggestions based on a multi-value field

You can use the isCategoryField and categoryFieldDelimitingCharacter options of a FacetValueSuggestions component to provide scoped query suggestions based on a field whose Multi-Value Facet option is enabled.

When you do so, we recommend that you include a corresponding CategoryFacet in your search interface.

EXAMPLE

In your Coveo organization, you’ve created a source called Living Things. In that source, each item describes a specific plant or animal. The @simpletaxonomy multi-value field gets populated by metadata representing the hierarchical categories to which each Living Things item belongs.

For example, the field value is:

  • Animals; Animals > Mammals; for items describing dogs, cats or horses.

  • Animals; Animals > Birds; for items describing parrots, eagles or crows.

  • Plants; Plants > Trees; for items describing maples, oaks or firs.

In your search interface, you configure a FacetValueSuggestions component (and a CategoryFacet) based on the @simpletaxonomy field:

<div id="search" class="CoveoSearchInterface">
  <div class="coveo-search-section">
    <div class="CoveoSearchbox">
      <div class="CoveoFacetValueSuggestions"
           data-field="@simpletaxonomy"
           data-is-category-field="true"
           data-category-field-delimiting-character=" > "></div>
      </div>
  </div>
  <div class="coveo-main-section">
    <div class="coveo-facet-column">
      <div class="CoveoCategoryFacet"
           data-field="@simpletaxonomy"
           data-title="Taxonomy"></div>
    </div>
    <div class="coveo-results-column">
      <div class="CoveoResultList"></div>
    </div>
  </div>
</div>

Your Omnibox can now provide scoped query suggestions similar to what’s shown in the following animation:

Nice friendly parrot example

Using custom templates for facet value suggestions

You can use the templateHelper option of the FacetValueSuggestions component to specify a custom template to apply when rendering scoped query suggestions in the Omnibox.

Note

You can’t set this option directly in the markup configuration of a FacetValueSuggestions component; you must rather set it in the init (or options) top-level function call (see Configuring components).

When specified, the templateHelper option must be set to a function that returns a string or template literal, and receives the following arguments:

  1. A reference to the current IFacetValueSuggestionRow object.

  2. A reference to the Omnibox in which to render the scoped query suggestions.

Typically, the function should leverage some attributes of the first argument (for example, keyword, value, etc.) to generate a template literal (which may contain HTML).

EXAMPLE

Consider the following markup:

<div id="search" class="CoveoSearchInterface">
  <div class="CoveoHiddenQuery"></div>
  <div class="coveo-search-section">
    <div class="CoveoSearchbox">
      <div id="authorFacetValueSuggestions" class="CoveoFacetValueSuggestions"
           data-field="@author"
           data-use-query-suggestions="false"></div>
      <div id="filetypeFacetValueSuggestions" class="CoveoFacetValueSuggestions"
           data-field="@filetype"
           data-use-query-suggestions="false"></div>
    </div>
  </div>
</div>

You could specify a generic custom template function to execute when rendering suggestions for each FacetValueSuggestions component:

Coveo.init(document.getElementById("search"), {
  FacetValueSuggestions: {
    templateHelper: (row, omnibox) => {
      return `<strong>${row.keyword}</strong> where <strong>${row.field}=="${row.value}"</strong> (~${row.numberOfResults} results)`;
    }
  }
});
FacetValueSuggestions custom template example 1 | Coveo JavaScript Search Framework

You could also specify a specific custom template function for each component instance by targeting its HTML id attribute in the init (or options) top-level function call:

Coveo.init(document.getElementById("search"), {
  authorFacetValueSuggestions: {
    templateHelper: (row, omnibox) => {
      return `<strong>${row.keyword}</strong> in items authored by <em>${row.value}</em>`;
    }
  },
  filetypeFacetValueSuggestions: {
    templateHelper: (row, omnibox) => {
      const normalizedRowValues = {
        "gmailmessage": "Gmail message",
        "lithiummessage": "Khoros Community message",
        "pdf": "PDF"
      }
      const normalizedRowValue = normalizedRowValues[row.value] || row.value;
      return `<strong>${row.keyword}</strong> in ${normalizedRowValue}s`;
    }
  }
});
FacetValueSuggestions custom template example 2 | Coveo JavaScript Search Framework

Providing field suggestions

Tip
Leading practice

Consider providing Coveo ML query suggestions rather than field suggestions, as the former yields better performance and relevance.

The FieldSuggestions component can provide Omnibox suggestions based on field values. To enable basic field suggestions in a search interface:

  1. Ensure that the search interface initializes an Omnibox component.

  2. Initialize a FieldSuggestions component in your search page, and set its field option to the @-prefixed name of the field on which you want to base the suggestions.

EXAMPLE
<div id="search" class="CoveoSearchInterface">
  <div class="coveo-search-section">
    <div class="CoveoSearchbox"></div>
    <div class="CoveoFieldSuggestions" data-field="@author"></div>
  </div>
</div>
Notes
  • You can add several FieldSuggestions components in a search interface to provide query completion suggestions based on different fields.

  • Ensure that the Facet option is enabled on each field you use to provide field suggestions (see Add or edit a field).

Field suggestions example