Access Site Preferences in Your Composable Storefront from the MRT Data Store

If your composable storefront code requires access to the site preferences that administrators manage in Business Manager, access site preferences directly from the Managed Runtime (MRT) Data Store. Accessing site preferences from the MRT data store is faster than making a Salesforce B2C Commerce API (SCAPI) call. Enable the MRT data store by using a configuration or an environment variable.

Enable the MRT Data Store 

Before accessing the MRT Data Store, enable it in the app configuration file or by using an MRT environment variable.

Enable the MRT Data Store in the app configuration value in config/default.js as shown in this example.

1module.exports = {
2    app: {
3        mrtDataStore: {
4            enabled: true  // Enable MRT Data Store bootstrap
5        },
6        // ... rest of config
7    }
8}

Alternatively, use an environment variable to enable the MRT Data Store.

1PWAKIT_MRT_DATA_STORE_ENABLED=true npm start

If the PWAKIT_MRT_DATA_STORE_ENABLED environment variable is set to a valid value, it takes precedence over the app configuration value.

Note

Usage in ssr.js (Server Middleware) 

Access preferences at the server middleware layer, before React renders. The async getCustomSitePreferences and getCustomGlobalPreferences functions from @salesforce/pwa-kit-runtime/utils/ssr-server let you inspect preference values and modify the HTTP response—for example, returning a 503 status during maintenance or populating an API endpoint with feature flags. Because middleware runs before rendering, this is the right place when preferences need to gate or redirect requests. To access preferences inside React components instead, use the utility functions or hooks.

1// app/ssr.js
2import {
3    getCustomSitePreferences,
4    getCustomGlobalPreferences
5} from '@salesforce/pwa-kit-runtime/utils/ssr-server'
6
7export default function(app) {
8    app.use(async (req, res, next) => {
9        const siteId = res.locals.site?.id
10
11        const [sitePrefs, globalPrefs] = await Promise.all([
12            getCustomSitePreferences({siteId}),
13            getCustomGlobalPreferences()
14        ])
15
16        if (sitePrefs.maintenanceMode) {
17            return res.status(503).send('Maintenance')
18        }
19
20        next()
21    })
22
23    app.get('/api/config', async (req, res) => {
24        const siteId = res.locals.site?.id
25        const prefs = await getCustomSitePreferences({siteId})
26
27        res.json({
28            enableFeature: prefs.enableFeature || false
29        })
30    })
31}

Usage in React Components (Utilities) 

Use the utility functions from @salesforce/pwa-kit-runtime/utils/ssr-server when you need direct control over how preferences are fetched and cached. Wrap them in useQuery from @tanstack/react-query to configure caching behavior—for example, staleTime: Infinity fetches data once per session, and enabled: Boolean(siteId) prevents the query from running until a site ID is available. Extract this logic into shared custom hooks and call them from any component that needs to conditionally render content based on preference flags.

1// app/hooks/useStorePreferences.js
2  import {useQuery} from '@tanstack/react-query'
3  import {
4      getCustomSitePreferences,
5      getCustomGlobalPreferences
6  } from '@salesforce/pwa-kit-runtime/utils/ssr-server'
7
8  export function useSitePreferences(siteId) {
9      return useQuery({
10          queryKey: ['sitePreferences', siteId],
11          queryFn: () => getCustomSitePreferences({siteId}),
12          staleTime: Infinity,
13          enabled: Boolean(siteId)
14      })
15  }
16
17  export function useGlobalPreferences() {
18      return useQuery({
19          queryKey: ['globalPreferences'],
20          queryFn: () => getCustomGlobalPreferences(),
21          staleTime: Infinity
22      })
23  }
24
25  // app/pages/home/index.jsx
26  const Home = () => {
27      const {data: sitePrefs} = useSitePreferences('RefArch')
28      const {data: globalPrefs} = useGlobalPreferences()
29
30      return (
31          <div>
32              {sitePrefs?.showBanner && <HeroBanner />}
33              {globalPrefs?.enableChat && <ChatWidget />}
34          </div>
35      )
36  }

Usage in React Components (Hooks) 

Use the React hooks for the most idiomatic way to access preferences in React function components. The useCustomSitePreferences and useCustomGlobalPreferences hooks from @salesforce/pwa-kit-react-sdk/ssr/universal/hooks integrate with React’s component model, follow standard hook conventions, and can be composed into custom hooks. This is the recommended approach for React function components.

1// app/pages/home/index.jsx
2import React from 'react'
3import {
4    useCustomSitePreferences,
5    useCustomGlobalPreferences
6} from '@salesforce/pwa-kit-react-sdk/ssr/universal/hooks'
7
8const Home = () => {
9    const sitePrefs = useCustomSitePreferences()
10    const globalPrefs = useCustomGlobalPreferences()
11
12    return (
13        <div>
14            {sitePrefs.showBanner && <HeroBanner />}
15            {globalPrefs.enableChat && <ChatWidget />}
16        </div>
17    )
18}

Local Development 

Use MRT_DATA_STORE_DEFAULTS to seed values without a real data store for local testing. You can use either a flat object or the SCAPI envelope format with data and total.

Use flat objects for simplicity:

1MRT_DATA_STORE_DEFAULTS='{
2  "custom-global-preferences":{
3    "enableChat": true,
4    "maintenanceMode": false
5  },
6  "RefArch-custom-site-preferences":{
7    "productsPerPage": 24,
8    "showBanner": true
9  }
10}' PWAKIT_MRT_DATA_STORE_ENABLED=true npm start

Or use the SCAPI envelope format to match the actual data store structure. Include both data (array) and total (number) — both fields are required to trigger envelope unwrapping:

1MRT_DATA_STORE_DEFAULTS='{
2  "custom-global-preferences":{
3    "data": [{ "enableChat": true, "maintenanceMode": false }],
4    "total": 1
5  },
6  "RefArch-custom-site-preferences":{
7    "data": [{ "productsPerPage": 24, "showBanner": true }],
8    "total": 1
9  }
10}' PWAKIT_MRT_DATA_STORE_ENABLED=true npm start

For example, based on the MRT_DATA_STORE_DEFAULTS definition, getCustomSitePreferences({siteId: 'RefArch'}) returns:

1{
2  productsPerPage: 24,
3  showBanner: true
4}

And getCustomGlobalPreferences() returns:

1{
2  enableChat: true,
3  maintenanceMode: false
4}

Data Store Structure 

The MRT Data Store is populated automatically when enabled. You don’t need to manually configure keys. The utilities and hooks handle key resolution internally based on the site ID you provide.

For reference, data is stored under these keys:

  • Global preferences: custom-global-preferences
  • Site preferences: {siteId}-custom-site-preferences

The exact structure of the preference objects depends on the custom preferences defined in Business Manager for your B2C Commerce instance.