Configuring external search results in Recommended ActionsSTEPS TO CONFIGURE EXTERNAL CONTENT FOR SEARCH IN RECOMMENDED ACTIONS:Prerequisites:App version:Common-Guidances: version 7.0.1 or higher.Recommended Actions: 34.0.1 or higher.Roles Required: sn_nb_action.next_best_action_author role and access to UIB create/edit required(ui_builder_admin).Use case:Surfacing SharePoint/Confluence results that must open in a browser tab instead of a platform record.Steps:1. Open the guidance(ga_guidance) “Default guidance for search results” and click on “Edit preview in UI Builder.” This will open the UIB page.2. Click on the hamburger icon, duplicate the variant, and give a unique name to the page such as “Guidance for external search results.” 3. Create a new guidance record similar to the “Default guidance for search results.” Give it a name and set the same guidance inputs. - All guidance inputs can be of type String if a JSON type is not available example for the search result preview fields input.- Also, create another input called “Search URL” of type String, since for external sources this URL will be used to open the link. 4. Map the newly created guidance to the duplicated variant. To do this, go to the Guidance Component table (ga_guidance_component) and create a new record with the guidance reference. - Add the preview macroponent and preview screen references (search using the variant name created earlier, “Guidance for external search results”). If you don’t see the fields, add them through the form layout. 5. After saving the record, open the new guidance. You should now see the “Edit preview in UI Builder” button. Click on it to open the new UIB page. 6. Make the following changes on this UIB page to handle external URLs: - Create a new client state parameter “searchUrl” of type String.- Modify the “Handle default guidance preview details” script. Ensure that the correct guidance input names are added under action inputs.These should match the guidance input column names created (usually prefixed with u_). - Add the “Search URL” under action inputs and set the state at the end of the script.Refer to the script below: //Example of the modified script 'Handle default guidance preview details' - Please ensure guidance input names matches and change the client script accordingly async function handler({ api, event, helpers, imports }) { const customGuidanceHelper = imports["sn_guidances.AttachArticleGuidanceHelper"](...arguments); const { customExpProps } = event.payload; const { actionStateValue, recommendationHint, icon, actionInputs } = customExpProps; let { u_search_result_table, u_search_result_sysid, u_search_result_title, u_search_result_preview_fields, u_search_teaser_text, u_search_url } = actionInputs; const statusProps = await customGuidanceHelper.getStatusProps(actionStateValue, recommendationHint, '', icon); u_search_result_table = u_search_result_table && u_search_result_table.trim(); u_search_result_sysid = u_search_result_sysid && u_search_result_sysid.trim(); u_search_result_title = u_search_result_title && u_search_result_title.trim(); const searchTeaserText = u_search_teaser_text && u_search_teaser_text.trim(); /* Parsing the string to get JSON object if someone fills the JSON manually as a string in the Guidance Input. */ if (typeof u_search_result_preview_fields === 'string') { try { u_search_result_preview_fields = JSON.parse(u_search_result_preview_fields); } catch (error) { console.error("Failed to parse JSON for Search result preview fields: " + error.message); u_search_result_preview_fields = {}; } } /* Parsing string as HTML using DOMPraser, replacing special html code with appropriate character value. */ const guidanceHeading = customGuidanceHelper.getTrimmedValue(u_search_result_title); const cardHeading = { label: guidanceHeading }; /* Fields to exclude */ const excluded_fields = ['sys_id', 'table', 'Table']; /* Fields to prioritize */ const most_priority_fields = ['Number', 'Name']; let prioritizedFields = [], otherFields = []; if ( u_search_result_preview_fields && Array.isArray(u_search_result_preview_fields.previewFields) && u_search_result_preview_fields.previewFields.length > 0 && u_search_result_preview_fields.previewFields.every(field => 'label' in field && 'displayValue' in field) ) { // Create prioritized fields in the sequence of most_priority_fields (keep Number, Name in front) prioritizedFields = most_priority_fields .map(fieldLabel => u_search_result_preview_fields.previewFields.find(field => field.label === fieldLabel)) .filter(field => field && !excluded_fields.includes(field.label) && (field.displayValue && field.displayValue.trim()) !== guidanceHeading // Exclude if displayValue matches heading ) .map(field => ({ label: field.label, value: field.displayValue && field.displayValue.trim() })); // Create other fields, excluding `excluded_fields`, prioritized fields, and fields matching `heading` otherFields = u_search_result_preview_fields.previewFields .filter(field => !excluded_fields.includes(field.label) && !most_priority_fields.includes(field.label) && (field.displayValue && field.displayValue.trim()) !== guidanceHeading // Exclude if displayValue matches heading ) .map(field => ({ label: field.label, value: field.displayValue && field.displayValue.trim() })); } /* Combine prioritized fields and other fields */ const fieldsToDisplay = [...prioritizedFields, ...otherFields]; /* Setting the client states */ api.setState('customExpProps', customExpProps); api.setState('heading', ({ currentValue }) => ({ ...currentValue, ...cardHeading })); api.setState('fieldsToDisplay', fieldsToDisplay); api.setState('statusProps', statusProps); api.setState('searchTeaserText', searchTeaserText); api.setState('recordTable', u_search_result_table); api.setState('recordSysId', u_search_result_sysid); api.setState('actionStateValue', actionStateValue); api.setState('searchUrl', u_search_url); } - Modify the “Handle opening guidance record” script to open the URL in a new browser tab //Example of the modified script 'Handle opening guidance record'. ensure url is mapped to the right client state parameter created function handler({ api, event, helpers, imports }) { const recordTable = api.state.recordTable; const recordSysId = api.state.recordSysId; if (recordTable === 'kb_knowledge') { openRecord('kb_view', recordTable, recordSysId); } else { openRecord('record', recordTable, recordSysId); } function openRecord(navigator, table, sysId) { helpers.navigate.to(undefined, undefined, {}, false, false, null, { url: api.state.searchUrl // opens the new searchUrl }); } } 7. Finally, ensure the new guidance is mapped in the search result configuration.- Recommended Actions > Context- Go to Search result mapping related list- Wherever SharePoint or Confluence sources are used, update them to use the newly created guidance. Map the inputs using the pill picker, and for the Search URL input, you should see the search result URL available for mapping.(sn_nb_action_search_result_mapping) 8. After completing these steps, the external search results should open correctly in a new browser tab.Trouble shoot:If mapping external results and clicking open Record action on search results shows the "Record not found" error, follow the steps in this KB article to configure guidance for external search results.