Bird Pickup & Delivery Bird Pickup & Delivery
On this page
Developer

Widget API Reference

B
Written by Bird Pickup & Delivery
Updated October 23, 2026

You don’t need this page to use Bird. On a Shopify theme the widget works on its own, and headless stores only need the 3-step install. Use this page when you want to do something extra with the customer’s choice.

1. Listen for changes

Runs every time the customer changes their choice:

window.addEventListener('bird:selection:changed', ({ detail }) => {
  console.log(detail.field, detail.value, detail.selection);
});

detail.selection is { method, locationId, zip, date, time }. Add the listener before the widget loads, or inside bird:widget:initialized.

2. Subscribe to the full state

Runs now, then on every change:

const sdk = await BirdApp.ready;
sdk.subscribe((state) => console.log(state.selection));

state also has isSyncing, saveError and checkout: { canProceed, reason }.

3. Check if checkout can go ahead

sdk.selections.canCheckout().canProceed; // true or false

When it’s false, canCheckout().reason says why: selection_incomplete, minimum_order_value_not_met, cart_ineligible, schedule_conflict, not_ready, saving or save_failed.

On a Shopify theme Bird already blocks checkout for you. To block it yourself and show the customer what’s missing, see Block checkout.

The customer’s choice

sdk.selections.current holds what the customer picked, or null:

💡
Field Value
method 'Pickup', 'Delivery' or 'Shipping'
date YYYY-MM-DD
time HH:mm or HH:mm-HH:mm
locationId Bird location id (also locationName, locationAddress)
note Order note
customerLocation Delivery address (holds the zip)

Events

Event data is on event.detail.

💡
Event Fires when Listen on detail
bird:selection:changed Any part of the choice changes window { field, value, selection }
bird:selection:complete The choice is complete window { method, locationId, date, time }
bird:cart:changed The cart changes window { cart: { itemCount, totalPrice, items } }, totalPrice in cents
bird:checkout:attempted Checkout was blocked window none
bird:widget:initialized The widget first appears document { mountCount }
bird:widget:reinitialized The widget appears again (for example after a cart redraw) document { mountCount }
bird:widget:removed The widget leaves the page document none

Custom storefronts only

On a Shopify theme Bird handles all of this itself.

Mount

const bird = await BirdApp.widget.mount(el);                                              // cart widget
const product = await BirdApp.widget.mount(el, { type: 'product', item: { variantId } }); // product widget

el is any element. variantId can be a number or a gid://shopify/ProductVariant/… id. mount() returns { destroy(), isMounted(), reportValidity() }.

Block checkout

if (bird?.reportValidity() === false) event.preventDefault();

bird is the handle from mount(). It shows the customer what’s missing and returns false. Don’t disable the button instead: the tap is what shows the message.

Pass your data

sdk.setCart(cart);                             // your Storefront API cart, on every change
sdk.setCustomer({ id, tags, loggedIn: true }); // for customer-tag rules
sdk.setLocale('fr');                           // widget language

Was this article helpful?