Skip to content

Developer mode — Shopify checkout integration API

Use Developer mode when another app or custom checkout script conflicts with HK Pickup’s automatic checkout intercept, or when you need full control over when the delivery dialog opens and how checkout continues.

Install HK Pickup on the Shopify App Store →


Situation Developer mode
Single HK Pickup install, default checkout Off (recommended)
Another app intercepts checkout On — you wire hkpickup.open() yourself
Custom checkout / headless flow On — listen for hkpickup:* events

With Developer mode on, HK Pickup does not bind checkout buttons. Checkout clicks go to Shopify unless you add custom JavaScript.

Need custom “who sees the dialog” logic with your own JavaScript? Use Developer mode. For normal live checkout while migrating from another pickup app, use Pilot mode instead — no custom code required.


  1. Online Store → Themes → Customize
  2. App embeds → HK Pickup
  3. Turn on Developer mode
  4. Save

Responsibility Owner
Show delivery dialog UI HK Pickup (when you call open())
Write cart attributes (_sf_delivery_mode, _sf_pickup_*) HK Pickup — before home / confirm events
Navigate to checkout / submit cart form You (integrator)

If /cart/update.js fails, HK Pickup shows an error in the dialog and does not fire home or confirm events.


Available only when Developer mode is on.

Member Description
isReady true after init and storefront config load
open() Reset to step 1, show dialog, fire hkpickup:open
close(options?) { force?: boolean } — closes dialog; fires non-cancelable hkpickup:close with reason: 'api'. Use force: true after async work when you previously blocked a home/confirm close

All events are document CustomEvents with prefix hkpickup:.

Register listeners after hkpickup:ready (or check window.hkpickup?.isReady).

Event When detail
hkpickup:ready Init complete { developerMode: true, locale }
hkpickup:open Dialog opened via open() { source: 'api' }
hkpickup:close Before dialog closes (dev mode) { reason } — see cancelable rules below
hkpickup:home Home delivery chosen (attrs cleared) { cartAttributes }
hkpickup:back Back from SF list → step 1 {}
hkpickup:location-select SF row selected { store }
hkpickup:confirm SF Confirm (attrs saved) { store, checkoutUrl, cartAttributes }

Not fired: step-1 “SF Express pickup” (internal only), filter/search changes.

{
"code": "H852K067P",
"type": "store",
"category": "store",
"name": "SF Station …",
"address": "",
"region": "Hong Kong Island",
"city": "Central",
"district": "Central"
}
Key Home Pickup
_sf_delivery_mode home pickup
_sf_pickup_code "" SF code
_sf_pickup_type "" Service type
_sf_pickup_address "" Address
_sf_pickup_region "" Region
_sf_pickup_district "" District
_sf_pickup_locale "" zh-HK / zh-CN / en-US

Only home and confirm close reasons are cancelable. Listeners may call event.preventDefault() synchronously to keep the dialog open (e.g. while another plugin runs).

detail.reason Cancelable? Behavior
home Yes After hkpickup:home
confirm Yes After hkpickup:confirm
dismiss No X button or backdrop — always closes
api No hkpickup.close() — always closes

Async pattern:

document.addEventListener('hkpickup:close', (e) => {
if (e.detail.reason !== 'confirm') return
e.preventDefault()
runOtherPlugin().finally(() => window.hkpickup.close({ force: true }))
})

Event order (home / confirm): cart attrs saved → hkpickup:home or hkpickup:confirm → cancelable hkpickup:close → close unless prevented.


Dawn example — intercept checkout yourself

Section titled “Dawn example — intercept checkout yourself”

Add to theme custom JavaScript (or your app’s asset):

document.addEventListener('hkpickup:ready', () => {
document.querySelectorAll('button[name="checkout"]').forEach((btn) => {
btn.addEventListener('click', (e) => {
e.preventDefault()
window.hkpickup.open()
})
})
})
document.addEventListener('hkpickup:home', () => {
window.location.href = '/checkout'
})
document.addEventListener('hkpickup:confirm', (e) => {
window.location.href = e.detail.checkoutUrl
})

Adjust selectors for your theme if checkout buttons differ.


Paste in DevTools console, then reload:

;['ready','open','close','home','back','location-select','confirm'].forEach((n) =>
document.addEventListener(`hkpickup:${n}`, (e) =>
console.log(`hkpickup:${n}`, e.detail, e.cancelable ? '(cancelable)' : '')
)
)

After wiring checkout, run the same checks in Verify checkout.