SfSkills Domains Docs GitHub

Home / admin / messaging-and-chat-setup

messaging-and-chat-setup

Configure Messaging for In-App and Web (MIAW) channels in Service Cloud: Messaging Channel, Embedded Service Deployment, CORS/CSP Trusted Sites, pre-chat fields, session routing by Queue or Omni-Channel Flow, Status-Based capacity, Live Agent migration.

Open the skill folder on GitHub


Messaging and Chat Setup

This skill activates when a practitioner needs to set up or troubleshoot real-time or asynchronous chat channels in Salesforce Service Cloud using Messaging for In-App and Web (MIAW). It covers the full administrative configuration path from channel creation through Omni-Channel routing to agent capacity management.


Before Starting

Gather this context before working on anything in this domain:


Questions to Ask Before Configuring

Ask these before opening Setup. Each one maps to a behaviour in references/gotchas.md; an agent that skips them produces a channel that deploys cleanly and serves nobody.

AskWhy it mattersWhat a good answer adds
"Which channel are we actually building — web/in-app chat, SMS, WhatsApp, or a partner channel?"messagingChannelType lists WhatsApp, Facebook, Text and more, but the guide says third-party channels don't use this metadata type (gotchas #6)The right value (EmbeddedMessaging or Custom) — or the finding that this skill is the wrong path
"Which Experience site or website does the widget live on, and does it exist yet?"EmbeddedServiceConfig.site is Required; there is no site-less web deploymentThe site's developer name and its place ahead of this work in the deploy order
"Which queue owns a session that the routing flow can't place, and who is in it?"sessionHandlerQueue is Required and doubles as the flow's fallback; the failure is a fallback nobody can accept from (gotchas #5)A named queue with a routing configuration and at least one available agent
"List every origin the widget loads from — production, staging, UAT, preview — with scheme and port."A non-allowlisted origin gets HTTP 404, not a CORS error, so the symptom lies about the cause (gotchas #1)The exact CORS and CSP entry list, and whether one wildcard pattern covers them
"Which resources does the host page need to load — scripts, frames, images, fonts, styles?"Every CSP directive defaults to false, and a directive-free trusted site grants nothing (gotchas #8)The isApplicableTo*Src set, chosen rather than defaulted
"Who links the conversation to a Contact, and on which record?"MessagingSession.EndUserContactId is read-only; the writeable field is on MessagingEndUser (gotchas #3)An owner and a target object for the identity automation, before agents see anonymous chats
"What does the customer hear when we're closed, when they go quiet, and when the agent leaves?"Each is a separate automatedResponses type; responseTimeoutInMins is bounded at 5–60The auto-response set and languages, instead of silence on three real paths

What a proper configuration adds over just creating a channel: the widget loads on every environment rather than only production, every session reaches a queue that can accept it, conversations attach to a person, and the deployment survives a wildcard retrieve instead of vanishing from the change set.


Core Concepts

MIAW vs Legacy Live Agent / Snap-ins

Messaging for In-App and Web (MIAW) is the current Salesforce platform for real-time and asynchronous web chat. It supersedes both legacy Live Agent (classic) and the Snap-ins SDK. Key differences:

Messaging Channel and Embedded Service Deployment

Every MIAW implementation requires two linked records:

  1. Messaging Channel (Setup > Messaging > Messaging Channels) — defines the channel name, routing configuration, pre-chat fields, and off-hours behavior. The API name of this record is used in the deployment snippet.
  2. Embedded Service Deployment (Setup > Embedded Service Deployments) — generates the JavaScript snippet deployed to the website. The deployment references the Messaging Channel through embeddedServiceMessagingChannel/messagingChannel, and names the Experience site through the Required site field. UNVERIFIED (2026-09-05): the Metadata API guide shows one channel reference per deployment but does not state whether several deployments may share one channel; confirm in the org before designing a shared-channel, multi-branding layout. Each host origin needs its own CORS and CSP registration regardless.

Pre-chat is split across the two records: the parameters are declared on the Messaging Channel (standardParameters, limited to Email, FirstName, LastName and Subject; customParameters for everything else), while the form that renders them — embeddedServiceForms and its fields — lives on the Embedded Service Deployment. A form field's messagingChannelParameterType must match the parameter kind it points at. Collecting an email does not link a Contact; that identity write goes to MessagingEndUser.ContactId, not to the session.

CORS and CSP Trusted Sites

The chat widget loads cross-origin resources from Salesforce CDN endpoints. Two separate allow-lists must be updated for every domain where the widget is embedded:

Both entries carry a scheme and hostname (e.g. https://www.example.com). Both accept a wildcard, with different rules: CorsWhitelistOrigin.urlPattern supports * only in front of a second-level domain (https://*.example.com is valid, https://support.*.com is not), and CspTrustedSite.endpointUrl accepts *.example.com. The CSP record additionally grants nothing until at least one directive is set — see references/gotchas.md #8. Forgetting one of the pair, or registering production and missing preview/staging hosts, is the most common cause of widget failures outside production.

Omni-Channel Routing for Messaging Sessions

MIAW sessions route through Omni-Channel, not through a separate chat routing engine. Two routing approaches are available:

A fallback queue must always be configured on the Messaging Channel. If the Omni-Channel Flow fails or no agents are available, sessions fall to the fallback queue rather than dropping silently.

Status-Based Capacity Model

Salesforce recommends Status-Based capacity for MIAW orgs. Under this model:

The older Tab-Based model releases capacity when the console work tab closes, which is unreliable for asynchronous messaging that outlives a tab. There are two switches: the org-level gate OmniChannelSettings.enableOmniStatusCapModel, and — from API version 65.0 — a per-channel ServiceChannel.capacityModel of STATUS_BASED or TAB_BASED. Both must agree. Capacity numbers themselves live on Presence Configurations, which belong to admin/omni-channel-routing-setup.


Common Patterns

Pattern: Greenfield MIAW Deployment with Queue Routing

When to use: New orgs or orgs migrating from legacy Live Agent that need a straightforward chat channel without complex conditional routing.

How it works:

  1. Enable Messaging for In-App and Web in Messaging Settings.
  2. Create a Messaging Channel: masterLabel, messagingChannelType EmbeddedMessaging, sessionHandlerType Queue, and sessionHandlerQueue naming the queue. Add the automatedResponses set for the initial and agent-end paths.
  3. Declare pre-chat parameters on the channel — standardParameters for First Name, Last Name and Subject, customParameters for anything else.
  4. Create the Embedded Service Deployment: site, deploymentFeature EmbeddedMessaging, deploymentType Web, the full embeddedServiceMessagingChannel block, the embeddedServiceForms pre-chat form matching step 3, and branding naming a BrandingSet.
  5. Add CORS and CSP Trusted Site entries for the target domain.
  6. Copy the deployment code snippet and paste into the website <head> or tag manager.
  7. Test in a sandbox using a second browser session as the customer.

Why not the alternative: Skipping the Messaging Channel / Embedded Service Deployment separation and attempting to reuse a legacy Live Agent Chat deployment produces a deployment that routes to LiveChatTranscript, not MessagingSession, breaking all MIAW-native features.

Pattern: Flow-Based Routing with Business-Hours Fallback

When to use: Orgs with multiple agent skill groups, time-zone-aware routing, or off-hours deflection to a bot or knowledge article.

How it works:

  1. Create an Omni-Channel Flow (type: Messaging Session).
  2. In the flow, use a Get Records element to check Business Hours.
  3. Branch: during hours, route to the appropriate queue based on a pre-chat field (e.g., language or product line); outside hours, send an auto-response message and end the session or queue to a low-priority fallback queue.
  4. On the Messaging Channel, set sessionHandlerType to Flow, sessionHandlerFlow to the flow's API name, and sessionHandlerQueue to the queue that catches whatever the flow cannot place — that queue is the fallback, and it is Required.
  5. Map each pre-chat parameter to the flow with actionParameterMappings/actionParameterName set to the flow's API name; an unmapped parameter never reaches the routing logic.
  6. Test the routing logic in sandbox across each branch and at least one out-of-hours run, then confirm with the MessagingSession query in references/metadata-examples.md.

Why not the alternative: Implementing business-hours logic in Apex triggers on MessagingSession is possible but fragile — it fires after routing has already begun and can leave sessions in inconsistent states.


Decision Guidance

SituationRecommended ApproachReason
Single-language support team, no conditional routingQueue-Based RoutingSimpler to configure and maintain; sufficient for most SMB deployments
Multi-language or multi-skill routing requiredOmni-Channel Flow routingFlows support conditional branching; queues cannot conditionally route
New org, no existing chat infrastructureMIAW with STATUS_BASED capacity on the messaging service channelAsync sessions outlive a console tab, which is exactly what TAB_BASED keys on
Migrating from legacy Live AgentCreate new MIAW channel; run in parallel during cutoverReusing Live Agent deployments causes transcript and routing conflicts
Pre-chat answers must reach routing logicDeclare the parameter on the channel and map it with actionParameterMappingsAn unmapped parameter is stored but invisible to the flow
The conversation must attach to a ContactWrite MessagingEndUser.ContactId from a flow or triggerMessagingSession.EndUserContactId is not writeable
Agents handle both phone and messagingStatus-Based capacity modelTab-Based is unreliable for voice + async messaging concurrency

  1. Read the shapes before opening Setup. Open references/metadata-examples.md for the five types this skill owns (MessagingChannel, EmbeddedServiceConfig, BrandingSet, CorsWhitelistOrigin, CspTrustedSite), their required fields, and the deploy order. Answer the Questions to Ask table above; each unanswered row becomes a gotcha later.
  2. Confirm the two prerequisites this package depends on but does not own. The Experience site or website named by EmbeddedServiceConfig.site must exist (admin/experience-cloud-site-setup), and the queue named by sessionHandlerQueue must exist with a routing configuration and members (admin/omni-channel-routing-setup). Retrieve both into the working project so the checker can resolve the pointers.
  3. Author the Messaging Channel. Set messagingChannelType to EmbeddedMessaging, pick sessionHandlerType, and fill sessionHandlerQueue — it is Required and it is the fallback when sessionHandlerFlow is set. Declare pre-chat parameters (standardParameters / customParameters) and the automatedResponses set for the initial, inactive and agent-end paths.
  4. Author the Embedded Service deployment. Set site, deploymentType Web, deploymentFeature EmbeddedMessaging, and the whole embeddedServiceMessagingChannel block — every field in it is Required. Build the pre-chat form under embeddedServiceForms, matching each formField to a parameter declared in step 3. Point branding at a BrandingSet, never at an EmbeddedServiceBranding.
  5. Register every origin as a CORS + CSP pair. One CorsWhitelistOrigin and one CspTrustedSite per host, production and non-production, with the CSP directives explicitly set rather than defaulted. Name each EmbeddedServiceConfig explicitly in package.xml — the type does not support the * wildcard.
  6. Gate it locally, then deploy. Run python3 scripts/check_messaging_and_chat_setup.py --manifest-dir <retrieved-tree> and clear every ERROR; the checks cover required fields, enum values, routing-pointer resolution, pre-chat form shape rules, directive-free CSP records and legacy Chat metadata mixed in. Then sf project deploy validate before sf project deploy start.
  7. Verify with data, not with the widget. Run a test conversation, then the MessagingSession and MessagingEndUser queries in references/metadata-examples.md § Verify after deploy. Work the Review Checklist below and record which pre-chat parameters actually arrived and whether a MessagingEndUser.ContactId was written.

Review Checklist

Run through these before marking work in this area complete:

Salesforce-Specific Gotchas

Ten non-obvious platform behaviours, each with a source line, are in references/gotchas.md. The five that most often decide whether a first deployment works:

  1. A non-allowlisted origin returns HTTP 404, not a CORS error — so the network tab blames the URL in the snippet while the real fault is a missing CorsWhitelistOrigin. CORS does accept a wildcard, but only immediately before a second-level domain.
  2. EmbeddedServiceConfig does not support the * wildcard in package.xml — a wildcard manifest retrieves the channel and the trusted sites and silently omits the deployment, with no error.
  3. MessagingSession.EndUserContactId is read-only — automation that tries to stamp a Contact on the session cannot succeed; the writeable field is MessagingEndUser.ContactId.
  4. MIAW branding uses BrandingSet — EmbeddedServiceBranding "works only with the legacy chat products", so branding deploys against it succeed and change nothing.
  5. Every CspTrustedSite directive defaults to false — an active trusted site with no isApplicableTo* field set grants nothing, and API 59.0+ now rejects that shape while older records survive.

Output Artifacts

ArtifactDescription
MessagingChannel XMLChannel type, routing (sessionHandlerType / sessionHandlerFlow / sessionHandlerQueue), embeddedConfig, auto-responses, pre-chat parameters
EmbeddedServiceConfig XMLThe web deployment: site, deploymentFeature, branding, the messaging-channel binding, and the pre-chat form
BrandingSet XMLColours for the MIAW chat window, referenced by EmbeddedServiceConfig.branding
CorsWhitelistOrigin entriesOne per widget host; without it the org answers 404
CspTrustedSite entriesOne per widget host, with the needed directives explicitly set
Deployment code snippetCopied from the Embedded Service Deployment record in Setup
Checker run outputscripts/check_messaging_and_chat_setup.py --manifest-dir <tree>, no ERROR
Verification query resultsMessagingSession and MessagingEndUser rows from a test conversation

Reference Files

FileRead it when
references/metadata-examples.mdAuthoring or deploying the channel, deployment, branding set and trusted sites — required fields, enum values, deploy order, package.xml, and the verification SOQL
references/gotchas.mdSomething deployed cleanly and does not work, or before committing to a shape you have not deployed before
references/examples.mdWalking a greenfield build or a flow-routed build end to end, and for the CORS/CSP anti-pattern
references/well-architected.mdJustifying the routing, capacity and channel-granularity choices in a design review
references/llm-anti-patterns.mdReviewing AI-generated messaging configuration before it reaches an org
templates/messaging-and-chat-setup-template.mdRecording context, decisions and sign-off for one deployment

Package files