Preserve shopper trust with a tracking consent banner on your Progressive Web App (PWA) Kit site. With the banner, your shoppers can opt in or out of the default activity tracking included in PWA Kit.
This guide explains the default implementation and customization options for the tracking consent banner.
note: The functionality described in this guide isn’t supported in a hybrid storefront.
Prerequisites
To configure and use the tracking consent banner, build your site with Retail React App version 6.0 or later.
Default Tracking Consent Implementation
Banner UI
The tracking consent banner is available in template-retail-react-app/app/components/_app/index.jsx, so you can display it on any page on your site. The banner is defined in template-retail-react-app/app/hooks/use-dnt-notification.js.
By default, the banner looks similar to this example.
![]()
Do Not Track Values
These are the two values that define what the DNT state is set to:
effectiveDnt: Is set to the default DNT state that you configured or is set tofalseif you didn't configure a default DNT state. This value is set tofalseif the shopper consented to tracking ortrueif the shopper opted out of tracking.selectedDnt: Is undefined until the shopper interacts with the consent banner. This value is set tofalseif the shopper consented to tracking ortrueif the shopper opted out of tracking.
Banner and DNT Workflow
If a shopper closes the banner or doesn’t make a selection in the banner, the default DNT state is set to false (track activity). To change that behavior, see Configure the Default DNT State. The banner reappears the next time the shopper visits your site after they take any of these actions:
- Close the browser
- Refresh site data
- Clear their cookies
The tracking preference is represented by the dw_dnt cookie. The cookie value is 0 if tracking is consented to and 1 if it isn’t. This value is synced with the backend through the DNT claim in the SLAS access token. The use of the SLAS access token is currently the way to pass the DNT preference to SCAPI. For more information about the use of the DNT claim in SLAS and the use of APIs and hooks, see Manage Shopper Tracking Preferences.
This diagram summarizes the behavior of the tracking consent banner and how shoppers’ DNT state is set when they visit your site. Unless otherwise stated, all of the steps in the diagram apply to both guest shoppers and known shoppers.
![]()
Configure the Default DNT State
Optionally, you can specify a default DNT state that applies if a shopper closes the tracking consent banner or doesn’t make a selection in the banner. To do so, set the defaultDNT property in this file in your project: {overridesDir}/app/components/_app-config/index.jsx.
defaultDnt={true}: Indicates that shopper activity isn’t tracked.defaultDnt={false}: Indicates that shopper activity is tracked.
In this example, defaultDnt is set to false.
// More code here...
<CommerceApiProvider
shortCode={commerceApiConfig.parameters.shortCode}
clientId={commerceApiConfig.parameters.clientId}
organizationId={commerceApiConfig.parameters.organizationId}
siteId={locals.site?.id}
locale={locals.locale?.id}
currency={locals.locale?.preferredCurrency}
redirectURI={`${appOrigin}/callback`}
proxy={`${appOrigin}${commerceApiConfig.proxyPath}`}
headers={headers}
// Add your chosen default DNT state.
defaultDnt={false}
// Uncomment 'enablePWAKitPrivateClient' to use SLAS private client login flows.
// Make sure to also enable useSLASPrivateClient in ssr.js when enabling this setting.
// enablePWAKitPrivateClient={true}
logger={createLogger({packageName: 'commerce-sdk-react'})}
>
<MultiSiteProvider site={locals.site} locale={locals.locale} buildUrl={locals.buildUrl}>
<ChakraProvider theme={theme}>{children}</ChakraProvider>
</MultiSiteProvider>
<ReactQueryDevtools />
</CommerceApiProvider>
// More code here...
Customize the Tracking Consent Banner
Optionally, you can customize the tracking consent banner by changing parts of it such as the appearance or text. Override the banner file in the base template by completing these steps.
- If you haven’t done so already, in your PWA Kit project, create a folder called
hooksin{overridesDir}/app. - Create a file called
use-dnt-notification.jsin thehooksfolder. - Copy and paste this code into
use-dnt-notification.js. In this example, we useselectedDntto render a customized banner that's controlled by theDntNotificationcomponent. Also, we use theupdateDntfunction to apply a shopper's tracking preference as a boolean. See Do Not Track Values.
import React, {useEffect} from 'react'
import PropTypes from 'prop-types'
import {FormattedMessage, useIntl} from 'react-intl'
import {
Button,
Modal,
ModalContent,
ModalBody,
ModalCloseButton,
useDisclosure,
Heading,
Stack,
Text,
Flex
} from '@salesforce/retail-react-app/app/components/shared/ui'
import {useDNT} from '@salesforce/commerce-sdk-react'
import {useLocation} from 'react-router-dom'
export const DntNotification = ({isOpen, onOpen, onClose}) => {
const {selectedDnt, updateDNT} = useDNT()
const {formatMessage} = useIntl()
const location = useLocation()
useEffect(() => {
if (selectedDnt === undefined) {
onOpen()
} else {
onClose()
}
}, [location, selectedDnt])
const onCloseNotification = () => {
updateDNT(null)
onClose()
}
return (
<Modal
size="sm"
data-testid="sf-dnt-notification"
blockScrollOnMount={false}
closeOnOverlayClick={false}
trapFocus={false}
isOpen={isOpen}
onOpen={onOpen}
onClose={onCloseNotification}
>
<ModalContent
position="fixed"
bottom="4"
right="4"
maxW="400px"
pointerEvents="all"
containerProps={{
pointerEvents: 'none'
}}
border="2px solid"
>
<ModalCloseButton
aria-label={formatMessage({
id: 'dnt_notification.button.assistive_msg.close',
defaultMessage: 'Close consent tracking form'
})}
/>
<ModalBody pb={8} bg="white" marginTop={4}>
<Heading as="h3" fontSize={25} width="100%" marginBottom={5}>
<FormattedMessage
defaultMessage="Your Privacy Matters to Us"
id="dnt_notification.title"
/>
</Heading>
<Flex direction="column">
<Text>
<FormattedMessage
defaultMessage="We collect data to improve your experience, deliver personalized content or ads, and better understand how our site is used. By selecting 'Accept,' you agree to our use of tracking technologies. "
id="dnt_notification.description"
/>
</Text>
<Stack direction="column" spacing={4} mt={4} align="flex-end">
<>
<Button
onClick={() => {
updateDNT(true)
onClose()
}}
width="100%"
>
<FormattedMessage defaultMessage="Decline" id="dnt_notification.button.decline" />
</Button>
<Button
onClick={() => {
updateDNT(false)
onClose()
}}
width="100%"
>
<FormattedMessage defaultMessage="Accept" id="dnt_notification.button.accept" />
</Button>
</>
</Stack>
</Flex>
</ModalBody>
</ModalContent>
</Modal>
)
}
DntNotification.propTypes = {
isOpen: PropTypes.bool.isRequired,
onOpen: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired
}
/**
*
* @returns {Object} - Object props to be passed into the DntNotification component
*/
export const useDntNotification = () => {
const {isOpen, onOpen, onClose} = useDisclosure()
return {
isOpen,
onOpen,
onClose
}
}
- If you overrode the
app/components/_app/index.jsxfile in your PWA Kit project, utilize theuseDntNotificationhook to display your customized tracking consent banner.
import {
DntNotification,
useDntNotification
} from '{overridesDir}/app/hooks/use-dnt-notification'
const App = (props) => {
...
const dntNotification = useDntNotification()
...
return (
...
// Put the consent tracking banner in your chosen location in your code by adding the dntNotification component.
<DntNotification {...dntNotification} />
...
)
}
Suppress Tracking Based on DNT State
Optionally, you can add code in your PWA Kit project to trigger or prevent actions based on a shopper's tracking preference or your default DNT state.
Use effectiveDnt to trigger or prevent actions such as API calls. For example, API calls to access Google Analytics. See Do Not Track Values.
In this example, we use effectiveDnt to trigger an analytics API call with the goal of gathering data based on a shopper's interactions with a site. The data can provide insights about factors such as shopper behavior, website traffic, or sales performance.
import {
useDNT
} from '@salesforce/commerce-sdk-react'
function reportClickTracking() {
const {effectiveDnt} = useDNT()
if (effectiveDnt) {
return
}
return fetch('https://tracking.example.com/collect')
}
Considerations
-
If a shopper opts out of tracking (the DNT state is set to
true) or the DNT state isn’t set:- Einstein events are suppressed. This means that a shopper’s activity on your site isn’t included in Reports & Dashboards.
- Active Data metrics are collected if you enabled the feature as described in Active Data. However, all shopper data is anonymized.
-
PWA Kit overrides any default tracking configuration that you set under privacy preferences in Business Manager. Your PWA Kit site applies either of these configurations:
- PWA Kit: The default or custom tracking configuration described in this guide.
- Shopper Login and API Access Service(SLAS): If you customized the tracking consent banner using SLAS, your site applies the tracking configuration described in Manage Shopper Tracking Preferences.
Troubleshoot Tracking Consent
This section provides a suggested solution for a common error that you can encounter while using the tracking consent banner.
Banner Doesn’t Appear or Behavior is Unexpected
Cause: CSS or JavaScript issues can hamper functionality or cause the banner to display incorrectly or not at all on certain devices or browsers.
Suggested Solution: Test the banner in multiple browsers and devices to ensure consistent functionality. Pay particular attention to browsers with stricter cookie policies (for example, Safari’s Intelligent Tracking Prevention). Test different screen sizes and resolutions to ensure that the banner is responsive and user-friendly. Confirm that the banner doesn’t interfere with any site functionality or shopper interactions.