--- title: Safely apply content filtering slug: lb1f1380 canonical_url: https://docs.coveo.com/en/lb1f1380/ collection: coveo-for-salesforce source_format: adoc --- # Safely apply content filtering The best way to ensure that your indexed content is seen only by the intended users is to enforce [content security](https://docs.coveo.com/en/1052#content-security-tab) when [configuring your Salesforce source](https://docs.coveo.com/en/1052#add-a-salesforce-source). The **Same users and groups as in your content system** content security option replicates the security model of your Salesforce organization, which means that users only see the content that they're allowed to see in Salesforce when obtaining search results from a Coveo [index](https://docs.coveo.com/en/204/). However, you may face situations where you have to configure your [source](https://docs.coveo.com/en/246/) to be accessible to everyone. This is typically the case when you index Salesforce Knowledge Base (KB) records that are based on [data categories](https://help.salesforce.com/s/articleView?id=sf.category_parent_admin.htm&type=5) as [Coveo can't replicate this security model](https://docs.coveo.com/en/1052#limitations-regarding-salesforce-securities). > **Leading practice** > > When using the Salesforce [Sharing for Lightning Knowledge](https://help.salesforce.com/s/articleView?id=sf.knowledge_sharing.htm&type=5) security model, Coveo automatically supports permissions set on **Online**, **Draft**, and **Archived** articles. This article provides the leading practices to safely filter content from a source whose content is accessible to everyone in a Salesforce Community. ## Configure query filters [Filter rules](https://docs.coveo.com/en/3410/) allow you to enter hidden [query](https://docs.coveo.com/en/231/) expressions to be added to all queries going through a given [query pipeline](https://docs.coveo.com/en/180/). They're typically used to add a field-based expression to the [constant query expression (`cq`)](https://docs.coveo.com/en/179/). **Example** You apply the `@objectType=="Solution"` query filter to the pipeline to which the traffic of your public support portal is directed. As a result, the `@objectType=="Solution"` query expression is added to any query sent via this support portal. Therefore, if a user types `Speedbit watch wristband` in the searchbox, the items returned are those that match these keywords and whose `objectType` has the `Solution` value. Items matching these keywords but having a different `objectType` value aren't returned in the user's search results. > **Important** > > Filters, by themselves, don't prevent the exposure of filtered content. > We strongly advise against creating a source whose content is [accessible to everyone](https://docs.coveo.com/en/1779#everyone) and using a pipeline filter to exclude sensitive information. > > In the following cases, sensitive content from a source whose content is [accessible to everyone](https://docs.coveo.com/en/1779#everyone) could be exposed: > > * A filter rule based on the [`aq`](https://docs.coveo.com/en/13#operation/searchUsingPost-aq) query parameter is set on a query pipeline that contains an [ART](https://docs.coveo.com/en/1013/) [model](https://docs.coveo.com/en/1012/) for which the [**Match the advanced query**](https://docs.coveo.com/en/l1ca1038#match-the-advanced-query) option is disabled. > > * Using other pipelines not having a similar filter from other search interfaces or directly from the API. > > * A colleague not understanding the reason for the filter could modify or remove the filter. To learn how to configure query pipeline filter rules, see [Manage filter rules](https://docs.coveo.com/en/3410/). > **Note** > > You can enforce a filter expression directly in the [search token](https://docs.coveo.com/en/1346/). > See [Configure the Search Token](https://docs.coveo.com/en/lb1f1380#configure-the-search-token) for instructions. ## Use the proper query pipeline routing mechanism The most recommended and flexible [query pipeline routing mechanism](https://docs.coveo.com/en/1666/) is [condition-based routing](https://docs.coveo.com/en/1666#condition-based-routing-recommended). In this scenario, search requests are authenticated with a search token that contains a [`searchHub`](https://docs.coveo.com/en/1075#searchhub-optional) parameter, and each query pipeline except the default one has a distinct [query pipeline condition](https://docs.coveo.com/en/2793/) based on a specific [search hub](https://docs.coveo.com/en/1342/) value such as **Search Hub is Community Search** or **Search Hub is Agent Panel**. When using this routing mechanism, you ensure that search requests are routed according to the search interface from which they originate. > **Important** > > Always use positive [operators](https://docs.coveo.com/en/1959#operators) (for example, `is`, `contains`, or `matches`) when creating a condition that aims at routing the queries originating from a specific search interface to a given query pipeline. ## Configure the search token When using query filters to secure content, the safest way to enforce content security is to authenticate user queries using a search token that's generated server side. For instance, when using this approach, you can enforce a search hub value in the search token, which will make every authenticated request originating from the desired component use the specified search hub. Because this configuration is stored server side and encrypted in the search token, it can't be modified by users or client-side code. The procedure to generate a custom search token differs depending on the origin of the authenticated request: * [Community Search component](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-community-search-component) * [Community Search Box component](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-community-search-box-component) * [Case Deflection component](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-case-deflection-component) * [Page View Tracker component](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-page-view-tracker-component) * [Recommendations component](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-recommendations-component) * [Quantic Search Interface](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-quantic-search-interface) ### Configure the search token for a Community Search component Since the [Coveo for Salesforce (v4.23)](https://docs.coveo.com/en/3236/) release, you can enforce a search hub in the search token that authenticates queries originating from a Coveo Lightning Recommendations component by using the [**Search Hub**](https://docs.coveo.com/en/1162#search-hub) option in the [**Advanced Server-Side Configuration**](https://docs.coveo.com/en/1162/) panel. > **Note** > > Setting a search hub using the **Search Hub** option of the **Advanced Server-Side Configuration** will override any search hub value set when building the page. Doing so prevents you from having to [create an Apex class to generate a custom search token](https://docs.coveo.com/en/lb1f1380#step-1-create-an-apex-class-to-generate-the-search-token). If you choose this approach to enforce a search hub in your search token, you can skip to [step 5](https://docs.coveo.com/en/lb1f1380#step-5-validate-the-search-token). #### Step 1: Create an Apex class to generate the search token . In Salesforce, access the [**Developer Console**](https://help.salesforce.com/s/articleView?id=sf.code_dev_console.htm&type=5). . In the **Developer Console**, create a new Apex class ( **File** > **New** > **Apex Class**). . In the new Apex class, enter the following template: ```apex public with sharing class { // Annotate the method so that it's accessible from the Lightning component @AuraEnabled public static string getToken() { // Generate a token using the Globals Class provided by Coveo. // See the Globals Class documentation: https://docs.coveo.com/en/1075/coveo-for-salesforce/globals-class Map endpoint = CoveoV2.Globals.getEndpointData(); endpoint.put('token', CoveoV2.Globals.generateSearchToken()); return JSON.serialize(endpoint); } } ``` Where you replace `` with the name you chose for your Apex class. . In the `getToken()` class, enter your code to create the custom search token. Modify that code to at least include the [`searchHub`](https://docs.coveo.com/en/1075#searchhub-optional) in your token generation steps. > **Warning** > > For content security reasons, don't specify a search hub value as a parameter of the `getToken()` class (for example, `getToken(String searchHub`)). **Example** ```apex public with sharing class { // Annotate the method so that it's accessible from the Lightning component @AuraEnabled public static string getToken() { // Generate a token using the Globals Class provided by Coveo. // See the Globals Class documentation: https://docs.coveo.com/en/1075/coveo-for-salesforce/globals-class Map endpoint = CoveoV2.Globals.getEndpointData(); endpoint.put('token', CoveoV2.Globals.generateSearchToken(new Map { 'searchHub' => '' })); return JSON.serialize(endpoint); } } ``` Where you replace `` with the name of the search hub to enforce in the search token. Note that you can specify other parameters in the search token, such as [query filters](https://docs.coveo.com/en/1075#filter-optional) or a [query pipeline](https://docs.coveo.com/en/1075#pipeline-optional). See [Globals Class](https://docs.coveo.com/en/1075/) for instructions. . Save the Apex class. > **Note** > > While you can use the [**Advanced Server-Side Configuration**](https://docs.coveo.com/en/1162/) panel to add configurations to the search token, this panel doesn't let you enforce a specific query pipeline in the search token. #### Step 2: Create the custom Lightning endpoint handler Now that you've created your Apex class, you must create a custom Lightning endpoint handler to reference your Apex class in your Lightning component. . In the **Developer Console**, [create a Lightning component](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_create_devconsole.htm). . In the component `.cmp`, add the following code: ```xml ``` Where you replace `` with the name of the Apex class you created in previous step. . In the `controller.js` file, enter the following code: ```javascript ({ getTokenAction: function(component, event, helper) { const getTokenAction = component.get('c.getToken'); var getTokenPromise = new Promise(function (resolve, reject) { getTokenAction.setCallback(this, function (response) { if (response.getState() === 'SUCCESS') { var responseData = response.getReturnValue(); resolve(JSON.parse(responseData)); } else if (response.getState() === 'ERROR') { reject(Error('Error generating token')); } }); }); $A.enqueueAction(getTokenAction); return getTokenPromise; } }); ``` . Save the file. Your custom Lightning endpoint handler is now ready. > **Note** > > In our simple example, since there's no difference between the generation and the renewal of a token, we call the same `controller.js` method twice. #### Step 3: Reference the custom Lightning endpoint handler in a Community Search component Now that you've created your Apex class to generate a custom search token and a custom Lightning endpoint handler, you must reference the custom Lightning endpoint handler in a Recommendations component. > **Note** > > The following procedure assumes that you've wrapped a default Coveo Lightning component to create a custom Lightning component. > See [Integrate Coveo components in a custom Lightning component for your Experience Cloud site](https://docs.coveo.com/en/1193/) for instructions. . In Salesforce, access an existing custom Lightning component, or [create a new one](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_create_devconsole.htm). . In the component `.cmp`, ensure that your component references the custom Lightning endpoint handler you created in the last step. For example, the component `.cmp` should look like the following: ```xml >> ``` Where you replace `` with the name of the custom endpoint handler you created in the last step. . Save the Lightning component. #### Step 4: Ensure your Community Search component generates the search token server side Now that your custom Recommendations component references your custom code to generate a search token, make sure that your component uses your code to generate the search token server side. . In the Experience cloud site where your custom Lightning component is integrated, access the [**Preview**](https://help.salesforce.com/s/articleView?id=sf.community_designer_preview.htm&type=5) mode. . Access the **Advanced Server-Side Configuration** panel for the component that must use the custom search token: [%header,cols="2"] |=== |With Coveo for Salesforce v3.25+ |With Coveo for Salesforce V3 |At the upper-right corner of the component, click the cogwheel icon, and then select **Advanced Configuration**. |At the upper-left corner of the component, click the cogwheel icon, and then select **Advanced Lightning Configuration**. |=== . In the **Advanced Server-Side Configuration** panel that opens, click the **Bypass above settings to rather generate the search token from a custom Apex class** checkbox to use your Apex class to generate the search token for this component. #### Step 5: Validate the search token Now that you're enforcing configurations in a search token that's generated server side, you should validate that the search token enforces the proper parameters to ensure that your content filtering is secure. See [Ensure that authentication enforces search hub values](https://docs.coveo.com/en/las95231/) for instructions. ### Configure the search token for a Community Search Box component The Recommendations component inherits its search token configuration from the [Community Search](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-community-search-component) component if they share the same [`name`](https://docs.coveo.com/en/2945#name). Therefore, if you specified a search hub value in the [**Search Hub**](https://docs.coveo.com/en/1162#search-hub) option of the [**Advanced Server-Side Configuration**](https://docs.coveo.com/en/1162/) panel of the [Community Search](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-community-search-component) component, you don't need to [create an Apex class to generate a custom search token](https://docs.coveo.com/en/lb1f1380#step-1-create-an-apex-class-to-generate-the-search-token-2), and you can skip to [step 5](https://docs.coveo.com/en/lb1f1380#step-5-validate-the-search-token-2). #### Step 1: Create an Apex class to generate the search token . In Salesforce, access the [**Developer Console**](https://help.salesforce.com/s/articleView?id=sf.code_dev_console.htm&type=5). . In the **Developer Console**, create a new Apex class ( **File** > **New** > **Apex Class**). . In the new Apex class, enter the following template: ```apex public with sharing class { // Annotate the method so that it's accessible from the Lightning component @AuraEnabled public static string getToken() { // Generate a token using the Globals Class provided by Coveo. // See the Globals Class documentation: https://docs.coveo.com/en/1075/coveo-for-salesforce/globals-class Map endpoint = CoveoV2.Globals.getEndpointData(); endpoint.put('token', CoveoV2.Globals.generateSearchToken()); return JSON.serialize(endpoint); } } ``` Where you replace `` with the name you chose for your Apex class. . In the `getToken()` class, enter your code to create the custom search token. Modify that code to at least include the [`searchHub`](https://docs.coveo.com/en/1075#searchhub-optional) in your token generation steps. > **Warning** > > For content security reasons, don't specify a search hub value as a parameter of the `getToken()` class (for example, `getToken(String searchHub`)). **Example** ```apex public with sharing class { // Annotate the method so that it's accessible from the Lightning component @AuraEnabled public static string getToken() { // Generate a token using the Globals Class provided by Coveo. // See the Globals Class documentation: https://docs.coveo.com/en/1075/coveo-for-salesforce/globals-class Map endpoint = CoveoV2.Globals.getEndpointData(); endpoint.put('token', CoveoV2.Globals.generateSearchToken(new Map { 'searchHub' => '' })); return JSON.serialize(endpoint); } } ``` Where you replace `` with the name of the search hub to enforce in the search token. Note that you can specify other parameters in the search token, such as [query filters](https://docs.coveo.com/en/1075#filter-optional) or a [query pipeline](https://docs.coveo.com/en/1075#pipeline-optional). See [Globals Class](https://docs.coveo.com/en/1075/) for instructions. . Save the Apex class. #### Step 2: Create the custom Lightning endpoint handler Now that you've created your Apex class, you must create a custom Lightning endpoint handler to reference your Apex class in your Lightning component. . In the **Developer Console**, [create a Lightning component](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_create_devconsole.htm). . In the component `.cmp`, add the following code: ```xml ``` Where you replace `` with the name of the Apex class you created in previous step. . In the `controller.js` file, enter the following code: ```javascript ({ getTokenAction: function(component, event, helper) { const getTokenAction = component.get('c.getToken'); var getTokenPromise = new Promise(function (resolve, reject) { getTokenAction.setCallback(this, function (response) { if (response.getState() === 'SUCCESS') { var responseData = response.getReturnValue(); resolve(JSON.parse(responseData)); } else if (response.getState() === 'ERROR') { reject(Error('Error generating token')); } }); }); $A.enqueueAction(getTokenAction); return getTokenPromise; } }); ``` . Save the file. Your custom Lightning endpoint handler is now ready. > **Note** > > In our simple example, since there's no difference between the generation and the renewal of a token, we call the same `controller.js` method twice. #### Step 3: Reference the custom Lightning endpoint handler in a Community Search Box component Now that you've created your Apex class to generate a custom search token and a custom Lightning endpoint handler, you must reference the custom Lightning endpoint handler in a Recommendations component. > **Note** > > The following procedure assumes that you've wrapped a default Coveo Lightning component to create a custom Lightning component. > See [Integrate Coveo components in a custom Lightning component for your Experience Cloud site](https://docs.coveo.com/en/1193/) for instructions. . In Salesforce, access an existing custom Lightning component, or [create a new one](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_create_devconsole.htm). . In the component `.cmp`, ensure that your component references the custom Lightning endpoint handler you created in the last step. For example, the component `.cmp` should look like the following: ```xml >> ``` Where you replace `` with the name of the custom endpoint handler you created in the last step. . Save the Lightning component. #### Step 4: Ensure your Community Search Box component generates the search token server side The Recommendations component inherits its configuration from the [Community Search](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-community-search-component) component if they share the same [`name`](https://docs.coveo.com/en/2945#name). Therefore, any change made to the **Advanced Server-Side Configuration** panel, such as activating the [**Bypass above settings to rather generate the search token from a custom Apex class**](https://docs.coveo.com/en/lb1f1380#step-4-ensure-your-community-search-component-generates-the-search-token-server-side) option will be replicated in your Recommendations component's configuration. #### Step 5: Validate the search token Now that you're enforcing configurations in a search token that's generated server side, you should validate that the search token enforces the proper parameters to ensure that your content filtering is secure. To do so, you should inspect the search token that appears in the request headers of a POST request made against a Coveo query suggest endpoint (for example, `search/v2/querySuggest`). See [Ensure that authentication enforces search hub values](https://docs.coveo.com/en/las95231/) for instructions. ### Configure the search token for a Case Deflection component Since the [Coveo for Salesforce (v4.23)](https://docs.coveo.com/en/3236/) release, you can enforce a search hub in the search token that authenticates queries originating from a Coveo Lightning Recommendations component by using the [**Search Hub**](https://docs.coveo.com/en/1162#search-hub) option in the [**Advanced Server-Side Configuration**](https://docs.coveo.com/en/1162/) panel. > **Note** > > Setting a search hub using the **Search Hub** option of the **Advanced Server-Side Configuration** will override any search hub value set when building the page. Doing so prevents you from having to [create an Apex class to generate a custom search token](https://docs.coveo.com/en/lb1f1380#step-1-create-an-apex-class-to-generate-the-search-token-3). If you choose this approach to enforce a search hub in your search token, you can skip to [step 5](https://docs.coveo.com/en/lb1f1380#step-5-validate-the-search-token-3). #### Step 1: Create an Apex class to generate the search token . In Salesforce, access the [**Developer Console**](https://help.salesforce.com/s/articleView?id=sf.code_dev_console.htm&type=5). . In the **Developer Console**, create a new Apex class ( **File** > **New** > **Apex Class**). . In the new Apex class, enter the following template: ```apex public with sharing class { // Annotate the method so that it's accessible from the Lightning component @AuraEnabled public static string getToken() { // Generate a token using the Globals Class provided by Coveo. // See the Globals Class documentation: https://docs.coveo.com/en/1075/coveo-for-salesforce/globals-class Map endpoint = CoveoV2.Globals.getEndpointData(); endpoint.put('token', CoveoV2.Globals.generateSearchToken()); return JSON.serialize(endpoint); } } ``` Where you replace `` with the name you chose for your Apex class. . In the `getToken()` class, enter your code to create the custom search token. Modify that code to at least include the [`searchHub`](https://docs.coveo.com/en/1075#searchhub-optional) in your token generation steps. > **Warning** > > For content security reasons, don't specify a search hub value as a parameter of the `getToken()` class (for example, `getToken(String searchHub`)). **Example** ```apex public with sharing class { // Annotate the method so that it's accessible from the Lightning component @AuraEnabled public static string getToken() { // Generate a token using the Globals Class provided by Coveo. // See the Globals Class documentation: https://docs.coveo.com/en/1075/coveo-for-salesforce/globals-class Map endpoint = CoveoV2.Globals.getEndpointData(); endpoint.put('token', CoveoV2.Globals.generateSearchToken(new Map { 'searchHub' => '' })); return JSON.serialize(endpoint); } } ``` Where you replace `` with the name of the search hub to enforce in the search token. Note that you can specify other parameters in the search token, such as [query filters](https://docs.coveo.com/en/1075#filter-optional) or a [query pipeline](https://docs.coveo.com/en/1075#pipeline-optional). See [Globals Class](https://docs.coveo.com/en/1075/) for instructions. . Save the Apex class. > **Note** > > While you can use the [**Advanced Server-Side Configuration**](https://docs.coveo.com/en/1162/) panel to add configurations to the search token, this panel doesn't let you enforce a specific query pipeline in the search token. #### Step 2: Create the custom Lightning endpoint handler Now that you've created your Apex class, you must create a custom Lightning endpoint handler to reference your Apex class in your Lightning component. . In the **Developer Console**, [create a Lightning component](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_create_devconsole.htm). . In the component `.cmp`, add the following code: ```xml ``` Where you replace `` with the name of the Apex class you created in previous step. . In the `controller.js` file, enter the following code: ```javascript ({ getTokenAction: function(component, event, helper) { const getTokenAction = component.get('c.getToken'); var getTokenPromise = new Promise(function (resolve, reject) { getTokenAction.setCallback(this, function (response) { if (response.getState() === 'SUCCESS') { var responseData = response.getReturnValue(); resolve(JSON.parse(responseData)); } else if (response.getState() === 'ERROR') { reject(Error('Error generating token')); } }); }); $A.enqueueAction(getTokenAction); return getTokenPromise; } }); ``` . Save the file. Your custom Lightning endpoint handler is now ready. > **Note** > > In our simple example, since there's no difference between the generation and the renewal of a token, we call the same `controller.js` method twice. #### Step 3: Reference the custom Lightning endpoint handler in a Case Deflection component Now that you've created your Apex class to generate a custom search token and a custom Lightning endpoint handler, you must reference the custom Lightning endpoint handler in a Recommendations component. > **Note** > > The following procedure assumes that you've wrapped a default Coveo Lightning component to create a custom Lightning component. > See [Integrate Coveo components in a custom Lightning component for your Experience Cloud site](https://docs.coveo.com/en/1193/) for instructions. . In Salesforce, access an existing custom Lightning component, or [create a new one](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_create_devconsole.htm). . In the component `.cmp`, ensure that your component references the custom Lightning endpoint handler you created in the last step. For example, the component `.cmp` should look like the following: ```xml >> ``` Where you replace `` with the name of the custom endpoint handler you created in the last step. . Save the Lightning component. #### Step 4: Ensure your Case Deflection component generates the search token server side Now that your custom Recommendations component references your custom code to generate a search token, make sure that your component uses your code to generate the search token server side. . In the Experience cloud site where your custom Lightning component is integrated, access the [**Preview**](https://help.salesforce.com/s/articleView?id=sf.community_designer_preview.htm&type=5) mode. . Access the **Advanced Server-Side Configuration** panel for the component that must use the custom search token: [%header,cols="2"] |=== |With Coveo for Salesforce v3.25+ |With Coveo for Salesforce V3 |At the upper-right corner of the component, click the cogwheel icon, and then select **Advanced Configuration**. |At the upper-left corner of the component, click the cogwheel icon, and then select **Advanced Lightning Configuration**. |=== . In the **Advanced Server-Side Configuration** panel that opens, click the **Bypass above settings to rather generate the search token from a custom Apex class** checkbox to use your Apex class to generate the search token for this component. #### Step 5: Validate the search token Now that you're enforcing configurations in a search token that's generated server side, you should validate that the search token enforces the proper parameters to ensure that your content filtering is secure. See [Ensure that authentication enforces search hub values](https://docs.coveo.com/en/las95231/) for instructions. ### Configure the search token for a Page View Tracker component The Recommendations component inherits its search token configuration from the [Community Search](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-community-search-component) component if they share the same [`name`](https://docs.coveo.com/en/2945#name). Therefore, if you specified a search hub value in the [**Search Hub**](https://docs.coveo.com/en/1162#search-hub) option of the [**Advanced Server-Side Configuration**](https://docs.coveo.com/en/1162/) panel of the [Community Search](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-community-search-component) component, you don't need to [create an Apex class to generate a custom search token](https://docs.coveo.com/en/lb1f1380#step-1-create-an-apex-class-to-generate-the-search-token-4), and you can skip to [step 4](https://docs.coveo.com/en/lb1f1380#step-4-validate-the-search-token). #### Step 1: Create an Apex class to generate the search token . In Salesforce, access the [**Developer Console**](https://help.salesforce.com/s/articleView?id=sf.code_dev_console.htm&type=5). . In the **Developer Console**, create a new Apex class ( **File** > **New** > **Apex Class**). . In the new Apex class, enter the following template: ```apex public with sharing class { // Annotate the method so that it's accessible from the Lightning component @AuraEnabled public static string getToken() { // Generate a token using the Globals Class provided by Coveo. // See the Globals Class documentation: https://docs.coveo.com/en/1075/coveo-for-salesforce/globals-class Map endpoint = CoveoV2.Globals.getEndpointData(); endpoint.put('token', CoveoV2.Globals.generateSearchToken()); return JSON.serialize(endpoint); } } ``` Where you replace `` with the name you chose for your Apex class. . In the `getToken()` class, enter your code to create the custom search token. Modify that code to at least include the [`searchHub`](https://docs.coveo.com/en/1075#searchhub-optional) in your token generation steps. > **Warning** > > For content security reasons, don't specify a search hub value as a parameter of the `getToken()` class (for example, `getToken(String searchHub`)). **Example** ```apex public with sharing class { // Annotate the method so that it's accessible from the Lightning component @AuraEnabled public static string getToken() { // Generate a token using the Globals Class provided by Coveo. // See the Globals Class documentation: https://docs.coveo.com/en/1075/coveo-for-salesforce/globals-class Map endpoint = CoveoV2.Globals.getEndpointData(); endpoint.put('token', CoveoV2.Globals.generateSearchToken(new Map { 'searchHub' => '' })); return JSON.serialize(endpoint); } } ``` Where you replace `` with the name of the search hub to enforce in the search token. Note that you can specify other parameters in the search token, such as [query filters](https://docs.coveo.com/en/1075#filter-optional) or a [query pipeline](https://docs.coveo.com/en/1075#pipeline-optional). See [Globals Class](https://docs.coveo.com/en/1075/) for instructions. . Save the Apex class. #### Step 2: Configure the component to reference the Apex class Now that you've created your Apex class, you must configure the Page View Tracker component to reference your Apex class. > **Note** > > The following procedure assumes that you have wrapped a default Coveo Lightning component to create a custom Lightning component. > See [Integrate Coveo components in a custom Lightning component for your Experience Cloud site](https://docs.coveo.com/en/1193/) for instructions. . In Salesforce, access an existing custom Page View Tracking Lightning component, or [create a new one](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_create_devconsole.htm). . In the component `.cmp`, ensure that your component references the Apex class you created in the last step. For example, the component `.cmp` should look like the following: ```xml ``` Where you replace `` with the name you chose for your Apex class in previous step. . In the `controller.js` file, enter the following code: ```javascript ({ generateSearchToken: function(component, event, helper) { var deferred = event.getParam('deferred'); var action = component.get('c.getToken'); action.setCallback(this, function(response) { if (response.getState() == 'SUCCESS') { deferred.resolve({ searchToken: response.getReturnValue() }) } }); $A.enqueueAction(action); } }) ``` . Save the component. Your custom Page View Tracker component is now ready. #### Step 3: Ensure your Page View Tracker component generates the search token server side The Recommendations component inherits its configuration from the [Community Search](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-community-search-component) component if they share the same [`name`](https://docs.coveo.com/en/2945#name). Therefore, any change made to the **Advanced Server-Side Configuration** panel, such as activating the [**Bypass above settings to rather generate the search token from a custom Apex class**](https://docs.coveo.com/en/lb1f1380#step-4-ensure-your-community-search-component-generates-the-search-token-server-side) option will be replicated in your Recommendations component's configuration. #### Step 4: Validate the search token Now that you're enforcing configurations in a search token that's generated server side, you should validate that the search token enforces the proper parameters to ensure that your content filtering is secure. To do so, you should inspect the search token that appears in the request headers of a POST request made against the [Coveo Usage Analytics Write API](https://docs.coveo.com/en/18/) (for example, `/rest/ua/v15/analytics/`). See [Ensure that authentication enforces search hub values](https://docs.coveo.com/en/las95231/) for instructions. ### Configure the search token for a Recommendations component The Recommendations component inherits its search token configuration from the [Community Search](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-community-search-component) component if they share the same [`name`](https://docs.coveo.com/en/2945#name). Therefore, if you specified a search hub value in the [**Search Hub**](https://docs.coveo.com/en/1162#search-hub) option of the [**Advanced Server-Side Configuration**](https://docs.coveo.com/en/1162/) panel of the [Community Search](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-community-search-component) component, you don't need to [create an Apex class to generate a custom search token](https://docs.coveo.com/en/lb1f1380#step-1-create-an-apex-class-to-generate-the-search-token-5), and you can skip to [step 5](https://docs.coveo.com/en/lb1f1380#step-5-validate-the-search-token-4). #### Step 1: Create an Apex class to generate the search token . In Salesforce, access the [**Developer Console**](https://help.salesforce.com/s/articleView?id=sf.code_dev_console.htm&type=5). . In the **Developer Console**, create a new Apex class ( **File** > **New** > **Apex Class**). . In the new Apex class, enter the following template: ```apex public with sharing class { // Annotate the method so that it's accessible from the Lightning component @AuraEnabled public static string getToken() { // Generate a token using the Globals Class provided by Coveo. // See the Globals Class documentation: https://docs.coveo.com/en/1075/coveo-for-salesforce/globals-class Map endpoint = CoveoV2.Globals.getEndpointData(); endpoint.put('token', CoveoV2.Globals.generateSearchToken()); return JSON.serialize(endpoint); } } ``` Where you replace `` with the name you chose for your Apex class. . In the `getToken()` class, enter your code to create the custom search token. Modify that code to at least include the [`searchHub`](https://docs.coveo.com/en/1075#searchhub-optional) in your token generation steps. > **Warning** > > For content security reasons, don't specify a search hub value as a parameter of the `getToken()` class (for example, `getToken(String searchHub`)). **Example** ```apex public with sharing class { // Annotate the method so that it's accessible from the Lightning component @AuraEnabled public static string getToken() { // Generate a token using the Globals Class provided by Coveo. // See the Globals Class documentation: https://docs.coveo.com/en/1075/coveo-for-salesforce/globals-class Map endpoint = CoveoV2.Globals.getEndpointData(); endpoint.put('token', CoveoV2.Globals.generateSearchToken(new Map { 'searchHub' => '' })); return JSON.serialize(endpoint); } } ``` Where you replace `` with the name of the search hub to enforce in the search token. Note that you can specify other parameters in the search token, such as [query filters](https://docs.coveo.com/en/1075#filter-optional) or a [query pipeline](https://docs.coveo.com/en/1075#pipeline-optional). See [Globals Class](https://docs.coveo.com/en/1075/) for instructions. . Save the Apex class. #### Step 2: Create the custom Lightning endpoint handler Now that you've created your Apex class, you must create a custom Lightning endpoint handler to reference your Apex class in your Lightning component. . In the **Developer Console**, [create a Lightning component](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_create_devconsole.htm). . In the component `.cmp`, add the following code: ```xml ``` Where you replace `` with the name of the Apex class you created in previous step. . In the `controller.js` file, enter the following code: ```javascript ({ getTokenAction: function(component, event, helper) { const getTokenAction = component.get('c.getToken'); var getTokenPromise = new Promise(function (resolve, reject) { getTokenAction.setCallback(this, function (response) { if (response.getState() === 'SUCCESS') { var responseData = response.getReturnValue(); resolve(JSON.parse(responseData)); } else if (response.getState() === 'ERROR') { reject(Error('Error generating token')); } }); }); $A.enqueueAction(getTokenAction); return getTokenPromise; } }); ``` . Save the file. Your custom Lightning endpoint handler is now ready. > **Note** > > In our simple example, since there's no difference between the generation and the renewal of a token, we call the same `controller.js` method twice. #### Step 3: Reference the custom Lightning endpoint handler in a Recommendations component Now that you've created your Apex class to generate a custom search token and a custom Lightning endpoint handler, you must reference the custom Lightning endpoint handler in a Recommendations component. > **Note** > > The following procedure assumes that you've created a custom Coveo Recommendations component as the default Coveo for Salesforce [Recommendation](https://docs.coveo.com/en/2981/) Lightning Web component doesn't support custom search tokens. . In Salesforce, access an existing custom Lightning component, or [create a new one](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_create_devconsole.htm). . In the component `.cmp`, ensure that your component references the custom Lightning endpoint handler you created in the last step. For example, the component `.cmp` should look like the following: ```xml >>

{!v.title}

``` Where you replace `` with the name of the custom endpoint handler you created in the last step and `` with the name of the Visualforce component that contains the JavaScript configuration for your custom Recommendations component. . Save the Lightning component. #### Step 4: Ensure your Recommendations component generates the search token server side The Recommendations component inherits its configuration from the [Community Search](https://docs.coveo.com/en/lb1f1380#configure-the-search-token-for-a-community-search-component) component if they share the same [`name`](https://docs.coveo.com/en/2945#name). Therefore, any change made to the **Advanced Server-Side Configuration** panel, such as activating the [**Bypass above settings to rather generate the search token from a custom Apex class**](https://docs.coveo.com/en/lb1f1380#step-4-ensure-your-community-search-component-generates-the-search-token-server-side) option will be replicated in your Recommendations component's configuration. #### Step 5: Validate the search token Now that you're enforcing configurations in a search token that's generated server side, you should validate that the search token enforces the proper parameters to ensure that your content filtering is secure. . Access the Salesforce Community where your custom Coveo Lightning Recommendations component is integrated. . Access the [**Preview**](https://help.salesforce.com/s/articleView?id=sf.community_designer_preview.htm&type=5) mode. . Open the **Debug** panel for the custom Coveo Lightning Recommendations component, and then select the **Enable query debug** option. . Search for the **Pipeline** parameter, and verify whether the associated value represents the query pipeline to which queries must be directed. ### Configure the search token for a Quantic search interface #### Step 1: Modify your token provider In most Quantic implementations, you'll have installed and [configured](https://docs.coveo.com/en/1275/) the Coveo for Salesforce package, and you'll have used it to implement your [search token provider](https://docs.coveo.com/en/quantic/latest/usage#search-token-provider). If that's the case, enforcing a target search hub requires minimal configuration of this search token provider. Hardcode the target search hub when calling the [`generateSearchToken`](https://docs.coveo.com/en/1075#generatesearchtoken) function: ```java global with sharing class CoveoTokenProvider implements ITokenProvider { @AuraEnabled(continuation=true cacheable=false) global static String getHeadlessConfiguration() { Map coveoEndpointData = CoveoV2.Globals.getEndpointData(); String searchToken = CoveoV2.Globals.generateSearchToken(new Map { 'searchHub' => '' });   Map headlessConfiguration = new Map(); headlessConfiguration.put('organizationId', (String) coveoEndpointData.get('organization')); headlessConfiguration.put('accessToken', searchToken); return JSON.serialize(headlessConfiguration); } } ``` Where you replace `` by the target search hub value. > **Warning** > > The reason why it's important to hardcode the target search hub value in your backend function (for example, `getHeadlessConfiguration()`) is that you don't want its output to depend on a parameter (for example, `getHeadlessConfiguration(hub)`), because malicious users could leverage that parameter to modify the search hub value set in their token, potentially causing security issues. If you haven't installed the Coveo for Salesforce package, or you have decided to implement your own custom token provider for some other reason, we can't make precise recommendations about what to do, but be sure not to expose an argument that would allow users to modify the search hub value set in the token. > **Note** > > In a Quantic search interface, while search tokens can enforce a search hub in search requests, set your [`QuanticSearchInterface`](https://docs.coveo.com/en/quantic/latest/reference/search-components/search-search-interface/) component `searchHub` parameter to the target search hub value, as this is the parameter used to log [Coveo Analytics data](https://docs.coveo.com/en/259/). > > [.highlight] > ```html ``` > Where you replace `` by the target search hub value. #### Step 2: Validate the search token Now that you're enforcing configurations in a search token that's generated server side, you should validate that the search token enforces the proper parameters to ensure that your content filtering is secure. See [Ensure that authentication enforces search hub values](https://docs.coveo.com/en/las95231/) for instructions.