Usage
Usage
Coveo Quantic is a Lightning Web Component (LWC) library for assembling powerful and responsive Coveo for Salesforce search interfaces. Quantic components are self-encapsulated, composable, and lightweight.
Under the hood, Quantic relies on the Coveo Headless library to interface with Coveo and handle the application state.
This article provides an overview of the core Quantic concepts by guiding you through the implementation of a search interface component.
Prerequisites
-
SFDX with a configured dev hub.
Since you’ll use Quantic to assemble LWCs, and LWCs are meant to be managed in SFDX projects, you’ll need SFDX.
-
In addition, while it’s not strictly necessary, we recommend installing and configuring the Coveo for Salesforce package, since it can automatically take care of important steps at the search token authentication stage (see the first two steps of the Get Started With Coveo for Salesforce) article.
Install Quantic
Quantic is released as an unlocked package. You can install it using the following links:
Otherwise, you can also use the SFDX force:package:install
command as follows:
sfdx force:package:install --package 04t6g000008fh0KAAQ -u <USER_NAME>
Where you replace <USER_NAME>
by your username in the target organization.
|
Note
While you should always keep all of your Apex code clean and compiled, if you wish to compile only the package Apex code during the installation rather than all of your Apex code, use the
|
Assemble Your Component
You use Quantic by creating LWCs that assemble the target Quantic components.
Because Quantic is released as an unlocked package, its components will be available under the default namespace c
.
In this article, we’ll create a search interface component. You can find a complete example in the Quantic project repository.
Setup
Create an SFDX Project
As mentioned in the prerequisites section, you need to create an SFDX project to manage your component.
The SFDX project structure is largely up to you, but you may want to retrieve Quantic locally in your project, so you can more easily navigate to the existing Quantic components and use them as examples when building your own.
You can import the Quantic project in yours using the SFDX force:mdapi:retrieve
command as follows:
sfdx force:mdapi:retrieve -p Quantic -r ./ -u <USER_NAME>
Where you replace <USER_NAME>
by your username in the target Salesforce organization.
Then, unzip the retrieved file and move its contents to force-app/quantic
.
Create Your Component
The next step, in your SFDX project, is to create your component.
You can use the SFDX force:lightning:component:create
command to do so.
For this example, let’s call it mySearchPage
.
sfdx force:lightning:component:create --type lwc -n mySearchPage
HTML
Open the HTML page of your newly created component (in this case, mySearchPage.html
).
This is where you assemble HTML elements to create your component, leveraging Quantic components.
In addition, you will typically want to set the function that will handle your result templates (more on that below).
<template>
<div onregisterresulttemplates={handleResultTemplateRegistration}>
<div class="search__grid">
<c-quantic-search-interface engine-id={engineId} search-hub={searchHub}>
<div class="slds-grid slds-grid_vertical slds-grid_align-center">
<div class="slds-col slds-size_1-of-1 slds-large-size_6-of-12 slds-align-middle">
<div class="slds-m-vertical_small">
<c-quantic-search-box engine-id={engineId}></c-quantic-search-box>
</div>
</div>
<div class="slds-col">
<div class="slds-grid slds-gutters_direct slds-wrap main slds-grid_align-center">
<div class="slds-col slds-order_2 slds-large-order_1 slds-size_1-of-1 slds-large-size_3-of-12">
<div class="slds-m-bottom_large">
<c-quantic-facet field="objecttype" label="Type" engine-id={engineId}></c-quantic-facet>
</div>
<div class="slds-m-bottom_large">
<c-quantic-facet display-values-as="link" field="filetype" label="File Type" engine-id={engineId}></c-quantic-facet>
</div>
</div>
<div class="slds-col slds-order_1 slds-large-order_2 slds-size_1-of-1 slds-large-size_6-of-12">
<ul class="slds-tabs_default slds-tabs_default__nav" role="tablist">
<c-quantic-tab label="All" engine-id={engineId}></c-quantic-tab>
<c-quantic-tab label="Articles" expression="@sfkbid" engine-id={engineId}></c-quantic-tab>
</ul>
<c-quantic-result-list engine-id={engineId}></c-quantic-result-list>
<div class="slds-var-m-vertical_medium">
<c-quantic-pager engine-id={engineId}></c-quantic-pager>
</div>
</div>
</div>
</div>
</div>
</c-quantic-search-interface>
</div>
</div>
</template>
Attach the handleResultTemplateRegistration function on the event thrown to register result templates (more on that below). |
|
Use the QuanticSearchInterface component, setting its engine-id and search-hub using variables whose values we’ll set in the next section.
This search interface component is required to handle the Headless search engine and localization configurations.
Most Quantic components require an engine-id , and all components that belong to a given interface must have the same engine-id .
Sharing this engine-id across components is what allows the QuanticSearchInterface component to establish the connection between them.
You must have one and only one QuanticSearchInterface component per engine-id in a given page or Digital Experience. |
|
Out of the box, Quantic allows you to use Salesforce Lightning Design System (SLDS) styling classes. In this case, we’re using the Grid utility. | |
Use the SLDS gutters_direct class, so it applies only to direct children.
Merely using the gutters class could cause styling issues in certain Quantic child components. |
|
The QuanticResultList component, inside which your result templates will initialize (more on that below). |
You may have noticed that, for the sake of simplicity, we have kept the above example fairly brief. You can find a more detailed example in the Quantic project repository.
XML
Your component XML file is where you define the targets of your component (see XML Configuration File Elements). In addition, this is where you specify parameters whose values your component requests through the Salesforce Experience Builder. You can also set default values for those parameters.
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>50.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
<target>lightningCommunity__Page</target>
<target>lightningCommunity__Default</target>
</targets>
<targetConfigs>
<targetConfig targets="lightningCommunity__Default">
<property name="engineId" type="String" default="example-search-community" label="Enter Coveo Headless engine ID"/>
<property name="searchHub" type="String" default="example-search-community-hub" label="Enter Search Hub"/>
</targetConfig>
<targetConfig targets="lightning__AppPage, lightning__RecordPage, lightning__HomePage">
<property name="engineId" type="String" default="example-search" label="Enter Coveo Headless engine ID"/>
<property name="searchHub" type="String" default="example-search-hub" label="Enter Search Hub"/>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
The targets where your component will be available (see XML Configuration File Elements). | |
In the lightningCommunity__Default target, expose the engineId and searchHub properties for editing in the Salesforce Experience Builder.
We passed these variables to instantiate Quantic components in your component HTML.
Set their default values to example-search-community and example-search-community-hub , respectively, for this target.
In the next targetConfig element, we do similarly for different targets. |
For simplicity, we kept the above example fairly short. You can find a more detailed one in the Quantic project repository.
Result Templates
Result templates are HTML files that determine the format of the individual result items in a search interface.
You build them by assembling SLDS elements and Quantic components.
Inside those, you can invoke the result
variable, which is passed by the result template manager and holds various result item attributes.
Typically, you’ll want to define your result templates in a folder that is a sibling of your other search interface files. You’ll learn how to connect them using conditions below.
mySearchPage/
├── resultTemplates/
│ ├── youtubeResultTemplate.html
├── mySearchPage.css
├── mySearchPage.js
├── mySearchPage.html
├── mySearchPage.js-meta.xml
While optional, we recommend using the QuanticResultTemplate
component, as it can significantly ease the process of creating new templates that are both responsive and stylistically cohesive.
It provides a recommended display structure using predefined and formatted slots.
<!-- force-app/main/default/lwc/mySearchPage/resultTemplates/youtubeResultTemplate.html -->
<template>
<c-quantic-result-template>
<c-quantic-result-label slot="label" result={result}></c-quantic-result-label>
<div slot="badges" class="slds-grid slds-grid_vertical-align-center">
<div class="slds-m-right_xx-small">
<c-quantic-result-badge variant="recommended" result={result}></c-quantic-result-badge>
</div>
<c-quantic-result-badge variant="featured" result={result}></c-quantic-result-badge>
</div>
<template if:true={resultHasPreview}>
<c-quantic-result-quickview slot="actions" engine-id={engineId} result={result}></c-quantic-result-quickview>
</template>
<p slot="date" class="slds-size_xx-small">
<lightning-formatted-date-time value={result.raw.date}></lightning-formatted-date-time>
</p>
<h3 slot="title" class="slds-truncate">
<c-quantic-result-link result={result} engine-id={engineId}></c-quantic-result-link>
</h3>
<div slot="visual" class="slds-size_1-of-1 slds-medium-size_1-of-4 slds-large-size_1-of-4 slds-p-right_x-small slds-m-top_xx-small slds-m-bottom_x-small">
<img style="border-radius: 4px; border: none;" src={videoThumbnail}></img>
</div>
<div slot="excerpt">
{result.Excerpt}
</div>
<div slot="bottom-metadata" class="slds-grid slds-text-align_left slds-m-top_xx-small" style="font-size: 10px">
<lightning-icon icon-name="utility:clock" size="xx-small"></lightning-icon>
<span class="slds-m-left_xxx-small">{videoTimeSpan}</span>
</div>
</c-quantic-result-template>
</template>
Wrap your template in the QuanticResultTemplate component. |
|
Use the QuanticResultLabel component.
To instantiate this component, we don’t need to specify the engine ID, but we do need to pass the result item.
Also, notice that we’re using the label slot. |
|
Pass the result raw.date field to the Lightning Formatted Date Time component to display it.
Further, notice that we are doing so in the date slot. |
|
The QuanticResult component exposes a videoThumbnail attribute which, as its name suggests, you can use in your result template to display the video thumbnail. |
You can find other result template examples in the Quantic project repository.
JavaScript
Open the .js
file of your component (e.g., mySearchPage.js
).
This is where you connect your result templates with your main HTML file, using conditions.
Additionally, this is where you define the variables you used in the HTML file, and whose values you set using the XML file.
import youtubeTemplate from './resultTemplates/youtubeResultTemplate.html';
import {LightningElement, api} from 'lwc';
export default class MySearchPage extends LightningElement {
@api engineId = 'example-search';
@api searchHub = 'example-hub';
handleResultTemplateRegistration(event) {
event.stopPropagation();
const resultTemplatesManager = event.detail;
const isYouTube = CoveoHeadless.ResultTemplatesHelpers.fieldMustMatch(
'filetype',
['YouTubeVideo']
);
resultTemplatesManager.registerTemplates(
{
content: youtubeTemplate,
conditions: [isYouTube],
fields: ['ytvideoid', 'ytvideoduration'],
priority: 1
},
);
}
}
Define the variables used to hold your engine ID and search hub, and set default values. These default values are secondary to the values set in your component XML file. | |
The function that we attached to the onregisterresulttemplates event in your component HTML file.
As the name of the event suggests, it lets you to register your result templates. |
|
Since you caught the event, stop its propagation. | |
The detail property contains a result template manager.
Store it in a variable so you can use it a few lines below. |
|
Create a condition that matches YouTube videos. | |
Register the result template on the result template manager. | |
This line and the following make it so that your youtubeTemplate defined above only applies to result items that fullfil your isYoutube condition.
If a result item doesn’t match the conditions of any of your result templates, then the default Quantic one applies. |
|
Specify the fields to include in the search requests made by Quantic, because you need them in your youtubeTemplate .
By default, the Coveo index doesn’t return all possible item field values, for optimization purposes.
You must specify any non-default fields you want to use in your result templates. |
|
Sets the priority of the result template. If the conditions of multiple templates are satisfied by a given result, the template with the highest priority is selected. If multiple templates have equal priority, the first template registered is selected. |
For simplicity, we kept the example above fairly brief. You can see a more detailed one in the Quantic project repository.
CSS
As mentioned above, you can use SLDS styling classes in your component markup.
You can also edit the .css
file of your component for further styling.
.search__grid {
position: relative;
padding: 12px;
background: #fff;
border-radius: .25rem;
background-clip: padding-box;
}
Search Token Provider
If you tried to deploy your component as it stands right now, you would see that it returns results.
That being said, those results aren’t yours. They come from a sample organization meant for testing purposes only. For a real implementation, you need to configure search token authentication in your search page. That way, each user gets their own search token, with appropriate privileges on your organization content. Additionally, personalized search tokens allow for personalized Coveo Usage Analytics and Machine Learning.
If you have installed and configured the Coveo for Salesforce V4 package in your Salesforce organization, it typically suffices to copy the CoveoTokenProvider
Apex class, along with its meta.xml
file, and to include them in your SFDX project.
That class can automatically fetch your Salesforce users' information to generate search tokens for them, provided you have installed and configured the Coveo for Salesforce package in your Salesforce organization.
For most use cases, using this class is the best and simplest option.
If you have not installed the Coveo for Salesforce V4 package, or if you think that the standard CoveoTokenProvider
Apex class doesn’t fit your needs, you need to implement your own search token provider.
You can find an example in the Quantic project repository.
Once you have created your search token provider Apex class, you need to modify your Headless configuration in your Quantic installation, so it calls your Apex class.
Do so in the HeadlessController
file.
Locate the following line:
return SampleTokenProvider.getHeadlessConfiguration();
Modify it so it instead leverages your own token provider:
return CoveoTokenProvider.getHeadlessConfiguration();
You can make the change locally if you have retrieved the Quantic project locally. When you deploy your SFDX project, your changes will be effective in your Salesforce organization. If you haven’t retrieved the package locally, you can alternatively navigate to that file from the Salesforce developer console, and modify it there.
Update Quantic
Updating the Quantic package is similar to updating other Salesforce packages, except for a few tweaks.
-
Start by installing the latest version.
-
Then, if you retrieved the Quantic package locally in your SFDX project, you’ll need to do so again to keep your SFDX project version in sync with the new one in your Salesforce organization.
-
Next, as you did when configuring your search token provider, you need to reference your own provider in the
HeadlessController
file, because it will get overwritten by updates.
What’s Next?
After implementing a main search page in an Experience Cloud site (i.e., Community), you’ll typically want to implement a standalone search box.