Composable Storefront Setup with SCAPI and PWA

Customizing the ESW integration in SCAPI & PWA

Setup and Configuration

Setting up BM cartridge / Cartridge Path

  1. Add the following cartridges to your cartridge path:
    • int_eshopworld_core
    • int_eshopworld_pwa
  2. The cartridge path should look like this:
    • int_eshopworld_core:int_eshopworld_pwa:app_storefront_base:modules

Importing site data

After setting up the cartridge path, import PWA-related custom objects, preferences, and content slots from the following paths:

System objects

  • link_eshopworld/sitesdata/meta/systemobjects.xml

Custom objects

  • link_eshopworld/sitesdata/meta/customobjects.xml

Content assets

  • link_eshopworld/sitesdata/sites/RefArch/libraries.xml
  • link_eshopworld/sitesdata/sites/RefArch/content-assets.xml

After importing site data:

  1. Navigate to Merchant Tools > Site Preferences > Custom Site Preference Groups > ESW PWA Integration Configuration.
  2. Provide the PWA Storefront URL (needed because ESW does not get server reference on MRT).
  3. Provide ESW PWA URL Expansion Pairs:
    • InventoryCheckFailurePageUrl|cart
    • BaseUrl|
    • ContinueShoppingUrl|Base url
    • BackToCartUrl|cart

Configuring Countries and Locales

Configuring “Countries” custom object

  1. Navigate to Merchant Tools > Custom Objects > Manage Custom Objects.
  2. Select ESW_COUNTRIES.
  3. Select the country.
  4. Add locale(s) for the country (as per the PDF screenshot guidance).
  5. Locale must be in {lang_Country} format (for example, en_IE, en_US, en_CA).

Configuring locales

  1. Navigate to Merchant Tools > Site Preferences > Locales and check if your locale is present.
  2. If present: activate it (check it and click Apply).
  3. If absent: add it via Administration > Global Preferences > Locales > New Locale (generates {lang_Country} format).

Code Customization

After you set up and run the PWA Kit successfully, ESW-related changes require overrides.

Files to override to enable ESW checkout functionality

Place the following files in the relevant PWA Kit directories to enable ESW checkout:

  • config/
    • default.js (To add ESW cartridge-related URLs)
    • sites.js (Override this file so that add only one base country configs)
  • override/
    • main.jsx (Add timezone cookie)
  • components/
    • footer/index.js (To call ESW init component)
    • forms/login-fields.jsx (Prefilled login email for post-checkout registration)
    • forms/registration-fields.jsx (Prefilled registration fields for post-checkout registration)
    • product-item/index.jsx (Display return prohibit and restricted product message)
    • product-view/index.jsx (Display return prohibit and restricted product message)
  • hooks/
    • use-derived-product.js (Setting return restricted product message)
    • use-add-to-cart-modal.js (Override checkout button in add to cart modal)
  • utils/
    • site-utils.js (Get site/country configs from BM instead of sites.js)
  • pages/
    • account/order-detail.jsx (Display order tracking information from ESW)
    • cart/partials/cart-cta.jsx (Override checkout button)
    • cart/index.jsx
    • routes.jsx
  • translations/
    • en-US.json (Add message for restricted products; update relevant translation file as needed)

esw-config.js

Go to /configs folder and add esw-config.js (as per PDF instruction).

default.js (add eswConfigs)

Add the following configuration in default.js in the app (ensure paths are correct):

eswConfigs: {
  ocapiProxyPath: '/mobify/proxy/ocapi',
  siteUri: '/on/demandware.store/Sites-RefArch-Site/default'
}

sites.js (base country configs)

The sites.js file should have content shaped like the following (base country example shown in PDF for US / RefArch):

module.exports = [
  {
    id: 'RefArch',
    l10n: {
      supportedCurrencies: ['USD'], // Retailer's base currency
      defaultCurrency: 'USD', // Retailer's base currency
      defaultLocale: 'en-US', // Retailer's base country locale
      supportedLocales: [
        {
          id: 'en-US', // Retailer's base country locale
          alias: 'us', // country code in lowercase for URL
          preferredCurrency: 'USD', // Retailer's base currency
          supportedLocales: ['en-US'], // Retailer's base country locale
          isFixedPriceModel: true,
          isSupportedByESW: true,
          countryCode: 'US' // country code in uppercase for ESW config
        }
      ]
    }
  }
]

This component is responsible for:

  • Getting ESW-related configurations.
  • Displaying geo-ip alert if the user changes the location.
  • Rebuilding the cart when a user comes back to the cart from the ESW checkout.

Steps (per PDF):

  1. Navigate to /overrides/components/footer/index.jsx (copy file from pwa-kit if absent).
  2. Import EswInit.
  3. Add EswInit component.

Import EswInit

import {EswInit} from '../../esw/components/esw-init'

Add EswInit component (as per screenshot snippet)

{/* ESW INIT */}
<EswInit locale={locale} site={site} />
{/* End ESW INIT */}

Note from PDF: EswInit calls the APIs during the initial rendering of the app.


Overriding Registration and Login Forms (optional – ESW shopper registration feature)

Navigate to /overrides/components/forms (create if missing).

  • Copy login-fields.jsx from ESW PWA cartridge (PDF says to add code snippets there).
  • Copy registration-fields.jsx from ESW PWA cartridge (PDF says to add code snippets there).

(There are no explicit code blocks shown in the PDF text for these snippets beyond “add the following code snippets”.)


Overriding Product Item Component (Return Prohibited feature)

Navigate to /overrides/components/product-item/index.jsx (copy from PWA cartridge if absent).

Import (shown truncated in PDF text; path starts as below)

import {EswReturnProhibitMsg} from '../../esw/components/product-return'

Call component (screenshot snippet)

{/* Esw return prohibit message */}
<EswReturnProhibitMsg product={product} />
{/* End Esw return prohibit message */}

Overriding Product View Component (Return Prohibited feature)

Navigate to /overrides/components/product-view/index.jsx (copy from PWA cartridge if absent).

Import (shown truncated in PDF text; path starts as below)

import {EswReturnProhibitMsg} from '../../esw/components/product-return'

(PDF references adding the component similarly to Product Item.)


Override use-derived-product hook (restricted product messaging)

Navigate to /overrides/hooks/use-derived-product.js (copy from PWA cartridge if absent) and add code as shown in the PDF screenshot.

Add restricted product constant (screenshot snippet)

// Esw modification
const ESW_RESTRICTED_PRODUCT = 'ESW_RESTRICTED_PRODUCT'
// End Esw modification

Add ESW restricted flags (screenshot snippet)

// Esw modification
const isEswRestricted =
  product && product.c_eswRestrictedProduct ? product.c_eswRestrictedProduct : false
const eswProductRestrictedMsg =
  product && product.c_eswRestrictedProductMsg ? product.c_eswRestrictedProductMsg : ''
// End Esw modification

Add translation mapping (screenshot snippet)

// Esw modification
[ESW_RESTRICTED_PRODUCT]: intl.formatMessage(
  {
    defaultMessage: '{eswProductRestrictedMsg}',
    id: 'esw.product.restricted.msg'
  },
  { eswProductRestrictedMsg }
)
// End Esw modification

Update inventory messaging conditions (screenshot snippet)

// Esw modification
const showInventoryMessage =
  product && ((variant && (isOutOfStock || unfulfillable)) || isEswRestricted)
const inventoryMessage =
  (isOutOfStock && inventoryMessages[OUT_OF_STOCK]) ||
  (unfulfillable && inventoryMessages[UNFULFILLABLE]) ||
  (isEswRestricted && inventoryMessages[ESW_RESTRICTED_PRODUCT])
// End Esw modification

Add translation key (required after use-derived-product override)

Go to /translations/en-US.json and add:

"esw.product.restricted.msg": {
  "defaultMessage": "{eswProductRestrictedMsg}"
},

PDF note: Use the relevant locale translation file(s) for your site.


Overriding use-add-to-cart-modal hook (checkout button in add-to-cart modal)

Navigate to /overrides/hooks/use-derived-product.js (PDF text says this path; context indicates overriding hook for add-to-cart modal behavior). If absent, get it from the PWA cartridge.

Import required ESW modules (PDF code block)

// Esw Customization
import { EswCheckoutBtn } from '../esw/components/checkout-btn'
import {
  useShippingMethodsForShipment,
  useShopperBasketsMutation
} from '@salesforce/commerce-sdk-react'
// end Esw Customization

Replace checkout button in both components (PDF code block)

Make sure to change it in both:

  • <ModalBody/>
  • <ModalFooter/>
<EswCheckoutBtn
  basketIdParam={basket.basketId}
  variant="outline"
  checkOrderAble={false}
/>

Overriding site-utils.js (get countries from BM config)

Navigate to /overrides/utils/site-utils.js (copy from PWA cartridge if absent).

Import getSupportedCountries (PDF code block)

import {getSupportedCountries} from '../esw/esw-services'

Update getSites() (PDF code block / screenshot snippet)

/**
 * ESW customized function to return the list of sites that has include
 * @return {array} sites - list of sites including their aliases
 */
export const getSites = () => {
  let sitesFromConfig = getConfig().app

  // sites.js from the BM
  getSupportedCountries()
    .then((response) => response.json())
    .then((data) => (sitesFromConfig.sites = data.allowedCountries))

  let {sites = [], siteAliases = {}} = sitesFromConfig || {}

  if (!sites.length) {
    throw new Error("Can't find any sites from the config. Please c")
  }

  return sites.map((site) => {
    const alias = siteAliases[site.id]
    return {
      ...site,
      ...(alias ? {alias} : {})
    }
  })
}

Overriding Order Detail Page (order tracking)

Navigate to /overrides/pages/account/order-detail.jsx (copy from PWA cartridge if absent).

Import ESWOrderTracking (shown truncated in PDF text; completed as a standard JS import)

import ESWOrderTracking from '../../esw/components/order-tracking/index'

Call component (screenshot snippet)

{/* Custom for ESW start */}
{selectedOrder && <ESWOrderTracking selectedOrder={selectedOrder} />}
{/* Custom for ESW END */}

Overriding Cart Page (redirect to ESW checkout only if supported)

Override cart CTA

Navigate to /overrides/pages/cart/partials/cart-cta.jsx (copy from PWA cartridge if absent).

Import EswCheckoutBtn

import {EswCheckoutBtn} from '../../../esw/components/checkout-btn'

Call component (screenshot snippet)

{/* Esw Modification */}
<EswCheckoutBtn variant="solid" />
{/* End Modification */}

Call cart CTA in cart page

Navigate to /overrides/pages/cart/index.jsx and modify the import of cart-cta as follows (screenshot snippet):

// ESW specific component
import ProductItem from '../../components/product-item'
import CartCta from './partials/cart-cta'
// End ESW specific component

Overriding Routes (required after cart override)

Navigate to /overrides/routes.jsx

Import Cart (PDF code block)

import Cart from './pages/cart'

Add route entry (PDF code block)

{
  path: '/cart',
  component: Cart,
  exact: true
}

Navigate to /overrides/main.jsx and add (PDF snippet was truncated after resolv; completed to a standard Intl timezone cookie value):

// Esw: Customization
document.cookie = "esw.shopperTimezone=" + Intl.DateTimeFormat().resolvedOptions().timeZone

Updating Content Slots and Messages

Updating Geo-Ip Alert Message

If you are using geo lookup, the alert messages displayed to shoppers can be customized:

  • Navigate to the asset: eswGeoIpChangeWarning
  • Make necessary changes.