Embed Salesforce LWC components in your storefront
On this page
StoreConnect storefronts use a Liquid-based theme engine, but you can also embed Salesforce Lightning Web Components (LWC) directly into your storefront pages. This lets you bring Salesforce-native UI and logic into your store without rebuilding it in Liquid or JavaScript.
This can be achieved using Salesforce Lightning Out combined with a secure, token-based authentication layer. The StoreConnect theme generates an HMAC-signed token server-side, and a wrapper LWC on the Salesforce side verifies the token before dynamically rendering your component with authenticated customer data. Depending on your setup, there are also other ways to approach this.
A ready-to-deploy proof of concept project is available for download:
Download the StoreConnect Secure LWC project
How it works
The embedding process follows a secure handshake between StoreConnect and Salesforce:
-
Token generation (StoreConnect) – When a storefront page loads, the Liquid template generates a JSON payload containing the customer’s context (Customer ID, Store ID) and a timestamp. This payload is cryptographically signed using HMAC-SHA256 with a shared secret stored in Store Variables. The resulting token is embedded into the page HTML.
-
Client-side loading – The browser loads the Salesforce Lightning Out library via a singleton loader (preventing duplicate script loads when multiple components are on the same page). A wrapper LWC is initialized and receives the signed token along with the name of the component to render.
-
Server-side verification (Salesforce) – The wrapper LWC passes the token to an Apex controller. Apex retrieves the shared secret for the originating store, recalculates the HMAC signature, and verifies it matches. It also checks that the token has not expired (1-hour window with 30-second clock skew tolerance).
-
Dynamic rendering – Once verified, the wrapper dynamically instantiates the requested business component and passes the authenticated customer data down to it. The component renders inside the storefront page.
StoreConnect Salesforce
+------------------------------+ +-----------------------------------+
| 1. Page loads | | |
| 2. Liquid generates | | |
| HMAC-signed token | | |
| 3. Token embedded in HTML | | |
| | | |
| 4. Browser loads | ------> | 5. Wrapper LWC receives token |
| Lightning Out library | | + component name |
| | | |
| | | 6. Apex validates: |
| | | - Retrieve store secret |
| | | - Verify HMAC signature |
| | | - Check token expiry |
| | | |
| | <------ | 7. Render requested component |
| 8. Resize and error events | <------ | with authenticated data |
| via postMessage | | |
+------------------------------+ +-----------------------------------+
Security features
- Tamper-proof – Any modification to the token (for example, changing the Customer ID) invalidates the signature and causes immediate rejection.
- Zero-trust – No secrets or API keys are ever exposed to the client browser. The HMAC secret exists only server-side in Store Variables and in the Salesforce
Store_Variable__crecord. - Cache compatible – The stateless design (timestamp + signature) works with StoreConnect’s page caching without triggering false security errors.
- Component allowlist – Only explicitly registered components can be loaded. The wrapper uses a
COMPONENT_MAPobject as a security gate, preventing arbitrary component injection. - Constant-time comparison – Signature verification uses constant-time string comparison to prevent timing attacks.
- Token expiry – Tokens are valid for 1 hour from generation, with a 30-second clock skew tolerance for server time differences.
Alternative approaches
Depending on what you are building, you may not need LWC embedding at all. StoreConnect provides several ways to add custom functionality to your storefront:
- Liquid templates with custom JavaScript – Full control over markup and scripting using the theme engine. See Adding custom JavaScript, CSS and head content.
- Content blocks with raw HTML/JS – Use the “No added styling” content block template to insert custom HTML and JavaScript. See Content block templates.
- Server-side API proxy – Use Liquid’s
apitag and Store Variables to call external APIs server-side without exposing credentials. This is useful for fetching and displaying data from third-party services.
LWC embedding is best suited for scenarios where you need to reuse existing Salesforce components, access Salesforce data in real time through Apex, or leverage the Lightning component ecosystem on your storefront.
Prerequisites
Before you begin, you need:
- A Salesforce org with the StoreConnect managed package installed
- Salesforce CLI (
sf) installed locally - An Experience Cloud site configured in your Salesforce org (this provides the Lightning Out endpoint)
- Access to your StoreConnect theme files
What is in the project
The downloadable project contains everything needed to get LWC embedding working:
| File | Purpose |
|---|---|
templates/blocks/lwc.liquid |
Liquid content block template for your StoreConnect theme. Handles token generation and Lightning Out initialization. |
force-app/main/default/classes/StoreConnectAuthHandler.cls |
Apex class that validates HMAC-signed tokens. Retrieves the shared secret from Store Variables, verifies the signature, and checks token expiry. |
force-app/main/default/classes/StoreConnectAuthHandlerTest.cls |
Apex test class covering valid tokens, expired tokens, tampered signatures, and invalid store IDs. |
force-app/main/default/lwc/storeConnectWrapper/ |
Wrapper LWC that authenticates the token via Apex, then dynamically renders the requested component. Uses a component allowlist for security. |
force-app/main/default/aura/StoreConnectLWCOut/ |
Lightning Out Aura application. This is a Salesforce requirement for serving LWC components externally. |
README.md |
Full setup instructions, architecture overview, and development commands. |
Set up Salesforce
Step 1: Configure the shared secret in Salesforce
Create a Store_Variable__c record for each store that will embed LWC components:
| Field | Value |
|---|---|
Store_Id__c |
Your StoreConnect Store ID |
Key__c |
SC_HMAC_Secret |
Value__c |
A strong, random secret string |
Available_In_Liquid__c |
true |
:::note The secret must be identical on both the Salesforce and StoreConnect sides. Generate a strong random string (at least 32 characters) and keep it secure. :::
Step 2: Deploy the Apex and LWC components
From the project directory, deploy to your Salesforce org:
bash
sf project deploy start --source-dir force-app
This deploys:
- The StoreConnectAuthHandler Apex class and its test class
- The storeConnectWrapper LWC
- The StoreConnectLWCOut Aura application
Step 3: Set up an Experience Cloud site
If you do not already have an Experience Cloud site, create one in Salesforce Setup under Digital Experiences > All Sites. This site provides the Lightning Out endpoint URL that StoreConnect uses to load components.
Note the following URLs from your Experience Cloud site:
- Lightning Out script URL – https://{your-domain}.my.site.com/lightning/lightning.out.js
- Experience Cloud site URL – https://{your-domain}.my.site.com
Set up StoreConnect
Step 1: Configure Store Variables
In your StoreConnect admin, create three Store Variables:
| Store Variable | Description | Example value |
|---|---|---|
SC_HMAC_Secret |
The shared HMAC secret (must match the value in Salesforce) | A strong random string (at least 32 characters) |
SF_My_Salesforce |
Lightning Out script URL from your Experience Cloud site | https://yourdomain.my.site.com/lightning/lightning.out.js |
SF_My_Experience |
Your Experience Cloud site URL | https://yourdomain.my.site.com |
Step 2: Add the Liquid template to your theme
Copy templates/blocks/lwc.liquid from the project into your StoreConnect theme’s templates directory at templates/blocks/lwc.liquid.
This creates a new content block template called lwc that you can use to embed components.
Step 3: Create a content block template option
In Salesforce, add lwc as a new picklist value to the Content_Block__c.Template__c field. This makes the template available when creating content blocks.
Step 4: Embed a component
Create a content block in StoreConnect and:
- Set the Template to
lwc - Set the Content field to the name of the component you want to render (for example,
contactSupportForm)
The Liquid template reads the component name from the content block, generates a signed token, and handles the Lightning Out initialization automatically.
Register custom components
The wrapper uses a component allowlist for security. Only components explicitly imported and registered in the COMPONENT_MAP can be loaded.
To add a new embeddable component:
- Create your LWC under
force-app/main/default/lwc/in your Salesforce org. - Import it in
storeConnectWrapper.jsand add it to theCOMPONENT_MAP:
```javascript import MyComponent from ‘c/myComponent’;
const COMPONENT_MAP = { // …existing components ‘myComponent’: MyComponent, }; ```
- Your component receives
authDataas a property containing all token claims:
```javascript // In your custom component import { LightningElement, api } from ‘lwc’;
export default class MyComponent extends LightningElement { @api authData; // Contains: isValid, customerId, and any custom claims } ```
- Deploy the updated wrapper and your new component to your Salesforce org.
- Reference the component name in a StoreConnect content block using the
lwctemplate.
:::tip You can embed multiple LWC components on the same page. Each content block gets its own container, token, and event scope. :::
Token structure
The token generated by the Liquid template follows this format:
{storeId}|v1.{base64-encoded-payload}.{hex-hmac-signature}
The payload contains standard claims:
| Claim | Description |
|---|---|
aud |
Store domain (audience) |
exp |
Expiry timestamp (1 hour from generation) |
iat |
Issued-at timestamp |
jti |
Nonce (store + customer + time + block ID for uniqueness) |
sub |
Customer ID, or guest for unauthenticated visitors |
Auto-resizing
The wrapper LWC uses a ResizeObserver to monitor the rendered component’s height and sends postMessage events back to the storefront. The Liquid template listens for these events and adjusts the container height automatically. This means embedded components resize smoothly without scrollbars or fixed heights.
Error events (SC_AUTH_ERROR) are also sent via postMessage and logged to the browser console, scoped to the specific component name.
Troubleshooting
Component does not render
- Verify the component name in the content block exactly matches a key in the
COMPONENT_MAPinstoreConnectWrapper.js - Check the browser console for authentication errors
- Confirm the Experience Cloud site is published and accessible
Authentication errors
- Confirm the
SC_HMAC_Secretvalue is identical in both StoreConnect Store Variables and the SalesforceStore_Variable__crecord - Check that the
Store_Id__con the Salesforce record matches your StoreConnect Store ID - If you see “Token expired” errors, verify that your server clocks are reasonably in sync (the system allows 30 seconds of skew)
Lightning Out script fails to load
- Verify the
SF_My_SalesforceStore Variable contains the correct URL ending in/lightning/lightning.out.js - Confirm the Experience Cloud site is published and the URL in
SF_My_Experienceis correct - Check for Content Security Policy (CSP) errors in the browser console – you may need to add your Salesforce domain to your store’s CSP trusted sites
Multiple components on the same page
Each content block generates its own unique container ID and token. The postMessage events include the component name so resize and error events are scoped correctly. If components are interfering with each other, check that each content block has a unique identifier.