The full pickup/delivery date & time scheduler on any storefront — Hydrogen, React, Vue, or plain HTML. One script, one mount call. No theme, no build step, no npm.
Both widgets are the real thing — a selection on the product page carries into the cart.
Hand-tied · locally sourced
<!-- 1. styles + config, then the bundle -->
<link rel="stylesheet" href="https://cdn.birdchime.com/widget/bird.bundle.css">
<script>
window.BirdApp = { config: { shop: 'your-store.myshopify.com' } };
</script>
<script src="https://cdn.birdchime.com/widget/bird.bundle.js" defer></script>
// 2. mount once ready (mount is async)
await window.BirdApp.ready;
const handle = await window.BirdApp.widget.mount(el);
// 3. keep the cart in sync — pass your Storefront cart as-is
window.BirdApp.sdk.setCart(cart);
window.BirdApp objectOne global, four members — you set config; the bundle fills in the rest.
window.BirdApp = {
config, // you set this — { shop, locale?, customer? }
ready, // Promise<sdk | null> — await before mounting
sdk, // BirdSDK instance (or null) — sdk.setCart(cart)
widget, // { mount(container, options?) }
}
window.BirdApp.config — set it before the script loads. Only shop is required; everything else (settings, translations, timezone, availability rules) is fetched automatically.
| Field | Required | Notes |
|---|---|---|
shop | yes | Your *.myshopify.com domain |
locale | no | Defaults to 'en' |
customer | no | { id, tags, loggedIn } — needed only if the merchant uses customer-tag availability rules |
widget.mount(container, options?) → Promise<MountHandle | null>. Default type is 'cart'; pass { type: 'product', item } for a product page. The handle is { destroy(), isMounted(), remount? }. Resolves null if mounting couldn't complete (check the console).
Call sdk.setCart(cart) on load and whenever the cart changes. Pass your Storefront-API cart object as-is.
window.BirdApp exists only client-side — never reference it during server render (in Hydrogen, mount inside a useEffect).ready never rejects. On init failure it resolves null (and mount() then resolves null) — check for null, don't .catch().defer and CDN-cached — it never blocks your page render.