
Messaging Widget Integration
OfficialFreeEasily embed chat widgets in Experience Cloud sites.
Free · Opens the source repo
What Messaging Widget Integration does
The Messaging Widget Integration skill facilitates the embedding of an In-App and Web (MIAW) chat widget into Salesforce Experience Cloud sites. By automating the process of patching the site's LWR or Aura page bundles, this skill streamlines the deployment and publishing of messaging components, significantly reducing the manual effort typically required. It retrieves the necessary bundle artifacts, updates the home page JSON to include the embedded messaging component, and verifies guest access to ensure the widget is operational.
This skill is particularly useful for developers and designers looking to enhance user engagement on their Experience Cloud sites by incorporating real-time chat functionality. Instead of navigating through the Experience Builder interface, users can execute a series of commands that automatically handle the retrieval, patching, deployment, and publishing of the messaging widget. The operation is designed to be idempotent, meaning that if the component is already present, it will be updated in place without creating duplicates, which simplifies the maintenance of the site.
The skill is structured into phases that handle different aspects of the integration process. It first detects the type of bundle (LWR or Aura) before proceeding to patch the appropriate bundle with the messaging component. If any issues arise during the automated steps, the skill includes a manual fallback procedure to ensure that the widget can still be deployed successfully. This makes it robust for various deployment scenarios, ensuring that users can rely on it for consistent results.
When to use it
Use this skill when you want to add a chat widget to an Experience site without manually navigating the Experience Builder.
When not to use it
This skill is not suitable for creating messaging channels or standalone JavaScript snippets for non-Experience websites.
What you can build with it
Adding a Chat Widget to a Community
Quickly integrate a chat widget into an existing Salesforce community site to enhance user interaction.
Updating an Existing Messaging Component
Easily update the configuration of an already embedded messaging component without the need for manual adjustments.
Deploying Messaging for New Experience Sites
Automate the deployment of a chat widget when launching a new Experience Cloud site, saving time and effort.
How to install Messaging Widget Integration
View source1. Install with the skills CLI
npx skills add forcedotcom/sf-skills/service-digital-engagement-messaging-site-integrate --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by forcedotcomEmbed Messaging Widget on an Experience Cloud Site
Wires an existing Embedded Messaging (MIAW) deployment onto an Experience Cloud site by retrieving the site's bundle (LWR DigitalExperienceBundle or Aura ExperienceBundle), patching the home page JSON to place the experience_messaging:embeddedMessaging component, staging the bundle into the local project, deploying it, publishing the site, and verifying guest access.
The operation is idempotent: if the component is already present it is updated in place (its id is preserved), so re-running with different ESD coordinates cleanly updates.
Scope
- In scope: Detecting LWR vs Aura bundle type; scaffolding missing LWR template routes required by the site template (e.g.
too-many-requests); patching the home-page JSON to insert or update the Embedded Messaging component; staging the bundle intoforce-app; async deploy with polling; resolving theNetwork.Nameand publishing the site; guest-URL smoke test; manual Experience Builder fallback with a deep link. - Out of scope: Creating the
EmbeddedServiceConfig(Embedded Service Deployment) itself — useservice-digital-engagement-deployment-configure; creating theMessagingChannel— useservice-digital-engagement-channel-configure; creating the Experience Cloud site itself — useexperience-lwr-site-generate; generating a standalone JS snippet for a non-Experience website.
Clarifying Questions
Before executing, ask the user if not already clear:
- Site name? The
DeveloperNameof the Experience Cloud site (the metadata folder name underdigitalExperiences/site/<siteName>/orexperiences/<siteName>/). - Deployment coordinates? The
deploymentName(Embedded Service DeploymentDeveloperName), thescrtUrl, and thesiteEndpoint(Experience site base URL). All three come from the publishedEmbeddedServiceConfig— obtain fromservice-digital-engagement-deployment-configureoutput if not provided. - Target org alias? For the
sfcommands. - URL path prefix? The site's
UrlPathPrefix(needed to resolveNetwork.Namefor publish and to hit the guest URL for verification).
Required Inputs
Gather or infer before proceeding:
- Site name —
DeveloperNameof the site - Deployment name —
DeveloperNameof theEmbeddedServiceConfig - scrtUrl — SCRT2 endpoint URL from the deployment
- siteEndpoint — Base URL of the Experience site
- Target org alias
- URL path prefix — Site's public URL path segment (e.g.
esw-site)
Defaults applied to the component's attributes when writing:
isExpSiteAuthMode:falsehideChatButtonOnLoad:"Default"clientVersion:"WebV1"
Workflow
Steps are sequential. If any automated step fails, proceed to the manual fallback (Phase 6) and do not claim the widget is "live" until either the guest-URL smoke test returns 200 or the user confirms manual publish.
Phase 1 — Detect Bundle Type
-
Retrieve both candidate bundles into
<retrieve-dir>. The script only performs a deterministic path check, so the retrieve calls must run first:sf project retrieve start --metadata "DigitalExperienceBundle:site/<siteName>" \ --target-org <org-alias> --target-metadata-dir <retrieve-dir> sf project retrieve start --metadata "ExperienceBundle:<siteName>" \ --target-org <org-alias> --target-metadata-dir <retrieve-dir>Either call may return "no metadata found" — that is expected; the missing bundle simply means the site is the other type.
-
Run
scripts/detect_bundle_type.sh <retrieve-dir> <siteName>. It emits exactly one token to stdout:LWR→ the LWR marker file exists (digitalExperiences/site/<siteName>/sfdc_cms__view/home/content.json). Go to Phase 2.AURA→ the Aura marker file exists (experiences/<siteName>/views/homeGuestLayout.json). Go to Phase 3.UNKNOWN(exit code 1) → neither marker exists. Skip to the manual fallback in Phase 6.
Read references/bundle_detection.md for retrieval command shapes and troubleshooting.
Phase 2 — Patch the LWR Bundle
-
Scaffold any missing LWR template routes (commonly
too-many-requests) before patching — missing routes fail the deploy. Route+view scaffolding is owned byexperience-lwr-site-generate(see itsconfigure-content-route.md,configure-content-view.md, andhandle-component-and-region-ids.md). Delegate to that skill for the actual scaffold; this skill only supplies the messaging-specific context (which route the deploy is complaining about, and confirmation that the scaffolded pair resolves that specific deploy error). Seereferences/lwr_route_scaffolding.mdfor the delegation pointer. -
Patch the home page by running:
scripts/patch_lwr_bundle.sh \ <retrieve-dir>/digitalExperiences/site/<siteName>/sfdc_cms__view/home/content.json \ <deploymentName> <scrtUrl> <siteEndpoint>The script deterministically walks
.contentBody.component.children[], targets the region with.type == "region"and.name == "content", and either updates the existing.definition == "experience_messaging:embeddedMessaging"component in place (preserving itsid) or appends a freshcommunity_layout:sectionwrapper with a JSON-stringsectionConfig. Seereferences/lwr_patch.mdfor the JSON shapes it emits and how to verify. -
Proceed to Phase 4.
Phase 3 — Patch the Aura Bundle
-
Patch the home guest layout by running:
scripts/patch_aura_bundle.sh \ <retrieve-dir>/experiences/<siteName>/views/homeGuestLayout.json \ <deploymentName> <scrtUrl> <siteEndpoint>The script iterates
.regions[], picks the first region whose.components[]is non-empty, recurses through anyforceCommunity:sectionwrappers, and either updates the existing.componentName == "experience_messaging:embeddedMessaging"component in place (preservingid) or appends a freshforceCommunity:sectionwrapper. Aura usescomponentName/componentAttributes(notdefinition/attributes) and has nodxpStyle. Seereferences/aura_patch.mdfor JSON shapes and verification steps. -
Proceed to Phase 4.
Phase 4 — Stage and Deploy
-
Copy the modified bundle into the project's default package. Use
cp -Rso unchanged files travel with the modified one:- LWR:
cp -R <retrieve-dir>/digitalExperiences force-app/main/default/ - Aura:
cp -R <retrieve-dir>/experiences force-app/main/default/and also copy the sibling<siteName>.site-meta.xmlfile — Aura deploys are rejected without it.
- LWR:
-
Async deploy and poll:
sf project deploy start --source-dir force-app/main/default \ --target-org <org-alias> --asyncPoll every 15 seconds up to 10 minutes:
sf project deploy report --job-id <job-id> --target-org <org-alias>Stop when status is
Succeeded,Failed,SucceededPartial, orCanceled. On failure, surface the deploy report and do not proceed to publish. Seereferences/deploy_and_publish.mdfor the full polling loop and common failure modes.
Phase 5 — Publish and Verify
-
Resolve the
Network.Name.Network.Namefrequently differs from the siteDeveloperName, so query it by the URL path prefix rather than guessing:sf data query --query \ "SELECT Name FROM Network WHERE UrlPathPrefix='<urlPath>' LIMIT 1" \ --target-org <org-alias> -
Publish the community with the resolved name:
sf community publish --name "<resolved-Name>" --target-org <org-alias> -
Smoke-test guest access by hitting the public URL:
curl -sL -o /dev/null -w "%{http_code}" \ https://<domainHostname>/<urlPath>Report success only when the response is
200.
Phase 6 — Manual Fallback
-
If any automated step fails (bundle undetectable, patch write blocked, deploy fails, publish fails, or guest URL not
200), print the Experience Builder deep link and verbatim instructions fromreferences/manual_fallback.md. Do not claim the widget is live until the user confirms.The deep link is:
https://<MyDomain>.lightning.force.com/sfsites/picasso/core/config/commeditor.apexp?...networkId=<Network.Id>Resolve
<MyDomain>viasf org display --target-org <org-alias>and<Network.Id>via:sf data query --query \ "SELECT Id FROM Network WHERE UrlPathPrefix='<urlPath>' LIMIT 1" \ --target-org <org-alias>Do not hardcode either value. Instruct the user to open Experience Builder, drag the Embedded Messaging component onto the target page, pick the deployment from the property panel, and click Publish.
Rules / Constraints
| Constraint | Rationale |
|---|---|
| Detect bundle type from retrieval output, do not assume | LWR and Aura sites need different files patched with different key names |
Preserve the existing component id when updating in place | Ensures idempotency; the Experience runtime keys off id |
Every new id must be a fresh UUID | Duplicate IDs corrupt the layout and can fail render |
LWR uses definition / attributes; Aura uses componentName / componentAttributes | Wrong key names silently drop the component from render |
LWR community_layout:section sectionConfig is a JSON string, not a nested object | The Experience CMS serializer expects a string |
Aura sibling <siteName>.site-meta.xml must be copied alongside the bundle | Deploy is rejected without it |
| Poll the async deploy; do not fire-and-forget | Publish must run only after deploy succeeds |
Resolve Network.Name from UrlPathPrefix, do not reuse site DeveloperName | The two are frequently different |
Do not claim "live on the site" until the guest URL returns 200 or the user confirms | Publish is asynchronous; premature success reports mislead |
Never hardcode MyDomain or Network.Id in the manual fallback link | Values are org-specific and must be queried |
| Idempotency: re-running with new ESD coordinates must update in place | Users iterate on deploymentName, scrtUrl, siteEndpoint during setup |
Gotchas
| Issue | Resolution |
|---|---|
too-many-requests route missing during LWR deploy | Scaffold the missing route+view pair per references/lwr_route_scaffolding.md |
| Aura deploy rejected with missing site metadata | Copy the sibling <siteName>.site-meta.xml from the retrieve dir |
| Component appended but not rendering | Confirm the region wrapper uses the correct type: "region" key and that Aura components use componentName (not definition) |
sf community publish fails with "community not found" | The Network.Name differs from site DeveloperName; resolve via UrlPathPrefix query |
Guest URL returns 403 or 503 after publish | Publish is async — retry the smoke test after 60s before falling back to manual |
| Re-run adds a second messaging component | The recursive search matched on the wrong key name; component detection must use definition (LWR) or componentName (Aura) |
| Deploy succeeds but widget does not appear | The messaging component is present in a region that is not on the site's home page — patch home/content.json (LWR) or homeGuestLayout.json (Aura), not another view |
sectionConfig written as an object | Serialize it as a JSON string; the CMS parser will not accept an object |
Verification Checklist
Bundle Detection
- Was exactly one of
sfdc_cms__view/home/content.json(LWR) orviews/homeGuestLayout.json(Aura) found? - If neither was found, did the workflow route to the manual fallback?
Patch Correctness
- For LWR, are the messaging component's keys
definitionandattributes? - For Aura, are the keys
componentNameandcomponentAttributes? - When updating in place, was the existing
idpreserved? - When appending, are all new
idvalues fresh UUIDs? - For LWR, is
sectionConfiga JSON string (not a nested object)? - For LWR, do the UUIDs referenced inside
sectionConfigmatch the sectionidand child regionid?
Deploy
- For Aura, was
<siteName>.site-meta.xmlcopied alongside the bundle? - Was the async deploy polled until a terminal status?
- Is the terminal status
SucceededorSucceededPartialbefore proceeding to publish?
Publish
- Was
Network.Nameresolved viaUrlPathPrefix, not reused from siteDeveloperName? - Did
sf community publishcomplete without error?
Verify
- Did the guest URL curl return
200? - Did the workflow refrain from claiming success until
200was observed or the user confirmed manual publish?
Output Expectations
Deliverables:
- Modified home-page JSON in the retrieval directory and in
force-app/main/default/... - (LWR only, if needed) new
sfdc_cms__route/<RouteApiName>/+sfdc_cms__view/<viewId>/pair for any scaffolded missing route - Deploy
job-idand the final deploy report - Publish confirmation
- Guest URL smoke-test HTTP status
- On failure: the Experience Builder deep link and manual instructions
Do not produce the EmbeddedServiceConfig or the MessagingChannel metadata — those are the responsibilities of the deployment and channel skills below.
Cross-Skill Integration
| Need | Delegate to |
|---|---|
| Create or update the Embedded Service Deployment | service-digital-engagement-deployment-configure |
| Create the underlying MIAW messaging channel | service-digital-engagement-channel-configure |
| Create the Experience Cloud LWR site itself | experience-lwr-site-generate |
Scaffold a missing LWR route + view pair (e.g. too-many-requests) | experience-lwr-site-generate (route/view creation, ID handling) |
Reference File Index
| File | When to read |
|---|---|
references/bundle_detection.md | Phase 1 — LWR vs Aura retrieval and disambiguation |
references/lwr_route_scaffolding.md | Phase 2 — delegation pointer for scaffolding missing LWR template routes (owned by experience-lwr-site-generate) |
references/lwr_patch.md | Phase 2 — what patch_lwr_bundle.sh does and how to verify its output |
references/aura_patch.md | Phase 3 — what patch_aura_bundle.sh does and how to verify its output |
references/deploy_and_publish.md | Phases 4–5 — staging into force-app, async deploy polling, publish, and guest-URL smoke test |
references/manual_fallback.md | Phase 6 — Experience Builder deep link and manual drag-drop-publish instructions |
scripts/detect_bundle_type.sh | Phase 1 — deterministic LWR/Aura/UNKNOWN detection over a retrieved bundle |
scripts/patch_lwr_bundle.sh | Phase 2 — idempotent LWR content.json patch (insert or update in place) |
scripts/patch_aura_bundle.sh | Phase 3 — idempotent Aura homeGuestLayout.json patch (insert or update in place) |
Frequently asked questions about Messaging Widget Integration
Similar skills
WinMD API Search
Easily find and explore Windows desktop APIs.
WebMCPify
Transform any web app into an agent-ready platform.
Phoenix Tracing
Instrument LLM applications with OpenInference tracing.
Foundry Hosted Agent CopilotKit
Guidance for developing agentic web apps on Azure.
Power Automate Foundation
Connect AI agents to Power Automate seamlessly.
Power Automate Flow Builder
Efficiently build and deploy Power Automate flows programmatically.
