Implement a result list
Implement a result list
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:
-
Usage analytics reports may become incoherent in the underlying Coveo organization (especially if that organization powers both Coveo JavaScript Search Framework and custom search interfaces).
-
The Coveo Machine Learning (Coveo ML) service may not function properly.
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 theexcerptLength
parameter in the search request. -
firstSentences
: The first sentences of the item. This property won’t be populated unless theretrieveFirstSentences
parameter is set totrue
in the search request. You can set the maximum length (in number of characters,200
by default) using theexcerptLength
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 thesummaryLength
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 thehref
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) ascustomData
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):
-
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 theraw.author
value of the clicked query result item (this can be an empty string). -
<documentTitle>
(string) is thetitle
value of the clicked query result item. -
<documentUrl>
(string) is theuri
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 thepermanentid
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 theraw.urihash
value of the clicked query result. -
-
Set other required/optional properties as appropriate (
language
, originLevel1, originLevel2, etc.).
-
-
When the Usage Analytics Write API returns, redirect the client as appropriate (using the
clickableUri
value of the clicked query result item).
-
Logging a
documentOpen
Click eventPOST 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", ... }
-
Logging a
recommendationOpen
Click eventPOST 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 thanPOST
.
When the end user previews a query result item (for example, by clicking a Preview button):
-
Prepare a
GET
request tohttps://<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 theraw.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. -
Call the Search API to execute the query prepared in step 1. When the Search API returns:
-
Call the Usage Analytics Write API to log the corresponding Click event. In the request body:
-
Set the
actionCause
property todocumentQuickview
. -
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 theraw.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 thepermanentid
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 theraw.urihash
value of the clicked query result.-
<documentTitle>
(string) is thetitle
value of the clicked query result item. -
<documentUrl>
(string) is theuri
value of the clicked query result item.
-
-
Set other required/optional properties as appropriate (
language
,originLevel1
,originLevel2
, etc.).
-
-
Render the HTML document.
-
-
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>
-
Logging a
documentQuickview
Click eventPOST 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):
-
Prepare a new query. Ensure that the
firstResult
and/ornumberOfResults
search request parameters are set to the desired values. -
Call the Search API to execute the query prepared in step 1. When the Search API returns:
-
Call the Usage Analytics Write API to log the corresponding Custom event. In the request body:
-
Set the
eventType
property togetMoreResults
. -
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 specifiedeventValue
:-
"pagerNumber": <pagerNumber>
ifeventValue
ispagernext
,pagerPrevious
, orpagerNumber
. -
"currentResultsPerPage": <currentResultsPerPage>
ifeventValue
ispagerResize
.
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 ifeventValue
ispagerScrolling
. -
-
Set other required/optional properties as appropriate (
language
,originLevel1
,originLevel2
, etc.).
-
-
Render the query results (see Rendering Query Results).
-
-
Executing a search query when the user, who is currently on page
1
, which contains10
results, selects page3
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, ... }
-
Logging a
pagerNumber
Custom event for the previous actionPOST 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 rankingscore
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 rankingscore
for each item, and sort the results in descending order. This is similar torelevancy
, 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 itssort
option set totrue
(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):
-
Prepare a new query. Ensure that the
sortCriteria
search request parameter is set to the desired value. -
Call the Search API to execute the query prepared in step 1. When the Search API returns:
-
Call the Usage Analytics Write API to log the corresponding Search event. In the request body:
-
Set the
actionCause
property toresultsSort
. -
Include the following key-value pair in the
customData
property:-
"resultsSortBy"
:<resultsSortBy>
where:
-
<resultsSortBy>
(string) is the newsortCriteria
and/or sort order, in lowercase and without spaces (for example,dateascending,@sizeascending
instead ofdate ascending,@size ascending
).
-
-
Set other required/optional properties as appropriate (
language
,originLevel1
,originLevel2
, etc.).
-
-
Render the query results (see Rendering Query Results).
-
-
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, ... }
-
Logging a
resultsSort
Search event for the previous actionPOST 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):
-
Call the Usage Analytics Write API to log the corresponding Custom event. In the request body:
-
Set the
eventType
property toresultsLayout
. -
Set the
eventValue
property tochangeResultsLayout
. -
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 thelist
,card
, andtable
values).
-
-
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:
-
Prepare a new query. Ensure that
filterField
, and potentiallyparentField
,childField
, andfilterFieldRange
, are set to the desired values. -
Call the Search API to execute the query prepared in step 1. When the Search API returns:
-
Call the Usage Analytics Write API to log the corresponding Search event).
-
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, theparentResult
field to resolve parent-child relationships.
-
-
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 theresults
andchildResults
arrays). Also, when a book series contains only one item, itschildResults
array is empty. -
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, abookid
field that uniquely identifies each book within its series, if applicable, and aparentbookid
that indicates thebookid
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 theresults
andchildResults
arrays), and thebookid
andparentbookid
fields are required to resolve the logical ordering. Also, when a book series contains only one item, itschildResults
array is empty and itsparentField
andchildField
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):
-
Prepare a new query. Ensure that the
format
property is set to:-
opensearch-atom
oropensearch-rss
if the end user selected an OpenSearch format. -
xlsx
if the end user selected the Excel format.
-
-
Call the Search API to execute the query prepared in step 1. When the Search API returns:
-
If
format
is set toxlsx
, call the Usage Analytics Write API to log the corresponding Custom event. In the request body:-
Set the
eventType
property tomisc
. -
Set the
eventValue
property toexportToExcel
.
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.
-
-
Generate a download link for the end-user.
-
-
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", ... }
-
Logging an
exportToExcel
Custom event for the previous actionPOST 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):
-
Prepare a new query. This is identical to the query sent when selecting/deselecting the associated facet value (see Toggling Facet Values).
-
Call the Search API to execute the query prepared in step 1. When the Search API returns:
-
Call the Usage Analytics Write API to log the corresponding Search event. In the request body:
-
Set the
actionCause
property todocumentField
. -
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.).
-
-
Update the facet instance.
-
Render the query results (see Rendering Query Results).
-
-
Executing a search query when the user selects the
salesforce
item fieldPOST 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, ... }
-
Logging a
documentField
Search event for the previous actionPOST 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", ... }