Enhanced Chat 30 min
Quick Setup: Generate Embed Snippet
Select an agent, enter your website domains, and generate the JavaScript embed snippet. Domains are whitelisted automatically.
Outcome
A working Enhanced Chat widget on your external website that routes conversations to your Agentforce Service Agent. No Experience Cloud site required.
When complete, you'll have:
- A MessagingChannel (type
EmbeddedMessaging) routed to your Agentforce agent - An EmbeddedServiceConfig (deployment) configured for external web delivery
- A JavaScript embed snippet added to your website's HTML
- Verified end-to-end message flow from the chat widget to your agent and back
This guide deploys Enhanced Chat on any external website using a JavaScript snippet. If you want to deploy on an Experience Cloud site instead, see Experience Site which places the widget as a Lightning component inside Experience Builder.
Architecture
When a visitor clicks the chat bubble on your website, the message flows through the following chain:
Click a node to jump to its configuration step.
The key metadata components are:
- MessagingChannel:
messagingChannelType = EmbeddedMessaging, withsessionHandlerType = AgentforceServiceAgentandsessionHandlerAsapointing to the BotDefinition DeveloperName - EmbeddedServiceConfig:
deploymentFeature = EmbeddedMessaging,deploymentType = Web,clientVersion = WebV2 - ServiceChannel:
sfdc_livemessage(auto-created with Messaging) - Queue: SObject type
MessagingSessionfor fallback routing
The JavaScript snippet loads asynchronously, connects to your org's SCRT2 endpoint, and renders a chat bubble in the bottom-right corner of the page. Both authenticated and guest (unauthenticated) users are supported.
No Digital Engagement license needed. Enhanced Chat is included with Service Cloud. Unlike WhatsApp, SMS, or other third-party channels, no additional add-on license is required.
Configure Your Variables
Update these variables with your values and they will be substituted in the code blocks below.
Implementation Steps
1. Verify Your Starting Point
Confirm your agent exists, your org is authenticated, and Messaging is enabled.
Confirm your Service Agent exists and is active
Before building the routing chain, verify your Agentforce Service Agent is deployed and active in the target org.
sf data query \
--target-org <your-org-alias> \
--query "SELECT Id, DeveloperName, MasterLabel, AgentType FROM BotDefinition WHERE DeveloperName='Reservation_Agent' AND IsActive=true"
Verify the agent is active:
Expected result: One record returned with a valid Id.
If no record is returned, activate your agent in Agent Builder before proceeding.
Authenticate and verify org access
Ensure you have admin access to the target org and the CLI is connected.
sf org login web --alias <your-org-alias> --instance-url https://login.salesforce.com
sf org display --target-org <your-org-alias> --verbose
Verify org access:
Expected result: Org display shows your username and instance URL without errors.
2. Enable Messaging
Messaging and Omni-Channel must be enabled at the org level before any messaging channels can be created.
# Deploy Omni-Channel settings via metadata
mkdir -p /tmp/sf-messaging-setup/force-app/main/default/settings
cat > /tmp/sf-messaging-setup/sfdx-project.json << 'EOF'
{
"packageDirectories": [{ "path": "force-app", "default": true }],
"namespace": "",
"sourceApiVersion": "64.0"
}
EOF
cat > /tmp/sf-messaging-setup/force-app/main/default/settings/OmniChannel.settings-meta.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<OmniChannelSettings xmlns="http://soap.sforce.com/2006/04/metadata">
<enableOmniChannel>true</enableOmniChannel>
</OmniChannelSettings>
EOF
sf project deploy start \
--target-org <your-org-alias> \
--source-dir /tmp/sf-messaging-setup/force-app/main/default/settings/OmniChannel.settings-meta.xml
Verify messaging is enabled:
Expected result: Messaging Settings page loads without errors and shows channel management options. Omni-Channel Settings shows "Omni-Channel is enabled."
3. Create the Messaging Channel
Create an EmbeddedMessaging type MessagingChannel and route it to your Agentforce Service Agent. This also creates the required Queue with MessagingSession as the supported SObject.
# Step 3a: Create a Queue for MessagingSession fallback routing
sf data query \
--target-org <your-org-alias> \
--query "SELECT Id, DeveloperName FROM Group WHERE Type='Queue' AND DeveloperName='AgentforceChannel_Queue' LIMIT 1"
# If no queue exists, create one:
sf data create record \
--target-org <your-org-alias> \
--sobject Group \
--values "Name='AgentforceChannel Queue' DeveloperName='AgentforceChannel_Queue' Type='Queue'"
# Get the Queue ID from the output, then map it to MessagingSession:
sf data create record \
--target-org <your-org-alias> \
--sobject QueueSobject \
--values "QueueId='QUEUE_ID_FROM_ABOVE' SobjectType='MessagingSession'"
# Step 3b: Get the BotDefinition Id for your agent
sf data query \
--target-org <your-org-alias> \
--query "SELECT Id, DeveloperName FROM BotDefinition WHERE DeveloperName='Reservation_Agent'"
# Step 3c: Create the MessagingChannel with direct agent routing
# Note: Use the Python/REST approach below for creating MessagingChannel,
# as sf data create record does not support all required fields.
Verify channel configuration:
Query the channel to confirm it is active and routed to your agent:
sf data query --target-org <your-org-alias> --query "SELECT Id, DeveloperName, IsActive, MessageType, SessionHandlerId FROM MessagingChannel WHERE DeveloperName='AgentforceChannel'"
Expected result: One record returned with IsActive = true and SessionHandlerId matching your BotDefinition Id.
4. Create an Embedded Service Deployment
The EmbeddedServiceConfig is the deployment wrapper that connects the MessagingChannel to the JavaScript snippet. It defines the deployment type as Web and links to your channel.
# EmbeddedServiceConfig is a Tooling API object.
# Create it via REST/Tooling API (see REST API tab) or Setup UI (see Browser tab).
# SF CLI does not have a direct command for creating EmbeddedServiceConfig.
After creating the EmbeddedServiceConfig, you must publish it before the snippet will work. In the Setup UI, navigate to the deployment record and click Publish. Via API, publishing may require a separate step depending on your org version.
Verify deployment exists:
Confirm the deployment exists:
sf data query --target-org <your-org-alias> --use-tooling-api --query "SELECT Id, DeveloperName, MasterLabel, DeploymentType, DeploymentFeature FROM EmbeddedServiceConfig WHERE DeveloperName='AgentforceDeployment'"
Expected result: One record returned with DeploymentFeature = EmbeddedMessaging and DeploymentType = Web.
5. Generate the Embed Snippet
After publishing the deployment, Salesforce generates a JavaScript snippet you can paste into any website. The snippet includes your org-specific SCRT2 URL, site endpoint, and deployment name.
# The embed snippet is available in Setup UI after publishing.
# Retrieve org details to construct the snippet manually:
sf org display --target-org <your-org-alias> --verbose --json
# The snippet URLs follow this pattern:
# SCRT2 URL: https://<your-domain>.my.salesforce-scrt.com
# Site Endpoint: https://<your-domain>.my.site.com (or your custom domain)
# ESW file: https://<your-domain>.my.salesforce-scrt.com/assets/js/bootstrap.min.js
The generated snippet follows this structure. Replace the placeholder values with your org-specific values:
<script type="text/javascript">
function initEmbeddedMessaging() {
try {
embeddedservice_bootstrap.settings.language = "en_US";
embeddedservice_bootstrap.init(
"YOUR_ORG_ID",
"AgentforceDeployment",
"https://YOUR_DOMAIN.my.site.com/ESWDeploymentName",
{
scrt2URL: "https://YOUR_DOMAIN.my.salesforce-scrt.com",
}
);
} catch (err) {
console.error("Error loading Enhanced Chat: ", err);
}
}
</script>
<script
type="text/javascript"
src="https://YOUR_DOMAIN.my.salesforce-scrt.com/assets/js/bootstrap.min.js"
onload="initEmbeddedMessaging()"
></script>
The exact snippet is auto-generated by Salesforce and includes your org-specific values. Always use the snippet from Setup rather than constructing it manually, since the URLs and parameters vary by org and environment.
6. Add the Snippet to Your Website
Paste the JavaScript snippet into your website's HTML. The snippet should be placed just before the closing </body> tag for optimal loading.
# This step is performed on your external website, not in Salesforce.
# Example: Add to an HTML file
cat >> /path/to/your/website/index.html << 'SNIPPET'
<!-- Salesforce Enhanced Chat Widget -->
<script type='text/javascript'>
function initEmbeddedMessaging() {
try {
embeddedservice_bootstrap.settings.language = 'en_US';
embeddedservice_bootstrap.init(
'YOUR_ORG_ID',
'YOUR_DEPLOYMENT_NAME',
'https://YOUR_DOMAIN.my.site.com/ESWDeploymentName',
{
scrt2URL: 'https://YOUR_DOMAIN.my.salesforce-scrt.com'
}
);
} catch (err) {
console.error('Error loading Enhanced Chat: ', err);
}
}
</script>
<script
type='text/javascript'
src='https://YOUR_DOMAIN.my.salesforce-scrt.com/assets/js/bootstrap.min.js'
onload='initEmbeddedMessaging()'>
</script>
SNIPPET
The domain serving your website must be added to the CORS allowlist in Salesforce Setup. Navigate to Setup -> CORS -> New, and add your website's origin (e.g., https://www.example.com). Without this, the chat widget will fail to connect.
For development and testing, you can use a simple local HTML file served via python3 -m http.server 8000 and add http://localhost:8000 to your CORS allowlist.
7. Test and Verify
Open your website, click the chat widget, and send a test message to confirm the full routing chain works.
# After sending a test message through the chat widget,
# verify a MessagingSession was created:
sf data query \
--target-org <your-org-alias> \
--query "SELECT Id, Status, AgentType, OwnerId, CreatedDate FROM MessagingSession ORDER BY CreatedDate DESC LIMIT 5"
# Verify AgentWork was created (shows the agent handled the conversation):
sf data query \
--target-org <your-org-alias> \
--query "SELECT Id, WorkItemId, BotId, RoutingType, CreatedDate FROM AgentWork ORDER BY CreatedDate DESC LIMIT 5"
Verify the chat widget works:
Expected result: The chat bubble appears on your website. Clicking it opens a chat window. Sending a message produces a response from your Agentforce agent. A MessagingSession record exists in Salesforce with AgentType indicating bot handling.
Customization
Branding
You can customize the chat widget's appearance to match your website's design:
# Branding is configured on the EmbeddedServiceConfig via Setup UI
# or by updating the deployment metadata. Key options:
# - Primary color, secondary color, contrast colors
# - Chat window header text
# - Avatar image
# - Font family
Pre-Chat Forms
Pre-chat forms collect customer information (name, email, case subject) before starting the conversation. This data is available to your agent via the session context.
# Pre-chat configuration is part of the EmbeddedServiceConfig metadata.
# Configure via Setup UI (see Browser tab).
Troubleshooting
Chat bubble does not appear on the website
Check these common causes in order:
- Snippet not loading: Open browser DevTools (F12) and check the Console for JavaScript errors. Verify the
bootstrap.min.jsURL is correct and accessible. - CORS error: Check the Console for CORS-related errors. Add your website's origin to Setup -> CORS -> Allowed Origins List.
- Deployment not published: Navigate to Setup -> Embedded Service Deployments and verify the deployment status shows as Published.
- Incorrect SCRT2 URL: Verify the
scrt2URLin your snippet matches your org's domain pattern:https://<your-domain>.my.salesforce-scrt.com.
Chat bubble appears but messages fail to send
This usually indicates a routing issue:
- Verify the MessagingChannel is active: query
SELECT IsActive FROM MessagingChannel WHERE DeveloperName='{{CHANNEL_NAME}}'. - Verify
SessionHandlerIdis set on the channel and points to a valid BotDefinition. - Check that the fallback queue exists and has
MessagingSessionas a supported SObject type. - Ensure your Agentforce Service Agent is active and published.
Agent does not respond to messages
The chat connects but the agent is silent:
- Check the agent is active:
SELECT Id, IsActive FROM BotDefinition WHERE DeveloperName='{{AGENT_NAME}}'. - Verify a BotVersion is active:
SELECT Id, Status FROM BotVersion WHERE BotDefinition.DeveloperName='{{AGENT_NAME}}' AND Status='Active'. - Check
AgentWorkrecords to see if the conversation was assigned:SELECT Id, WorkItemId, BotId FROM AgentWork ORDER BY CreatedDate DESC LIMIT 5. - Review the agent's subagent instructions to ensure it can handle the test utterance.
Widget loads but shows 'Service is not available'
The deployment is published but the runtime cannot connect:
- Verify Messaging is enabled: Setup -> Messaging Settings should show Messaging as active.
- Check that the MessagingChannel
IsActive = true. - Ensure Omni-Channel is enabled: Setup -> Omni-Channel Settings.
- If the org was recently provisioned, wait 5-10 minutes for SCRT2 infrastructure to propagate.
Enhanced Chat v1 vs v2
Salesforce offers two versions of the Enhanced Chat widget:
| Feature | Enhanced Chat v1 (Standard) | Enhanced Chat v2 (Custom LWC) |
|---|---|---|
| Setup | Standard configuration in Setup | Requires custom Lightning Web Components |
| Customization | Branding colors, fonts, pre-chat forms | Full custom UI via LWC (custom message types, interactive elements) |
| Use case | Standard chat with agent responses | Rich interactive experiences (carousels, forms, custom cards) |
| Requirement | Service Cloud | Service Cloud + custom LWC development |
This guide covers Enhanced Chat v1 (standard). For Enhanced Chat v2 with custom Lightning types, see the Salesforce Web Developer Guide and the In-App Developer Guide.
Enhanced Chat also supports mobile apps via iOS and Android SDKs. The same MessagingChannel and EmbeddedServiceConfig are reused; only the client-side integration differs. See the Salesforce Mobile SDK documentation for details.
Definition of Done
Definition of Done:
- MessagingChannel is active with
MessageType = EmbeddedMessagingandSessionHandlerIdpointing to your BotDefinition. - EmbeddedServiceConfig exists with
DeploymentFeature = EmbeddedMessagingandDeploymentType = Web, and is published. - JavaScript snippet is added to your external website's HTML.
- Your website's origin is added to the Salesforce CORS allowlist.
- Chat bubble appears on the website and opens a chat window on click.
- Sending a test message produces a response from the Agentforce agent.
MessagingSessionandAgentWorkrecords confirm the routing path works.