Skip to content

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.