Einstein for Service is a powerful set of features to support your agents and satisfy your customers. Using Einstein Bots can greatly reduce the time efforts made to resolve the customers queries. Since Bots are the virtual agents acting towards the customer complaints or grievances, they are trained in a manner to listen to customer's queries and act on some pre-defined rules. If you want to know more on how to use/create Einstein Bots and Chat deployment, visit the Einstein for Service module of Salesforce help documentation or Einstein Bots Developer Cookbook from Salesforce developer documentation.
Implementation:
- Enable the Google reCAPTCHA scripts in Experience Builder.
- Create a custom Pre-Chat Form with Google reCAPTCHA.
- Add the Embedded Service Chat in our Experience Builder.
Now let's focus on step by step process.
Enable the Google reCAPTCHA scripts in Experience Builder
To enable the Google reCAPTCHA in Experience Builder, follow the below steps
- Setup Google Admin console for using reCAPTCHA: First step is to set up the site key and secret key in order to use Google reCAPTCHA. Follow the steps as given here. Copy the site key and we will use this in our next step.
- Login to Sandbox/Production org.
- Go to Digital Experiences → All Sites and open the Builder for next to Site URL.
-
Click on the Gear Icon(⚙) → Advanced → Edit Head Markup
-
Add the following script in the Head Markup and Save. See the CustomEvents create to render the Google reCAPTCHA and track the response back. Make sure you replace the ENTER_YOUR_SITEKEY with the Site Key created in step 1
<!--reCaptcha v2 Checkbox--> <script> var prefix; var verifyCallback = function(token) { var message = prefix + 'success'; window.parent.document.dispatchEvent(new CustomEvent('grecaptchaVerified', {detail: {response: token, message: message}})); }; var expireCallback = function() { var message = prefix + 'expire'; window.parent.document.dispatchEvent(new CustomEvent('grecaptchaExpired', {detail: {message: message}})); }; var errorCallback = function() { var message = prefix + 'error'; window.parent.document.dispatchEvent(new CustomEvent('grecaptchaError', {detail: {message: message}})); }; document.addEventListener('grecaptchaRender', function(e) { prefix = e.detail.prefix; prefix = prefix ? prefix : ''; grecaptcha.render(e.detail.element, { 'sitekey': 'ENTER_YOUR_SITEKEY', 'callback': verifyCallback, 'expired-callback': expireCallback, 'error-callback': errorCallback }); }); document.addEventListener('grecaptchaReset', function() { grecaptcha.reset(); }); </script> <script src='https://www.google.com/recaptcha/api.js?render=explicit' async defer></script>
- Click on the Gear Icon(⚙) → Advanced → Security & Privacy
- Clickjack Protection Level: Allow framing by the same origin only (Recommended)
- Security Level: Relaxed CSP: Permit Access to Inline Scripts and Allowed Hosts
- Add following Trusted Sites for Scripts
- Google: https://www.google.com
- Gstatic: https://www.gstatic.com
-
Go to Setup → CSP Trusted Sites and Add
https://www.google.com as shown below
Create custom Pre-Chat Form
Custom pre-chat form is required to add the Google reCAPTCHA. Detailed explanation for creating custom Pre-Chat Form can be referenced here.
-
Create Static Resource botPreChatFormCSS: First step is to create a static resource. We will use this static resource to left align the error message on our pre-chat form.botPreChatFormCSS.css
botPreChatFormCSS.resource-meta.xml.text-align .slds-form-element__help { text-align: left; }
<?xml version="1.0" encoding="UTF-8"?> <StaticResource xmlns="http://soap.sforce.com/2006/04/metadata"> <cacheControl>Public</cacheControl> <contentType>text/css</contentType> </StaticResource>
-
Create LWC botPreChatForm: Next is to create a lightning web component botPreChatForm which will import the lightningsnapin/basePrechatbotPreChatForm.html
<template> <div if:true={hasFields}> <div class="formContent embeddedServiceSidebarForm"> <div class="slds-var-p-around_medium"> <template for:each={fields} for:item="field"> <div key={field.name} class="slds-var-p-bottom_small"> <span class="slds-form-element__label slds-no-flex slds-float_left"> <span if:true={field.required} class="slds-text-color_destructive slds-var-p-right_xxx-small">*</span> {field.label} </span> <lightning-input name={field.name} type={field.type} label={field.label} variant="label-hidden" class="text-align" value={field.value} required={field.required}> </lightning-input> </div> </template> <div class="recaptcha slds-var-p-top_medium"></div> <div if:true={recaptchaAuthenticationError} class="slds-form-element__label slds-no-flex slds-float_left slds-text-color_destructive">Please Select Recaptcha</div> </div> </div> <div class="buttonWrapper embeddedServiceSidebarForm"> <button type="button" onclick={handleStartChat} class="slds-button slds-button--neutral startButton uiButton--default uiButton embeddedServiceSidebarButton"> <span class="label bBody">{startChatLabel}</span> </button> </div> </div> </template>
botPreChatForm.js: Here we are using document.addEventListener to listen to CustomEvents fired from the script that we included in the Head Markup in our Experience Builder.
botPreChatForm.cssimport BasePrechat from 'lightningsnapin/basePrechat'; import { api, track } from 'lwc'; import startChatLabel from '@salesforce/label/c.StartChat'; import botPreChatFormCSS from "@salesforce/resourceUrl/botPreChatFormCSS"; import { loadStyle } from "lightning/platformResourceLoader"; export default class BotPreChatForm extends BasePrechat { @api prechatFields; @track fields; @track namelist; startChatLabel; recaptchaAuthenticated; recaptchaAuthenticationError; constructor() { super(); document.addEventListener("grecaptchaVerified", (evt) => { this.listenForGrecaptchaVerified(evt) }); document.addEventListener("grecaptchaExpired", (evt) => { this.listenForGrecaptchaExpired(evt) }); document.addEventListener("grecaptchaError", (evt) => { this.listenForGrecaptchaError(evt) }); } //Set the button label and prepare the prechat fields to be shown in the form. connectedCallback() { this.startChatLabel = startChatLabel; this.recaptchaAuthenticated = false; this.recaptchaAuthenticationError = false; if (this.prechatFields) { this.fields = this.prechatFields.map(field => { field = JSON.parse(JSON.stringify(field)); field.type = field.type.replace('input', ''); const { label, name, value, required, maxLength, type } = field; return { label, name, value, required, maxLength, type }; }); this.namelist = this.fields.map(field => field.name); } } disconnectedCallback() { this.removeEventListeners(); } //Focus on the first input after this component renders. renderedCallback() { Promise.all([ loadStyle(this, botPreChatFormCSS), ]).then(() => { }); if(!this.inputFocused) { let lightningInputElement = this.template.querySelector("lightning-input"); if (lightningInputElement) { lightningInputElement.focus(); this.inputFocused = true; }; } if (!this.recaptchaRendered) { let divElement = this.template.querySelector('.recaptcha'); let payload = { element: divElement, prefix: 'bot' }; document.dispatchEvent(new CustomEvent("grecaptchaRender", { "detail": payload })); this.recaptchaRendered = true; } } removeEventListeners() { document.removeEventListener("grecaptchaVerified", () => { }); document.removeEventListener("grecaptchaExpired", () => { }); document.removeEventListener("grecaptchaError", () => { }); } listenForGrecaptchaVerified(event) { this.setRecaptchaAuthentication(event.detail.message); this.recaptchaAuthenticated = true; } listenForGrecaptchaExpired(event) { this.setRecaptchaAuthentication(event.detail.message); } listenForGrecaptchaError(event) { this.setRecaptchaAuthentication(event.detail.message); } setRecaptchaAuthentication(message) { this.recaptchaAuthenticated = false; this.recaptchaAuthenticationError = true; if (message && message.toUpperCase() === 'BOTSUCCESS') { this.recaptchaAuthenticated = true; this.recaptchaAuthenticationError = false; } } // getter property to render the prechat fields get hasFields() { return this.fields && this.fields.length > 0; } //On clicking the 'Start Chatting' button, send a chat request. handleStartChat(event) { event.preventDefault(); let inputElements = this.template.querySelectorAll("lightning-input"); this.recaptchaAuthenticationError = false; if (!this.recaptchaAuthenticated) { this.recaptchaAuthenticationError = true; } if (inputElements && this.checkInputValidity(inputElements) && this.recaptchaAuthenticated) { inputElements.forEach(input => { this.fields[this.namelist.indexOf(input.name)].value = input.value; }); if (this.validateFields(this.fields).valid) { this.removeEventListeners(); this.startChat(this.fields); } else { // Error handling if fields do not pass validation. } } } checkInputValidity(inputElements) { const allValid = [...inputElements].reduce( (validSoFar, inputCmp) => { inputCmp.reportValidity(); return validSoFar && inputCmp.checkValidity(); }, true); return allValid; } }
botPreChatForm.js-meta.xml:host { display: flex; flex-direction: column; } lightning-button { padding-top: 1em; } .embeddedServiceSidebarForm.formContent { width: 100%; height: 350px; overflow-y: auto; position: relative; background-color: var(--lwc-esColorBackgroundInverse,#fff); border-radius: 0 0 8px 8px; } .embeddedServiceSidebarForm.buttonWrapper { text-align: center; padding: 30px 24px 24px; margin: 0; width: 100%; position: absolute; box-sizing: border-box; bottom: 0; background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) calc(100% - 77px), rgba(255, 255, 255, 1) 100%); } .embeddedServiceSidebarButton { position: relative; border: none; background: var(--lwc-colorBrand,#2574A9); text-shadow: none; box-shadow: none; border-radius: 4px; transition: background .4s ease; color: var(--lwc-colorTextInverse,#FFFFFF); font-size: var(--lwc-esFontSizeMedium,1em); font-weight: var(--lwc-fontWeightRegular,400); font-family: var(--lwc-fontFamily,Lato),sans-serif; width: 100%; margin: 0; height: 44px; }
<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>52.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightningSnapin__PreChat</target> </targets> </LightningComponentBundle>
- Override Standard Pre-Chat Form: Now as we have created our custom pre-chat form, Click here to know how to override the standard pre-chat form from my previous blog.
Add the Embedded Service Chat in our Experience Builder
Lastly we need to add the Einstein Bot to our public facing site.
- Login to Sandbox/Production org.
- Go to Digital Experiences → All Sites and open the Builder for next to Site URL.
- Go to Components → Embedded Service Chat and drag-drop to builder canvas.
- Finally Publish your community.
DEMO:
- Covers the validation for the pre-chat fields.
- Doesn't allow to start the chat until we verify the Google reCAPTCHA. While verifying the Google reCAPTCHA, we may sometime be forced to solve the challenge like the image selection or audio CAPTCHA.
- Once all verified successfully then only we will be allowed to start the chat.
YouTube:
If you like this blog content and find inciteful, please comment and let me know.
Validation for email is missing
ReplyDeleteThanks for taking the time to discuss this, I feel strongly about it and love learning more on this topic.
ReplyDeleteanti captcha key
Hi Thanks for great post!
ReplyDeleteI have implemented same thing working fine now the issue is recaptcha image challenge comes inside chatbox outside like you shown above. could you help?
This comment has been removed by the author.
ReplyDeleteHi Thanks for great post!
ReplyDeleteI have implemented same thing working fine now the issue is recaptcha image challenge comes inside chatbox not outside like you shown above. could you help? what I am missing.
Thanks and I have a swell supply: How To Become A House Renovation house renovation companies
ReplyDelete