This repo provides an example of how to integrate a Commerce Optimizer (ACO) EDS storefront with a Salesforce Commerce B2C (SFCC) commerce backend.
Important Note: The blocks in this repo are provided as a reference implementation and should be customized and tailored to each individual use case, implementation patterns, and styling.
Follow the steps in each installation section to install and configure the SFCC blocks and scripts.
The following configuration is required to be completed on the SFCC side in order for the storefront integration to function properly.
- Create a public client in the Salesforce SLAS UI:
https://{your_sfcc_short_code}.api.commercecloud.salesforce.com/shopper/auth-admin/v1/sso/login. - Add your EDS callback route (
https://{your_eds_site}/callback) to the SLAS redirect URI allowlist. - Save your SLAS Public Client ID. You will need to input it into the SFCC CORS settings and EDS configuration in the following sections.
In order for your EDS storefront to be able to communicate with SFCC, you need to enable CORS. Enabling CORS can be done via the SCAPI CORS endpoint (see documentation)
Example CORS client preferences payload to enable CORS on localhost (for development purposes - it is not recommended to enable CORS for localhost in production) and the main branch of our EDS .page and .live sites. Be sure to replace these values with your own EDS URLs (following the EDS URL pattern https://{branch}--{repo}--{org}.aem.[page|live]).
- HTTP Method:
PUT - Endpoint URL:
https://{your_sfcc_short_code}.api.commercecloud.salesforce.com/configuration/cors/v1/organizations/{your_sfcc_org_id}/cors - Example Payload:
{
"corsClientPreferences": [
{
"clientId": "{your_slas_public_client_id}",
"origins": [
"http://localhost",
"https://localhost",
"https://main--aco-sfcc-storefront--adobe-commerce.aem.page",
"https://main--aco-sfcc-storefront--adobe-commerce.aem.live"
]
}
]
}Important Note: CORS settings can take over 1 hour to apply. If you apply these settings and still see errors, please wait and try again later.
Using the AEM EDS Configuration Service, set the salesforce configuration object to your site config so that our SFCC client can connect with your SFCC instance. For the OAuth callback to work correctly, we also need to set a CORS header in EDS to allow our SFCC origin. Note: this can also be done via the AEM HTTP Headers Editor.
{
...
"public": {
...
"default": {
"salesforce": {
"api-url": "https://{your_sfcc_short_code}.api.commercecloud.salesforce.com",
"auth-redirect-uri": "https://{your_eds_site}/callback",
"client-id": "{your_slas_public_client_id}",
"organization-id": "{your_sfcc_org_id}",
"short-code": "{your_sfcc_short_code}",
"site-id": "{your_sfcc_site_id}",
"locale": "{your_sfcc_site_locale}"
}
}
},
"headers": {
"/**": [
{
"key": "access-control-allow-origin",
"value": "*"
}
]
}
}Follow the steps in each installation section to install and configure the SFCC blocks and scripts.
Copy the scripts/aco and scripts/salesforce directories into the scripts/ directory of your EDS site's repo.
Copy any of the provided blocks you wish to use from the blocks directory of this repo into the blocks/ directory of your EDS site's repo.
Provided Blocks:
sfcc-auth-callback: Provides a callback page to complete the OAuth flow with SFCC. Required.sfcc-cart: Provides an example of a shopping cart view.sfcc-checkout: Provides an example of a checkout form view.sfcc-order-confirmation: Provides an example of an order confirmation page view.sfcc-login: Provides an example of a login form view.sfcc-register: Provides an example of a shopper account registration view.
In your Document Authoring UI (https://da.live), create the following documents by clicking New at the top of the file browse page.
- Create a new document called
callback. This will create a page at the/callbackroute used for OAuth with SFCC.- In the document editor, add the following blocks
metadatato define Title and Robots fields.sfcc-auth-callback
- In the document editor, add the following blocks
- Create a new document called
cart. This will create a page at the/cartroute.- In the document editor, add the following blocks
metadatato define Title and Robots fields.sfcc-cart
- Create a new document called
checkout. This will create a page at the/checkoutroute.- In the document editor, add the following blocks
metadatato define Title and Robots fields.sfcc-checkout
-
Using
Newbutton at the top of the file browse page, create a new folder calledcustomer. -
In the new
customerdirectory, create a new document calledlogin. This will create a page at the/customer/loginroute.- In the document editor, add the following blocks
metadatato define Title and Robots fields.sfcc-login
- In the
customerdirectory, create a new document calledregister. This will create a page at the ``/customer/register` route.- In the document editor, add the following blocks
metadatato define Title and Robots fields.sfcc-register
In the head.html file, append the following commerce-sdk-isomorphic import at the end of the script import map.
<script nonce="aem" type="importmap">
{
"imports": {
...
"commerce-sdk-isomorphic": "https://esm.sh/commerce-sdk-isomorphic@4.0.0?bundle"
}
}
</script>Alternatively, the commerce-sdk-isomorphic SDK can be imported via NPM and included in your site's assets by running the npm run postinstall command.
The add to cart button functionality in the product details block composed of two parts:
- In the
/blocks/product-details/product-details.jsfile, find the usage of theupdateProductsFromCartfunction. This logic will update the quantity of a product we are viewing that we already have in our cart. We need to replace this code with our SFCCupdateCartQuantityfunction. Change the code as described in the example below.
REMOVE:
// --- Update existing item ---
const { updateProductsFromCart } = await import(
"@dropins/storefront-cart/api.js"
);
await updateProductsFromCart([{ ...values, uid: itemUidFromUrl }]);REPLACE WITH:
// --- Update existing item ---
const { updateCartQuantity } = await import("../../scripts/salesforce/api.js");
await updateCartQuantity(values.sku, values.quantity);- Next, find the usage of the
addProductsToCartfunction. This logic will update the quantity of a product we are viewing that we already have in our cart. We need to replace this code with our SFCCupdateCartQuantityfunction. Change the code as described in the example below.
REMOVE:
// --- Add new item ---
const { addProductsToCart } = await import("@dropins/storefront-cart/api.js");
await addProductsToCart([{ ...values }]);REPLACE WITH:
// --- Add new item ---
const { addToCart: addToCartSalesforce } = await import(
"../../scripts/salesforce/api.js"
);
await addToCartSalesforce(values.sku, values.quantity);- In the
/blocks/product-list-page/product-list-page.jsfile, replace thecartApiimport with an import of our Salesforce API script. Change the code as described in the example below.
REMOVE:
// Cart Dropin
import * as cartApi from "@dropins/storefront-cart/api.js";REPLACE WITH:
// Salesforce SDK
import * as cartApi from "../../scripts/salesforce/api.js";- Next, find the
getAddToCartButtonfunction and change theonClickattribute value inside theUI.render(Button, {...})button component render function to call our Salesforce API. Change the code as described in the example below.
REMOVE:
UI.render(Button, {
children: labels.Global?.AddProductToCart,
icon: Icon({ source: "Cart" }),
onClick: () => cartApi.addProductsToCart([{ sku: product.sku, quantity: 1 }]),
variant: "primary",
})(button);REPLACE WITH:
UI.render(Button, {
children: labels.Global?.AddProductToCart,
icon: Icon({ source: "Cart" }),
onClick: () => {
cartApi.addToCart(product.sku, 1);
},
variant: "primary",
})(button);





