Leverage case context in your custom Insight Panel

When building a custom Insight Panel, you can optionally leverage case information in your custom context. Custom context helps machine learning models promote content that’s more relevant to the specific case situation.

At a high level, to add case context to your custom Insight Panel, you must retrieve case information with the Salesforce getRecord wire adapter and update your Headless engine state with this information using the target Headless Insight actions. You must also update the context and execute a new search with the updated context when the case information changes.

Tip

For clarity, this article focuses only on the snippets relevant to adding case context to your custom Insight Panel. For the full implementation, see exampleInsightPanel.js in the Quantic project repository.

  1. In your custom Insight Panel JavaScript file, import the required Salesforce modules:

    import {LightningElement, api, wire} from 'lwc'; 1
    import {getRecord} from 'lightning/uiRecordApi'; 2
  2. Define variables you’ll need as well as the case fields that your Insight Panel will leverage:

    triggeredFirstSearch = false; 1
    
    caseRecord; 2
    
    caseFields = [ 3
      'Case.CreatedDate',
      'Case.CreatedBy.Email',
      'Case.CaseNumber',
      'Case.Subject',
      'Case.Description',
    ];
    1 A flag that will be used below to ensure the first search is executed only once.
    2 The current case record data. It will be populated using the getRecord wire below.
    3 The case fields that your Insight Panel will use.
  3. Define functions to check if the watched fields of a case record have been updated and to retrieve the value of a record field:

    watchedFieldsUpdated(newRecordData) {
      return Object.values(this.caseFields)?.reduce((result, field) => {
        const previousValue = this.getFieldValueFromRecord(
          this.caseRecord,
          field
        );
        const newValue = this.getFieldValueFromRecord(newRecordData, field);
        return result || previousValue !== newValue;
      }, false);
    }
    
    getFieldValueFromRecord(record, fieldName) {
      let innerKeys = fieldName.split('.'); 1
      if (!record || !innerKeys.length) return null;
      if (innerKeys[0].toLowerCase() === 'case') {
        innerKeys = innerKeys.slice(1);
      }
      if (innerKeys.length === 1) return record.fields?.[innerKeys[0]]?.value;
      return this.getFieldValueFromRecord(
        record.fields?.[innerKeys[0]]?.value,
        innerKeys.slice(1).join('.')
      );
    }
    1 This function expects the fieldName to be in the following format: Case.Contact.Name.
  4. In your engine initialization function, load the required Headless actions and set the case number in the engine state:

    initialize = (engine) => {
      // ...
    
      this.actions = {
        // ...
        ...this.headless.loadInsightSearchAnalyticsActions(engine), 1
        ...this.headless.loadInsightSearchActions(engine), 2
      };
    
      this.caseNumber =
        this.getFieldValueFromRecord(this.caseRecord, 'Case.CaseNumber') ||
        '1234'; 3
    
      // ...
      this.engine.dispatch(this.actions.setCaseNumber(this.caseNumber)); 4
    };
    1 See loadInsightSearchAnalyticsActions.
    2 See loadInsightSearchActions.
    3 Provide a default case number if the Insight Panel isn’t on a case record page.
    4 Dispatch an action to set the case number in the engine.
  5. Use the getRecord wire adapter to fetch and store the target case record data. This wire adapter is reactive, so also use the watchedFieldsUpdated function just defined to check if the watched fields have changed. If they have, update the case record and execute a search with the updated context, which will yield better results.

    @wire(getRecord, {recordId: '$caseId', fields: '$caseFields'}) 1
    wiredRecord({data, error}) {
      if (data) {
        if (!this.triggeredFirstSearch) {
          this.caseRecord = data;
        } else {
          if (this.watchedFieldsUpdated(data)) {
            this.caseRecord = data;
            this.executeSearchAfterContextChanged();
          }
        }
      } else {
        console.warn('An error occurred while retrieving the record.');
        console.warn(error);
      }
    }
    
    executeSearchAfterContextChanged() {
      this.setupContext(); 2
      this.engine.dispatch(
        this.actions.executeSearch(
          this.actions.logContextChanged(this.caseId, this.caseNumber)
        )
      );
    }
    
    setupContext() {
      const context = { 3
        Case_ID: this.caseId,
        Case_Subject: this.getFieldValueFromRecord(
          this.caseRecord,
          'Case.Subject'
        ),
        Case_Description: this.getFieldValueFromRecord(
          this.caseRecord,
          'Case.Description'
        ),
      };
      this.engine.dispatch(this.actions.setCaseContext(context)); 4
    }
    1 Target only the case record by its ID and the fields you want to monitor.
    2 Update the context, execute a search, and log the context change when case fields are modified.
    3 Create a context object with case information that will be sent with search requests.
    4 Set the case context in the Headless engine so it’s included in all searches.
  6. Update your search execution methods to include case context:

    handleInterfaceLoad = (event) => {
      event.stopPropagation();
      if (!this.triggeredFirstSearch) { 1
        this.triggeredFirstSearch = true;
        this.executeFirstSearch();
      }
    };
    
    executeFirstSearch = () => {
      this.setupContext(); 2
      this.engine.executeFirstSearch();
    };
    1 Only execute the first search once when the interface loads.
    2 Set up case context before executing the initial search.
  7. Validate that the Insight Panel works as expected. When you open a case record page in which you’ve included your custom Insight Panel, it should automatically execute a search request with the case context.

    Quantic Insight Panel request with custom context | Coveo Quantic