Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

Buy online, pickup in store

Buy online, pickup in store (BOPIS) is a popular fulfillment option that allows customers to purchase items online and pick them up in-store.

The Commerce boilerplate template does not include a BOPIS checkout flow by default, but you can easily implement one using Adobe’s drop-in components.

Step-by-step

The following steps describe how to modify the commerce-checkout.js block file in the boilerplate template to allow users to choose between delivery and in-store pickup during the checkout process.

Prerequisites

Before you start, you must configure in-store delivery options in the Adobe Commerce Admin to define pickup locations. The fetchPickupLocations function retrieves the list of available pickup locations using a GraphQL query.

Update content fragment

  1. To create a new section for the delivery options, additional DOM elements are required. You can add these elements by modifying the content fragment.

    <div class="checkout__delivery-method">
    <h2 class="checkout-delivery-method__title">Delivery Method</h2>
    <div class="checkout-delivery-method__toogle-buttons">
    <div class="checkout-delivery-method__delivery-button"></div>
    <div class="checkout-delivery-method__in-store-pickup-button"></div>
    </div>
    </div>
    <div class="checkout__in-store-pickup"></div>
  2. You must also add new selectors to render the required components and content.

    export const $deliveryButton = fragment.querySelector('.checkout-delivery-method__delivery-button');
    export const $inStorePickupButton = fragment.querySelector('.checkout-delivery-method__in-store-pickup-button');
    export const $inStorePickup = fragment.querySelector('.checkout__in-store-pickup');

    Update content fragment

Add toggle buttons

During initialization, the code renders two buttons:

  • Delivery
  • In-store pickup

These buttons allow users to toggle between the two options.

UI.render(ToggleButton, {
label: 'Delivery',
onChange: () => onToggle('delivery'),
})($deliveryButton)
UI.render(ToggleButton, {
label: 'In-store Pickup',
onChange: () => onToggle('in-store-pickup'),
})($inStorePickupButton)

Toggle buttons

Toggle between options

The onToggle function manages switching between the delivery and in-store pickup options. It updates the selected state of the buttons and toggles the visibility of the corresponding forms.

async function onToggle(type) {
if (type === 'delivery') {
deliveryButton.setProps((prev) => ({ ...prev, selected: true }));
inStorePickupButton.setProps((prev) => ({ ...prev, selected: false }));
$shippingForm.removeAttribute('hidden');
$shippingMethods.removeAttribute('hidden');
$inStorePickup.setAttribute('hidden', '');
} else {
inStorePickupButton.setProps((prev) => ({ ...prev, selected: true }));
deliveryButton.setProps((prev) => ({ ...prev, selected: false }));
$shippingForm.setAttribute('hidden', '');
$shippingMethods.setAttribute('hidden', '');
$inStorePickup.removeAttribute('hidden');
}
}

Fetch pickup locations

The fetchPickupLocations function retrieves the list of available pickup locations using a GraphQL query. Users can choose a location where they’d like to pick up their order.

async function fetchPickupLocations() {
return checkoutApi
.fetchGraphQl(
`query pickupLocations {
pickupLocations {
items {
name
pickup_location_code
}
total_count
}
}`,
{ method: 'GET', cache: 'no-cache' }
)
.then((res) => res.data.pickupLocations.items);
}

Render location options

After the code fetches the pickup locations, it renders options as radio buttons. The user can select a location, which updates the shipping address with the corresponding pickup location code.

const pickupLocations = await fetchPickupLocations();
pickupLocations.forEach((location) => {
const { name, pickup_location_code } = location;
const locationRadiobutton = document.createElement('div');
UI.render(RadioButton, {
label: name,
value: name,
onChange: () => {
checkoutApi.setShippingAddress({
address: {},
pickupLocationCode: pickup_location_code,
});
},
})(locationRadiobutton);
$inStorePickup.appendChild(locationRadiobutton);
});

Pick up location options

Finalize the flow

After a user selects In-store pickup and chooses a location, the pickup form is shown, while the shipping form is hidden. This provides a clear and seamless way for users to choose how they want to receive their order.

Example

See blocks/commerce-checkout-bopis in the demos branch of the boilerplate repository for complete JS and CSS code for the BOPIS checkout flow.