Implement a result list

This is for:

Developer

A search interface almost always displays a list of results which the end user can use to interact with query result items. This article provides guidelines for properly implementing a result list on your own, assuming that you can’t use the Coveo Atomic or Headless libraries in your custom search integration with Coveo.

As a reference, you may want to look at the source code of the ResultList component to see how it’s implemented in the Coveo JavaScript Search Framework.

Standard result list actions

The following table lists some of the most frequent actions you may want to make available in a result list implementation.

Each entry indicates the specific Coveo Usage Analytics (Coveo UA) event category, actionCause/eventValue, eventType, and customData that must be logged when the action is performed, as well as a link to the corresponding implementation guidelines (see Log Usage analytics events).

Result list action Usage analytics events actionCause eventType eventValue customData Implementation guidelines
Clicking a result Click documentOpen N/A N/A author, contentIdKey, contentIdValue, documentTitle, documentURL Opening Query Results
Clicking a recommendation Click recommendationOpen N/A N/A author, contentIdKey, contentIdValue, documentTitle, documentURL Opening Query Results
Previewing a result Click documentQuickview N/A N/A author, contentIdKey, contentIdValue, documentTitle, documentURL Previewing a Result
Selecting a page of results Custom N/A getMoreResults pagerNumber pagerNumber Paging Query Results
Selecting the next page of results Custom N/A getMoreResults pagerNumber pagerNext Paging Query Results
Selecting the previous page of results Custom N/A getMoreResults pagerNumber pagerPrevious Paging Query Results
Scrolling to get more results in infinite scroll mode Custom N/A getMoreResults pagerNumber pagerScrolling Paging Query Results
Resizing the number of results per page Custom N/A getMoreResults pagerResize currentResultsPerPage Paging Query Results
Sorting results Search resultsSort N/A N/A resultsSortBy Sorting Query Results
Changing the result layout Custom N/A resultsLayout changeResultsLayout resultsLayoutChangeTo Switching Result List Layouts
Exporting to Excel Custom N/A misc exportToExcel N/A Exporting Results
Toggling a Facet from a result list item Search documentField N/A N/A facetField, facetId, facetValue Toggling a Facet Value from a Result List Item

It’s important to use the proper eventType, actionCause/eventValue, and customData when logging a usage analytics event for a specific type of action in a search interface. Otherwise:

Rendering query results

You typically want to update the result list whenever a search request to the Search API returns.

The results array of a query response contains the list of query result items which you typically rely on to render and/or update the result list. By default, the results array is sorted by relevance (that is, by descending index ranking score value), but you can modify this behavior using the sortCriteria search request parameter (see Sorting Query Results).

In a search interface with many similar results, you may want use the enableDuplicateFiltering search request parameter. Result items are considered duplicates when the proportion of their data that’s identical exceeds a certain threshold. When enableDuplicateFiltering is set to true and some items are duplicates, only one of those items will appear in the results array of the query response.

The following properties are especially useful when rendering a query result item:

  • Descriptions:

    • title: The title of the item. Use this to render the item in the result list. This property should be saved, as its value will be required when logging a usage analytics Click event for the item (see Opening Query Results).

    • excerpt: Text segments from the item, generated using query keywords. You can set the maximum length (in number of characters, 200 by default) using the excerptLength parameter in the search request.

    • firstSentences: The first sentences of the item. This property won’t be populated unless the retrieveFirstSentences parameter is set to true in the search request. You can set the maximum length (in number of characters, 200 by default) using the excerptLength parameter in the search request.

    • summary: A description of the item, generated independently of query keywords. You can set the maximum length (in number of characters, 0 by default) using the summaryLength parameter in the search request.

    • printableUri: A human-readable version of the item URI to be displayed.

  • Highlights:

    All of the properties listed above have a <propertyName>Highlights counterpart containing an array of {length, offset} items, each of which indicates a keyword to highlight (for example, bold or italicize) when rendering the corresponding value.

    • titleHighlights

    • excerptHighlights

    • firstSentencesHighlights

    • summaryHighlights

    • printableUriHighlights

  • Link:

    • clickUri: The hyperlinkable item URI. Use this to define the target when rendering a link to the corresponding item (for example, as the value of the href attribute in an HTML anchor element).
  • Fields:

    The raw property of a query result item contains key-value pairs, each corresponding to the name of a field along with its value for that specific item. The following fields are particularly important, and they should be included (if available) as customData when logging usage analytics Click events for that item (see Opening Query Results):

    • author: The author of the item.

    • permanentid: The unique identifier of the item in the index.

    • By default, values in multi-value fields are separated by semicolon characters (for example, an item corresponding to the coauthored book The Talisman may have the following key-value pair: "authors":"Stephen King;Peter Straub").

    • When performing queries, you can take advantage of the fieldsToInclude/fieldsToExclude search request parameters to only request the fields which are required by your search interface. By default, all fields are requested, which is typically non-optimal.

  • Miscellaneous:

    • uri: The URI of the item. Although you won’t typically use this to render the item in the result list, this property should be saved, as its value will be required when logging a usage analytics Click event for the item (see Opening Query Results).

    • isRecommendation: Whether the query result item was recommended by a Coveo ML Automatic Relevance Tuning (ART) model. You may want to use this property to render Coveo ML recommendations in a distinctive fashion in the result list.

For legacy reasons, several of the above properties are duplicated in PascalCase (for example, each item in the results array has both the clickUri and ClickUri properties). You should always use the camelCase version (for example, clickUri).

Executing a search query

POST https://myorganizationid9sd8df7s.org.coveo.com/rest/search/v2 HTTP/1.1
 
Accept: application/json
Content-Type: application/json
Authorization: Bearer **********-****-****-****-************

Payload (excerpt)

{
  ...
  "excerptlength": 200,
  "q": "karamazov",
  "retrieveFirstSentences": true,
  ...
}

200 OK response body (excerpt)

{
  ...
  "results": [
    {
      ...
      "clickUri": "https://example.com/books/the-brothers-karamazov",
      "excerpt": "The Brothers Karamazov is a passionate philosophical novel set in 19th-century Russia ... one of the supreme achievements in world literature.",
      "excerptHighlights": [
        {
          "length": 9,
          "offset": 13
        }
      ],
      "firstSentences": "The Brothers Karamazov is a passionate philosophical novel set in 19th-century Russia, that enters deeply into the ethical debates of God, free will, and morality. It's a spiritual drama of moral ...",
      "firstSentencesHighlights": [
        {
          "length": 9,
          "offset": 13
        }
      ],
      "isRecommendation": true,
      "printableUri": "https://example.com/books/the-brothers-karamazov",
      "printableUriHighlights": [
        {
          "length": 9,
          "offset": 39
        }
      ],
      "raw": {
        ...
        "author": "Fyodor Dostoyevsky",
        "permanentid": "648a63d6a19545297692b4ae41a7d5e947c711be5f3c23dff69af3106960",
        ...
      },
      "summary": null,
      "summaryHighlights": [],
      "title": "The Brothers Karamazov",
      "titleHighlights": [
        {
          "length": 9,
          "offset": 13
        }
      ],
      "uri": "https://example.com/books/the-brothers-karamazov",
      ...
    },
    ...next results...
  ],
  ...
}

Opening query results

When the end user opens a query result in a result list (for example, by clicking a link targeting the corresponding item):

  1. Call the Usage Analytics Write API to log the corresponding Click event. In the request body:

    • Set the actionCause property to:

      • documentOpen if the result item was opened in a standard search interface.

      • recommendationOpen if the result item was opened in a Content Recommendations (CR) search interface.

    • Include the following key-value pairs (if available) in the customData property:

      • "author": <author>

      • "documentTitle": <documentTitle>

      • "documentUrl": <documentUrl>

      • "contentIdKey": <contentIdKey>

      • "contentIdValue": <contentIdValue>

      where:

      • <author> (string) is the raw.author value of the clicked query result item (this can be an empty string).

      • <documentTitle> (string) is the title value of the clicked query result item.

      • <documentUrl> (string) is the uri value of the clicked query result item.

      • <contentIdKey> (string) is the name of a field which uniquely and permanently identifies the clicked item.

      Use "permanentid" (see About the permanentid field). If this is unavailable (for example, if the clicked item resides in a Push source that doesn’t populate the permanentid field with metadata), use "urihash".

      • <contentIdValue> (string) is the value of the field whose name was specified in <contentIdKey>.

      Use the raw.permanentid value of the clicked query result item. If this is unavailable, use the raw.urihash value of the clicked query result.

    • Set other required/optional properties as appropriate (language, originLevel1, originLevel2, etc.).

  2. When the Usage Analytics Write API returns, redirect the client as appropriate (using the clickableUri value of the clicked query result item).

  1. Logging a documentOpen Click event

    POST https://myorganizationid9sd8df7s.analytics.org.coveo.com/rest/ua/v15/analytics/click?visitor=28s6g49d-f81s-1435-2r5x153dle72 HTTP/1.1
        
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "anonymous": false,
      "actionCause": "documentOpen",
      "customData":{
        "contentIdKey": "permanentid",
        "contentIdValue": "648a63d6a19545297692b4ae41a7d5e947c711be5f3c23dff69af3106960",
        "author": "Fyodor Dostoyevsky",
        "documentTitle": "The Brothers Karamazov",
        "documentURL": "https://example.com/books/the-brothers-karamazov"
      },
      "documentPosition": 1,
      "documentTitle": "The Brothers Karamazov",
      "documentUriHash": "xyhvGJJGRDM3OiG5",
      "documentUrl": "https://example.com/books/the-brothers-karamazov",
      "language": "en",
      "originLevel1": "BookstoreSearch",
      "originLevel2": "All",
      "searchQueryUid": "7bfc652a-9dea-4811-b3f9-6d24345c37ce",
      "sourceName": "example.com",
      ...
    }
    
  2. Logging a recommendationOpen Click event

    POST https://myorganizationid9sd8df7s.analytics.org.coveo.com/rest/ua/v15/analytics/click?visitor=28s6g49d-f81s-1435-2r5x153dle72 HTTP/1.1
     
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
     ...
      "anonymous": false,
      "actionCause": "recommendationOpen",
      "customData":{
        "contentIdKey": "permanentid",
        "contentIdValue": "8asd8f7a9sfd8asfdasf78afsdh8h87h878g37g872gf8g83gf78g2f387g2",
        "author": "Ivan Turgenev",
        "documentTitle": "Fathers and Sons",
        "documentURL": "https://example.com/books/fathers-and-sons"
      },
      "documentPosition": 2,
      "documentTitle": "Fathers and Sons",
      "documentUriHash": "D7nqaBC4ctHfeDñi",
      "documentUrl": "https://example.com/books/fathers-and-sons",
      "language": "en",
      "originLevel1": "BookstoreRecommendation",
      "originLevel2": "",
      "searchQueryUid": "b2d60d3f-b2cf-4018-bfd2-8094d24fa8e9",
      "sourceName": "example.com",
      ...
    }
    

Previewing a result

  • As a reference, you may want to look at the source code of the Quickview component to see how it’s implemented in the Coveo JavaScript Search Framework.

  • Unlike most other Search API requests in this guide, preview requests are made using the GET endpoint rather than POST.

When the end user previews a query result item (for example, by clicking a Preview button):

  1. Prepare a GET request to https://<orgId>.org.coveo.com/rest/search/v2/html?uniqueId=<uniqueId>, where <orgId> is the unique identifier of your organization. In the query string, set <uniqueId> to the raw.uniqueId value of the query result item to preview.

    Although only the uniqueId parameter is required when requesting an HTML document from the Search API, you should send all of the parameters that were originally included in the search request that returned the item to preview. This allows the search API to highlight relevant terms in the HTML response.

  2. Call the Search API to execute the query prepared in step 1. When the Search API returns:

    1. Call the Usage Analytics Write API to log the corresponding Click event. In the request body:

      • Set the actionCause property to documentQuickview.

      • Include the following key-value pairs (if available) in the customData property:

        • "author": <author>

        • "contentIdKey": <contentIdKey>

        • "contentIdValue": <contentIdValue>

        • "documentTitle": <documentTitle>

        • "documentUrl": <documentUrl>

        where:

        • <author> (string) is the raw.author value of the clicked query result item (this can be an empty string).

        • <contentIdKey> (string) is the name of a field which uniquely and permanently identifies the clicked item.

        Use "permanentid" (see About the permanentid field). If this is unavailable (for example, if the clicked item resides in a Push source that doesn’t populate the permanentid field with metadata), use "urihash".

        • <contentIdValue> (string) is the value of the field whose name was specified in <contentIdKey>.

        Use the raw.permanentid value of the clicked query result item. If this is unavailable, use the raw.urihash value of the clicked query result.

        • <documentTitle> (string) is the title value of the clicked query result item.

        • <documentUrl> (string) is the uri value of the clicked query result item.

      • Set other required/optional properties as appropriate (language, originLevel1, originLevel2, etc.).

    2. Render the HTML document.

  1. Requesting a Preview

    GET https://myorganizationid9sd8df7s.org.coveo.com/rest/search/v2/html?uniqueId=The_Brothers_Karamazov_Unique_Id&locale=en-US&q=karamazov&searchHub=BookstoreSearch&tab=All HTTP/1.1
     
    Authorization: Bearer **********-****-****-****-************
    

    200 OK response (excerpt)

    <meta http-equiv='Content-Type' content='text/html; charset=CP1252'>
    <base target="_blank" href="https://example.com/books/the-brothers-karamazov">
    <html lang="en"><head>
    ...
      <p>The Brothers
        <span id='CoveoHighlight:1.2.1' style='background-color:#B0FFFF'>Karamazov</span>
        is a passionate philosophical novel set in 19-th century Russia, that enters
        ...
      </p>
    ...
    </body></html>
    
  2. Logging a documentQuickview Click event

    POST https://myorganizationid9sd8df7s.analytics.org.coveo.com/rest/ua/v15/analytics/click?visitor=28s6g49d-f81s-1435-2r5x153dle72 HTTP/1.1
     
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "anonymous": false,
      "actionCause": "documentQuickview",
      "customData":{
        "contentIdKey": "permanentid",
        "contentIdValue": "648a63d6a19545297692b4ae41a7d5e947c711be5f3c23dff69af3106960",
        "author": "Fyodor Dostoyevsky",
        "documentTitle": "The Brothers Karamazov",
        "documentURL": "https://example.com/books/the-brothers-karamazov"
      },
      "documentPosition": 1,
      "documentTitle": "The Brothers Karamazov",
      "documentUriHash": "xyhvGJJGRDM3OiG5",
      "documentUrl": "https://example.com/books/the-brothers-karamazov",
      "language": "en",
      "originLevel1": "BookstoreSearch",
      "originLevel2": "All",
      "searchQueryUid": "7bfc652a-9dea-4811-b3f9-6d24345c37ce",
      "sourceName": "example.com",
      ...
    }
    

Paging query results

As a reference, you may want to look at the source code of the Pager component to see how it’s implemented in the Coveo JavaScript Search Framework.

By default, the results array of a query response contains the first ten items that match the query, according to the specified sort criteria (see Sorting Query Results). However, you may want to allow end users to navigate to a specific page of query results or modify the default page size in your result list implementation. Paging query results involves the following search request parameters:

  • firstResult (unsigned integer)

  • numberOfResults (unsigned integer)

The Search API will return numberOfResults (for example, 50) items , starting from the 0-based index position of the specified firstResult (for example, 10).

When the end user changes the page number of the result list (for example, by clicking a different page number, an arrow, or a button to modify the number of results per page):

  1. Prepare a new query. Ensure that the firstResult and/or numberOfResults search request parameters are set to the desired values.

  2. Call the Search API to execute the query prepared in step 1. When the Search API returns:

    1. Call the Usage Analytics Write API to log the corresponding Custom event. In the request body:

      • Set the eventType property to getMoreResults.

      • Set the eventValue property to:

        • pagerNumber if the end user has selected a specific page.

        • pagerNext if the end user has selected the next page.

        • pagerPrevious if the end user has selected the previous page.

        • pagerScrolling if the end user has scrolled down to the bottom of the result list (for example, in infinite scroll mode) and an additional “page” of query results needs to be loaded.

        • pagerResize if the end user has selected a different number of results to display per page.

      • Include one of the following key-value pairs in the customData property, depending on the specified eventValue:

        • "pagerNumber": <pagerNumber> if eventValue is pagernext, pagerPrevious, or pagerNumber.

        • "currentResultsPerPage": <currentResultsPerPage> if eventValue is pagerResize.

        where:

        • <pagerNumber> (unsigned integer) is the new page number (for example, 2).

        • <currentResultsPerPage> (unsigned integer) is the new number of results per page (for example, 50).

        No customData is required if eventValue is pagerScrolling.

      • Set other required/optional properties as appropriate (language, originLevel1, originLevel2, etc.).

    2. Render the query results (see Rendering Query Results).

  1. Executing a search query when the user, who is currently on page 1, which contains 10 results, selects page 3

    POST https://myorganizationid9sd8df7s.org.coveo.com/rest/search/v2 HTTP/1.1
     
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "firstResult": 20,
      "locale": "en-US",
      "searchHub": "BookstoreSearch",
      "tab": "All",
      ...
    }
    

    200 OK response body (excerpt)

    {
      ...
      "results": [
        ...data to render the result list...
      ],
      "totalCount": 36,
      ...
    }
    
  2. Logging a pagerNumber Custom event for the previous action

    POST https://myorganizationid9sd8df7s.analytics.org.coveo.com/rest/ua/v15/analytics/custom?visitor=28s6g49d-f81s-1435-2r5x153dle72 HTTP/1.1
     
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "anonymous": false,
      "customData": {
        "pagerNumber": "3"
      },
      "eventType": "getMoreResults",
      "eventValue": "pagerNumber",
      "language": "en",
      "originLevel1": "BookstoreSearch",
      "originLevel2": "All",
      ...
    }
    

Sorting query results

As a reference, you may want to look at the source code of the Sort component to see how it’s implemented in the Coveo JavaScript Search Framework.

The Search API sortCriteria query parameter specifies how results are sorted. This parameter has five possible values which you may want to offer as options to your end users:

  • relevancy: Use index ranking factors/weights as well as specified query ranking expressions (QREs) and query ranking functions (QRFs) to compute a ranking score for each item, and sort the results in descending order.

  • date ascending/date descending: Use the @date field to sort the results in the specified order. This field typically contains the last modification date of each item in the index.

  • qre: Use only QREs and QRFs to compute a ranking score for each item, and sort the results in descending order. This is similar to relevancy, except that index ranking factors/weights aren’t computed.

  • nosort: Don’t sort the results. The index will return the results in an indeterminate order.

  • @<field> ascending/@<field> descending: Use the value of a custom, sortable field to sort the results in the specified order. <field> represents a result item field name.

    • When @<field> ascending/@<field> descending is used, the <field> it’s based on must have its sort option set to true (see Available Boolean Field Options).

    • It’s possible to combine zero or one date criterion with one or more field sort criteria by separating them with commas (for example, date ascending,@views descending,@likes descending).

By default, sortCriteria is set to relevancy, meaning that query result items are sorted by their ranking score values, which are computed by the index. These score values are based on several ranking factors/weights (for example, proximity of query terms to one another, term frequency-inverse document frequency, etc.), and they can be influenced by other means such as QREs and QRFs, Coveo ML ART and CR models, and certain types of query pipeline statements.

When the end user chooses a different sortCriteria and/or sort order for the query results (for example, by selecting a value in a Sort By widget):

  1. Prepare a new query. Ensure that the sortCriteria search request parameter is set to the desired value.

  2. Call the Search API to execute the query prepared in step 1. When the Search API returns:

    1. Call the Usage Analytics Write API to log the corresponding Search event. In the request body:

      • Set the actionCause property to resultsSort.

      • Include the following key-value pair in the customData property:

        • "resultsSortBy": <resultsSortBy>

        where:

        • <resultsSortBy> (string) is the new sortCriteria and/or sort order, in lowercase and without spaces (for example, dateascending,@sizeascending instead of date ascending,@size ascending).
      • Set other required/optional properties as appropriate (language, originLevel1, originLevel2, etc.).

    2. Render the query results (see Rendering Query Results).

  1. Executing a search query when the user selects Date Descending

    POST https://myorganizationid9sd8df7s.org.coveo.com/rest/search/v2 HTTP/1.1
     
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "locale": "en-US",
      "q": "tolstoy",
      "searchHub": "BookstoreSearch",
      "sortCriteria": "Date Descending",
      "tab": "All",
      ...
    }
    

    200 OK response body (excerpt)

    {
      ...
      "duration": 105,
      "searchUid": "7bfc652a-9dea-4811-b3f9-6d24345c37ce",
      "results": [
        {
          ...
          "title":"The 19th Century",
          "raw":
            {
              ...
              "date":1375187019000,
              ...
            },
          ...
        },
        {
          ...
          "title":"War and Peace",
          "raw":
            {
              ...
              "date":1375189132000,
              ...
            },
          ...
        },
        {
          ...
          "title":"Russian literature for Dummies",
          "raw":
            {
              ...
              "date":1384880103000,
              ...
            },
          ...
        },
        ...
      ],
      "totalCount": 403,
      ...
    }
    
  2. Logging a resultsSort Search event for the previous action

    POST https://myorganizationid9sd8df7s.analytics.org.coveo.com/rest/ua/v15/analytics/search HTTP/1.1
     
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "actionCause": "resultsSort",
      "anonymous": false,
      "customData": {
        "resultsSortBy": "dateascending"
      },
      "language": "en",
      "originLevel1": "BookstoreSearch",
      "originLevel2": "All",
      "queryText": "tolstoy",
      "responseTime": 105,
      "searchQueryUid": "7bfc652a-9dea-4811-b3f9-6d24345c37ce",
      ...
    }
    

Switching result list layouts

As a reference, you may want to look at the source code of the ResultLayoutSelector component to see how it’s implemented in the Coveo JavaScript Search Framework.

When the end user chooses a different result list layout (for example, by selecting an item in a Layout widget):

  1. Call the Usage Analytics Write API to log the corresponding Custom event. In the request body:

    • Set the eventType property to resultsLayout.

    • Set the eventValue property to changeResultsLayout.

    • Include the following key-value pair in the customData property:

      • "resultsLayoutChangeTo": "<resultsLayoutChangeTo>"

      where:

      • <resultsLayoutChangeTo> (string) is the identifier of the newly selected result list layout (the Coveo JavaScript Search Framework uses the list, card, and table values).
  2. Render the result list with the new layout (see Rendering Query Results).

In the Coveo JavaScript Search Framework, query results are rendered using a different set of result templates for each type of result list layout (that is, list, card, and table).

Logging a changeResultsLayout Custom event when the user selects the list display

POST https://myorganizationid9sd8df7s.analytics.org.coveo.com/rest/ua/v15/analytics/custom?visitor=28s6g49d-f81s-1435-2r5x153dle72 HTTP/1.1
 
Accept: application/json
Content-Type: application/json
Authorization: Bearer **********-****-****-****-************

Payload (excerpt)

{
  ...
  "anonymous": false,
  "customData": {
    "resultsLayoutChangeTo": "list"
  },
  "eventType": "resultsLayout",
  "eventValue": "changeResultsLayout",
  "language": "en",
  "originLevel1": "BookstoreSearch",
  "originLevel2": "All",
  ...
}

Handling folded results

As a reference, you may want to look at the source code of the Folding component to see how it’s implemented in the Coveo JavaScript Search Framework.

A search interface sometimes supports the folding of related query result items. There are two possible folding actions, the first of which simply groups items together. The second action, which builds upon the first, orders the grouped items in logical parent-child relationships.

Implementing the first action requires setting the filterField Search API parameter to @<filterField>, where <filterField> is the name of the field to use for grouping. Upon receiving this request, the Search API sends back a list of result items, where each item contains a childResults array of results which have the same <filterField> value. The childResults arrays are sorted using the sortCriteria, and their maximum length is filterFieldRange (the default value is 5).

To implement the second action, you must provide additional parentField and childField parameters in your Search API request, where the parentField value must uniquely identify each item and the childField value is the value of the parent parentField. When the Search API sends back a list of result items, the items in the childResults arrays will also have a parentResult field, which can be used to resolve parent-child relationships within each folded query result (see Result Folding).

The search API doesn’t necessarily return the result list in the logical parent-child ordering. You will likely need to write client-side logic to resolve the parent-child relationships within each folded query result, using one or both of the above properties.

When a new query is made in a search interface which supports folding:

  1. Prepare a new query. Ensure that filterField, and potentially parentField, childField, and filterFieldRange, are set to the desired values.

  2. Call the Search API to execute the query prepared in step 1. When the Search API returns:

    1. Call the Usage Analytics Write API to log the corresponding Search event).

    2. Render the folded result list. In addition to the standard properties to use when rendering query result items, the search interface needs to use the childResults field to display items belonging to the same group and, if necessary, the parentResult field to resolve parent-child relationships.

  1. A bookstore search interface implements the first folding action to group books by series. Indexed items contain a bookseriesid field that identifies the series to which each item belongs.

    When the end user queries “solzhenitsyn”, the search interface sends the following request to the Search API:

    POST https://myorganizationid9sd8df7s.org.coveo.com/rest/search/v2 HTTP/1.1
     
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "locale": "en-US",
      "q": "solzhenitsyn",
      "filterField":"@bookseriesid",
      "searchHub": "BookstoreSearch",
      "tab": "All",
      ...
    }
    

    200 OK response body (excerpt)

    {
    ...
      "results": [
        {
          ...
          "title": "The Gulag Archipelago, Vol. 2",
          "raw":
            {
              ...
              "bookseriesid":"GulagArchipelagoHarperClassics",
              ...
            },
          ...
          "childResults": [
            {
              "title": "The Gulag Archipelago, Vol. 1",
              "raw":
                {
                  ...
                  "bookseriesid":"GulagArchipelagoHarperClassics",
                  ...
                },
              ...
            },
            {
              "title": "The Gulag Archipelago, Vol. 3",
              "raw":
                {
                  ...
                  "bookseriesid":"GulagArchipelagoHarperClassics",
                  ...
                },
              ...
            },
          ],
          ...
        },
        {
          ...
          "title": "One Day in the Life of Ivan Denisovich",
          "raw":
            {
              ...
              "bookseriesid":"OneDayLifeIvanDenisovichSignetClassics",
              ...
            },
          ...
          "childResults": [],
          ...
        },
        ...
      ],
      ...
    }
    

    As you can see in the above query response, the Search API returns a list of items grouped by bookseriesid. The results are sorted by relevance (this applies to both the results and childResults arrays). Also, when a book series contains only one item, its childResults array is empty.

  2. A bookstore search interface implements both folding actions to group books by series and order them in logical parent-child relationships. Indexed items contain a bookseriesid field that identifies the series to which each item belongs, a bookid field that uniquely identifies each book within its series, if applicable, and a parentbookid that indicates the bookid of the parent book, if applicable.

    When the end user queries “solzhenitsyn”, the search interface sends the following request to the Search API:

    POST https://myorganizationid9sd8df7s.org.coveo.com/rest/search/v2 HTTP/1.1
     
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "locale": "en-US",
      "q": "solzhenitsyn",
      "filterField":"@bookseriesid",
      "parentField":"@bookid",
      "childField":"@parentbookid",
      "searchHub": "BookstoreSearch",
      "sortCriteria": "Date Descending",
      "tab": "All",
      ...
    }
    

    200 OK response body (excerpt)

    {
    ...
      "results": [
        {
          ...
          "title": "The Gulag Archipelago, Vol. 2",
          "raw":
            {
              ...
              "bookseriesid":"GulagArchipelagoHarperClassics",
              "bookid":"GulagArchipelagoHarperClassics2",
              "parentbookid":"GulagArchipelagoHarperClassics1",
              ...
            },
          ...
          "childResults": [
            {
              "title": "The Gulag Archipelago, Vol. 1",
              "raw":
                {
                  ...
                  "bookseriesid":"GulagArchipelagoHarperClassics",
                  "bookid":"GulagArchipelagoHarperClassics1",
                  "parentbookid":"GulagArchipelagoHarperClassics1",
                  ...
                },
              ...
            },
            {
              "title": "The Gulag Archipelago, Vol. 3",
              "raw":
                {
                  ...
                  "bookseriesid":"GulagArchipelagoHarperClassics",
                  "bookid":"GulagArchipelagoHarperClassics3",
                  "parentbookid":"GulagArchipelagoHarperClassics1",
                  ...
                },
              ...
            },
          ],
          ...
        },
        {
          ...
          "title": "One Day in the Life of Ivan Denisovich",
          "raw":
            {
              ...
              "bookseriesid":"OneDayLifeIvanDenisovichSignetClassics",
              ...
            },
          ...
          "childResults": [],
          ...
        },
        ...
      ],
      ...
    }
    

    As you can see in the above query response, the Search API returns a list of items grouped by bookseriesid. The results are sorted by relevance (this applies to both the results and childResults arrays), and the bookid and parentbookid fields are required to resolve the logical ordering. Also, when a book series contains only one item, its childResults array is empty and its parentField and childField fields don’t need to be populated.

Exporting results

As a reference, you may want to look at the source code of the ExportToExcel component to see how it’s implemented in the Coveo JavaScript Search Framework.

A search interface sometimes offers the possibility to export the result list in Excel or OpenSearch format.

When the end user chooses to export the result list (for example, by clicking an Export to Excel button):

  1. Prepare a new query. Ensure that the format property is set to:

    • opensearch-atom or opensearch-rss if the end user selected an OpenSearch format.

    • xlsx if the end user selected the Excel format.

  2. Call the Search API to execute the query prepared in step 1. When the Search API returns:

    1. If format is set to xlsx, call the Usage Analytics Write API to log the corresponding Custom event. In the request body:

      • Set the eventType property to misc.

      • Set the eventValue property to exportToExcel.

      The Coveo JavaScript Search Framework doesn’t currently support exporting in XML format. As a result, if the end user selects export to XML, there are currently no precise guidelines to follow when logging the corresponding usage analytics event.

    2. Generate a download link for the end-user.

  1. Executing a search query when the end user clicks an exportToExcel button

    POST https://myorganizationid9sd8df7s.org.coveo.com/rest/search/v2 HTTP/1.1
     
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "format": "xlsx",
      ...
    }
    
  2. Logging an exportToExcel Custom event for the previous action

    POST https://myorganizationid9sd8df7s.analytics.org.coveo.com/rest/ua/v15/analytics/custom?visitor=28s6g49d-f81s-1435-2r5x153dle72 HTTP/1.1
     
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "anonymous": false,
      "eventType": "misc",
      "eventValue": "exportToExcel",
      "language": "en",
      "originLevel1": "BookstoreSearch",
      "originLevel2": "All",
      ...
    }
    

Toggling a facet value from a result list item

In some result lists, query result items contain clickable fields which the end user can toggle to filter the entire result list (that is, select/deselect a facet value).

When the end user clicks a result list item field (for example, by clicking the salesforce field):

  1. Prepare a new query. This is identical to the query sent when selecting/deselecting the associated facet value (see Toggling Facet Values).

  2. Call the Search API to execute the query prepared in step 1. When the Search API returns:

    1. Call the Usage Analytics Write API to log the corresponding Search event. In the request body:

      • Set the actionCause property to documentField.

      • Include the following key-value pairs in the customData property:

        • facetField: <facetField>

        • facetId: <facetId>

        • facetValue: <facetValue>

        where:

        • <facetField> (string) is the @-prefixed name of the field the toggled facet is based on (for example, @tags).

        • <facetId> (string) is the unique identifier of the toggled facet. Typically, this is the name of the field this facet is based on (for example, @tags).

        • <facetValue> (string) is the value of the field selected by the end user (for example, salesforce).

      • Set other required/optional properties as appropriate (language, originLevel1, originLevel2, etc.).

    2. Update the facet instance.

    3. Render the query results (see Rendering Query Results).

  1. Executing a search query when the user selects the salesforce item field

    POST https://myorganizationid9sd8df7s.org.coveo.com/rest/search/v2 HTTP/1.1
     
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "aq": "(@tags==("salesforce"))",
      "locale": "en-US",
      "q": "coveo",
      "searchHub": "ExternalSearch",
      "tab": "All",
      ...
    }
    

    200 OK response body (excerpt)

    {
      ...
      "duration": 247,
      "searchUid": "de6cb58a-2abb-4718-a874-cc2162691cd9",
      "results": [
        ...data to render the result list...
      ],
      "totalCount": 272,
      ...
    }
    
  2. Logging a documentField Search event for the previous action

    POST https://myorganizationid9sd8df7s.analytics.org.coveo.com/rest/ua/v15/analytics/search HTTP/1.1
     
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer **********-****-****-****-************
    

    Payload (excerpt)

    {
      ...
      "actionCause": "documentField",
      "anonymous": false,
      "customData": {
        "facetField": "@tags",
        "facetId": "@tags",
        "facetValue": "salesforce"
      },
      "language": "en",
      "originLevel1": "ExternalSearch",
      "originLevel2": "All",
      "queryText": "coveo",
      "responseTime": 247,
      "searchQueryUid": "de6cb58a-2abb-4718-a874-cc2162691cd9",
      ...
    }