Documentation
Feedback
Guides
Storefront Development

Storefront Development
Storefront development

Implementing Delivery Promise

This feature is in closed beta, which means that only selected customers have access to it. If you're interested in implementing it in the future, please contact our Support team.
Delivery Promise is a feature that provides accurate and reliable delivery estimates for available products based on the customer's location. It ensures that customers only see products that are in stock and can be delivered to their address or picked up at a nearby location.
This solution continuously updates product availability throughout the buying journey by responding to changes in catalog, pricing, inventory, or shipping settings. These updates are then sent to Checkout and Intelligent Search, ensuring customers see up-to-date options based on their region.
In this guide, you'll learn how to configure Delivery Promise in your FastStore project.
To understand how Delivery Promise operates, see the Understanding Delivery Promise operation guide. For more information about Delivery Promise components, see the Working with Delivery Promise components guide.

Default settings

Delivery Promise is defined in the deliveryPromise section of the discovery.config.js file.
The default settings are:
discovery.config.js

_10
deliveryPromise: {
_10
enabled: true,
_10
mandatory: false
_10
},

  • enabled: When set to true, Delivery Promise activates, allowing the store to provide delivery estimates based on the user's location.
  • mandatory: When set to true, users must provide a postal code. By default, this is false, allowing users to browse and add items to the cart without entering their postal code. However, without a postal code, the accuracy of delivery information may be limited.

Before you begin

Get the search-session app

Check if you have version 0.5.0 or later of the search-session app installed.
  1. In your terminal, run the vtex list command.
  2. In the returned results, search for the app.
  3. If you don't have this app installed, run the command vtex install vtex.search-session.

Enable the VTEX Intelligent Search app

To enable the Intelligent Search app, check the version of your Edition Store account.
In your terminal, log in to your account by running vtex login {accountName} and run vtex edition get to see the Edition app version installed. Remember to replace the values between curly braces with your account name.
Accounts with vtex.edition-store@5.x
If your account is using the vtex.edition-store@5.x major version, the VTEX Intelligent Search app is already included, and you need to integrate it via VTEX Admin.
To integrate VTEX Intelligent Search, access Store Settings > Intelligent Search > Integrations in the VTEX Admin, and click START INTEGRATION.
Accounts with an edition version older than 5.x
  1. In the VTEX IO CLI, log in to your VTEX account by running vtex login {accountName}. Remember to replace the values between curly braces with your account name.
  2. If the VTEX Intelligent Search app isn't installed in your account, run the following command:

    _10
    vtex install vtex.search-resolver@1.x vtex.admin-search@1.x

After installing the app, integrate it by going to Store Settings > Intelligent Search > Integrations in the VTEX Admin, and clicking START INTEGRATION.
Accounts that want to migrate to version 5.x
If you're using a different major version and want to migrate, please open a ticket with VTEX Support and request the installation of Edition app vtex.edition-store@5.x.

Update the @faststore/cli package

Run the yarn upgrade @faststore/cli command to update the @faststore/cli package to the latest version.

Open a ticket with VTEX Support

Open a ticket with VTEX Support and request the activation of Delivery Promise in your account.

Instructions

Step 1 - Enabling deliveryPromise

  1. Open your FastStore project using the code editor of your choice.
  2. Open the discovery.config.js file.
  3. Under the deliveryPromise section, set the enabled value to true. Set the mandatory value based on your business needs. Learn more in the Default settings section.
    discovery.config.js

    _10
    deliveryPromise: {
    _10
    enabled: true,
    _10
    mandatory: false,
    _10
    }

Step 2 - Syncing your FastStore project with Headless CMS

Run the faststore cms-sync command to sync the cms folder of your FastStore project with Headless CMS.
The expected response is the message CMS synced successfully.... The native regionalization components and sections will be automatically updated. You can check them in the VTEX Admin:
  • Regionalization component: Go to Storefronts > Headless CMS > Global Sections > NavBar > Navigation > Regionalization.
  • Region Bar section: Go to Storefronts > Headless CMS > Global Sections > Region Bar.
  • Region Modal section: Go to Storefronts > Headless CMS > Global Sections > Region Modal.
You only need to add a new section: Region Popover.

Step 3 - Adding the Region Popover section

RegionPopover is a section that manages user location inputs. It's used when location data is missing or the store default postal code is applied. RegionPopover is available in @faststore/core and uses the Popover component as its UI base.
{"base64":"  ","img":{"width":2851,"height":1135,"type":"png","mime":"image/png","wUnits":"px","hUnits":"px","length":1097984,"url":"https://vtexhelp.vtexassets.com/assets/docs/src/regionpopover___dedb0aad756657e71d4c8d40cb2ef5e7.png"}}
RegionPopover code
packages/core/src/components/region/RegionPopover/RegionPopover.tsx

_174
import type { PopoverProps as UIPopoverProps } from '@faststore/ui'
_174
import {
_174
Icon as UIIcon,
_174
InputField as UIInputField,
_174
Link as UILink,
_174
Popover as UIPopover,
_174
useUI,
_174
} from '@faststore/ui'
_174
import { useRef, useState } from 'react'
_174
_174
import useRegion from '../RegionModal/useRegion'
_174
_174
import { sessionStore, useSession } from 'src/sdk/session'
_174
import { textToTitleCase } from 'src/utils/utilities'
_174
import styles from './section.module.scss'
_174
_174
interface RegionPopoverProps {
_174
title?: UIPopoverProps['title']
_174
closeButtonAriaLabel?: UIPopoverProps['closeButtonAriaLabel']
_174
inputField?: {
_174
label?: string
_174
errorMessage?: string
_174
noProductsAvailableErrorMessage?: string
_174
buttonActionText?: string
_174
}
_174
idkPostalCodeLink?: {
_174
text?: string
_174
to?: string
_174
icon?: {
_174
icon?: string
_174
alt?: string
_174
}
_174
}
_174
textBeforeLocation?: string
_174
textAfterLocation?: string
_174
description?: string
_174
triggerRef?: UIPopoverProps['triggerRef']
_174
onDismiss: UIPopoverProps['onDismiss']
_174
offsetTop?: UIPopoverProps['offsetTop']
_174
offsetLeft?: UIPopoverProps['offsetLeft']
_174
placement?: UIPopoverProps['placement']
_174
}
_174
_174
function RegionPopover({
_174
title = 'Set your location',
_174
closeButtonAriaLabel,
_174
inputField: {
_174
label: inputFieldLabel,
_174
errorMessage: inputFieldErrorMessage,
_174
noProductsAvailableErrorMessage: inputFieldNoProductsAvailableErrorMessage,
_174
buttonActionText: inputButtonActionText,
_174
},
_174
idkPostalCodeLink: {
_174
text: idkPostalCodeLinkText,
_174
to: idkPostalCodeLinkTo,
_174
icon: { icon: idkPostalCodeLinkIcon, alt: idkPostalCodeLinkIconAlt },
_174
},
_174
textBeforeLocation = 'Your current location is:',
_174
textAfterLocation = 'Use the field below to change it.',
_174
description = 'Offers and availability vary by location.',
_174
triggerRef,
_174
offsetTop = 6,
_174
offsetLeft,
_174
placement = 'bottom-start',
_174
}: RegionPopoverProps) {
_174
const inputRef = useRef<HTMLInputElement>(null)
_174
const { isValidating, ...session } = useSession()
_174
const { popover: displayPopover, closePopover } = useUI()
_174
const { city, postalCode } = sessionStore.read()
_174
const location = city ? `${textToTitleCase(city)}, ${postalCode}` : postalCode
_174
_174
const [input, setInput] = useState<string>('')
_174
_174
const { loading, setRegion, regionError, setRegionError } = useRegion()
_174
_174
const handleSubmit = async () => {
_174
if (isValidating) {
_174
return
_174
}
_174
_174
await setRegion({
_174
session,
_174
onSuccess: () => {
_174
setInput('')
_174
closePopover()
_174
},
_174
postalCode: input,
_174
errorMessage: inputFieldErrorMessage,
_174
noProductsAvailableErrorMessage:
_174
inputFieldNoProductsAvailableErrorMessage,
_174
})
_174
}
_174
_174
const idkPostalCodeLinkProps = {
_174
href: idkPostalCodeLinkTo,
_174
children: (
_174
<>
_174
{idkPostalCodeLinkText}
_174
{!!idkPostalCodeLinkIcon && (
_174
<UIIcon
_174
name={idkPostalCodeLinkIcon}
_174
aria-label={idkPostalCodeLinkIconAlt}
_174
width={20}
_174
height={20}
_174
/>
_174
)}
_174
</>
_174
),
_174
}
_174
_174
const RegionPopoverContent = (
_174
<>
_174
<span data-fs-region-popover-description>
_174
{postalCode ? (
_174
<>
_174
{textBeforeLocation} <span>{location}</span>. {textAfterLocation}
_174
</>
_174
) : (
_174
<>{description}</>
_174
)}
_174
</span>
_174
<UIInputField
_174
data-fs-region-popover-input
_174
id="region-popover-input-postal-code"
_174
inputRef={inputRef}
_174
label={inputFieldLabel}
_174
actionable
_174
value={input}
_174
onInput={(e) => {
_174
regionError !== '' && setRegionError('')
_174
setInput(e.currentTarget.value)
_174
}}
_174
onSubmit={handleSubmit}
_174
onClear={() => {
_174
setInput('')
_174
setRegionError('')
_174
}}
_174
buttonActionText={loading ? '...' : inputButtonActionText}
_174
error={regionError}
_174
/>
_174
{idkPostalCodeLinkTo && (
_174
<UILink data-fs-region-popover-link {...idkPostalCodeLinkProps} />
_174
)}
_174
</>
_174
)
_174
_174
return (
_174
<>
_174
{displayPopover.isOpen && (
_174
<div className={`${styles.section} section-region-popover`}>
_174
<UIPopover
_174
data-fs-region-popover
_174
title={title}
_174
isOpen={displayPopover.isOpen}
_174
content={RegionPopoverContent}
_174
placement={placement}
_174
dismissible
_174
triggerRef={triggerRef}
_174
offsetTop={offsetTop}
_174
offsetLeft={offsetLeft}
_174
closeButtonAriaLabel={closeButtonAriaLabel}
_174
onEntered={() => {
_174
if (!postalCode && inputRef.current) {
_174
inputRef.current.focus()
_174
}
_174
}}
_174
/>
_174
</div>
_174
)}
_174
</>
_174
)
_174
}
_174
_174
export default RegionPopover

Follow the steps below to add the RegionPopover section to Headless CMS.
  1. In the VTEX Admin, go to Storefront > Headless CMS > Global Sections.
  2. In the Sections tab, click + to open a modal with a list of section options.
  3. Search for the Region Popover section and click it to add it.
  4. Set the Title and Close popover aria-label fields with your values.
  5. Click Save to save your changes.
  6. Click Publish to open a dropdown list with the options Add to Release (to schedule the update) and Publish now (to publish immediately).

Step 4 - (Optional) Defining a default postal code

The default postal code is a fallback mechanism when users don't provide a location, aren't logged in, or have no saved address.
To set a default postal code for your store, follow the steps below:
  1. Open your FastStore project using the code editor of your choice.
  2. Open the discovery.config.js file.
  3. In the session object, set your default postalCode. See the example below:
    discovery.config.js

    _15
    session: {
    _15
    currency: {
    _15
    code: "USD",
    _15
    symbol: "$",
    _15
    },
    _15
    locale: "en-US",
    _15
    channel: '{"salesChannel":"1","regionId":""}',
    _15
    country: "USA",
    _15
    deliveryMode: null,
    _15
    addressType: null,
    _15
    city: null,
    _15
    postalCode: 10021,
    _15
    geoCoordinates: null,
    _15
    person: null,
    _15
    },

Managing Delivery Promise filters and labels

Delivery Promise filters help shoppers narrow products by delivery/pickup availability for their location, while badges visually indicate shipping/pickup availability for the shopper's location when Delivery Promise data exists.
By default, filters and badges are active once Delivery Promise is enabled and implemented in the store. However, you can deactivate them (Global Filter by Pickup Point, Delivery Option, and Badges and edit their labels in the Headless CMS. To do this, follow these steps.
For more details on filters and badges, see the Working with Delivery Promise components guide.
  1. Access the VTEX Admin and go to Storefront > Headless CMS.
  2. Click the Global Sections Content Type.
  3. Click the Settings tab.
  4. Go to the Delivery Promise section and change the labels and settings to suit your scenario.
{"base64":"  ","img":{"width":1327,"height":742,"type":"gif","mime":"image/gif","wUnits":"px","hUnits":"px","length":3564390,"url":"https://vtexhelp.vtexassets.com/assets/docs/src/dp-managing-filter-labels___8ced78ce723693085b3d8baa857ff5a6.gif"}}

Enabling the Availability (In-stock) filter

By default, the Availability filter is disabled in the Headless CMS. To enable this feature, follow these steps:

Setting up hideUnavailableItems

  1. Open your FastStore project in the code editor of your choice.
  2. Open the discovery.config.js file.
  3. In the hideUnavailableItems property, change the value to false.

    _10
    ...
    _10
    api: {
    _10
    storeId: "newstore",
    _10
    workspace: "master",
    _10
    environment: "vtexcommercestable",
    _10
    hideUnavailableItems: false,
    _10
    incrementAddress: false,
    _10
    },
    _10
    ...

  4. Create a new branch and open a pull request to deploy the change made in the discovery.config.js file to production.

Enabling the filter in the Headless CMS

After changing the hideUnavailableItems value to false, you can enable this filter in the Headless CMS.
  1. Access VTEX Admin and go to Storefront > Headless CMS.
  2. Click the Global Sections Content Type.
  3. Click the Settings tab.
  4. Go to the Delivery Promise section and check the field Should display In Stock filter?
{"base64":"  ","img":{"width":953,"height":325,"type":"png","mime":"image/png","wUnits":"px","hUnits":"px","length":35736,"url":"https://vtexhelp.vtexassets.com/assets/docs/src/dp-availability-filter___2fd389aefe66a4014d8bf9828ade58b1.png"}}
Contributors
2
Photo of the contributor
Photo of the contributor
Was this helpful?
Yes
No
Suggest Edits (GitHub)
Contributors
2
Photo of the contributor
Photo of the contributor
Was this helpful?
Suggest edits (GitHub)
On this page