Documentation Index
Fetch the complete documentation index at: https://docs.launchmystore.io/llms.txt
Use this file to discover all available pages before exploring further.
Local Pickup Options
local_pickup_options functions return a list of merchant-owned pickup
locations (store, warehouse, kiosk) that the customer can choose
instead of having the order shipped. Use it for:
- Buy-online-pickup-in-store (BOPIS).
- Curbside pickup at a specific retail address.
- “Pick up at our warehouse” for B2B customers.
For carrier-operated parcel lockers / partner pickup points (e.g.
DHL Packstation, UPS Access Point) use
pickup_point_options instead.
Manifest is honored; runtime dispatch is reserved. You may declare
local_pickup_options in your app.json and ship a .wasm today —
LaunchMyStore stores it, lints it, and surfaces it in the developer
portal. Wiring into the React checkout shipping step lands in the
delivery-options release; until then, returned options are not yet
shown to customers. Build now for forward-compat — your function will
start firing once the consumer is enabled.
Manifest
{
"type": "local_pickup_options",
"handle": "store-pickup",
"title": "In-store pickup",
"entrypoint": "dist/local-pickup.wasm",
"inputFields": {
"shippingAddress": ["countryCode", "city", "postalCode"]
}
}
Per-shop cap: 5 active local_pickup_options apps.
WASM execution timeout: 1500ms (configurable via
WASM_TIMEOUT_LOCAL_PICKUP_OPTIONS).
interface LocalPickupOptionsFunctionInput {
cart: {
id?: string;
lines: Array<{
id: string;
quantity: number;
merchandise: {
id: string;
productId: string;
sku?: string;
weight?: number;
attributes?: Record<string, string>;
};
cost: { subtotal: { amount: string; currencyCode: string } };
}>;
cost: {
subtotal: { amount: string; currencyCode: string };
total: { amount: string; currencyCode: string };
};
};
shippingAddress?: {
address1?: string;
city?: string;
province?: string;
countryCode?: string;
postalCode?: string;
latitude?: number;
longitude?: number;
};
currency: string; // ISO-4217 of the cart presentment currency
}
Output
interface LocalPickupOptionsFunctionOutput {
pickupOptions: Array<{
id: string; // stable id; surfaces on the order
title: string; // shown in checkout, e.g. "Downtown Store"
address: {
address1?: string;
address2?: string;
city?: string;
province?: string;
countryCode?: string;
postalCode?: string;
latitude?: number;
longitude?: number;
};
hours?: string; // free-text, e.g. "Mon–Fri 9–6, Sat 10–4"
distance?: number; // straight-line km from shippingAddress
fee?: number; // surcharge in cart currency (default 0)
}>;
}
Return an empty pickupOptions: [] to opt out of offering pickup for
this cart (e.g. when the cart contains items not stocked at any pickup
location).
Example — Two retail locations, distance-sorted
const LOCATIONS = [
{
id: 'store-downtown',
title: 'Downtown Store',
address: {
address1: '123 Market St',
city: 'San Francisco',
province: 'CA',
countryCode: 'US',
postalCode: '94103',
latitude: 37.7749,
longitude: -122.4194,
},
hours: 'Mon-Fri 9-6, Sat 10-4',
},
{
id: 'store-mission',
title: 'Mission Store',
address: {
address1: '456 Valencia St',
city: 'San Francisco',
province: 'CA',
countryCode: 'US',
postalCode: '94110',
latitude: 37.7599,
longitude: -122.4214,
},
hours: 'Daily 10-8',
},
];
function haversine(a, b) {
if (!a || !b) return undefined;
const R = 6371;
const toRad = (d) => (d * Math.PI) / 180;
const dLat = toRad(b.latitude - a.latitude);
const dLon = toRad(b.longitude - a.longitude);
const h =
Math.sin(dLat / 2) ** 2 +
Math.cos(toRad(a.latitude)) *
Math.cos(toRad(b.latitude)) *
Math.sin(dLon / 2) ** 2;
return Math.round(2 * R * Math.asin(Math.sqrt(h)));
}
export default function main(input) {
const ship = input.shippingAddress;
const country = ship?.countryCode;
const pickupOptions = LOCATIONS.filter(
(loc) => !country || loc.address.countryCode === country,
)
.map((loc) => ({
...loc,
distance: ship ? haversine(ship, loc.address) : undefined,
fee: 0,
}))
.sort((a, b) => (a.distance ?? Infinity) - (b.distance ?? Infinity));
return { pickupOptions };
}
Persistence
Selected pickup option is stored on the order at
additionalFields.localPickupOption:
{
"localPickupOption": {
"appHandle": "my-pickup-app",
"functionHandle": "store-pickup",
"id": "store-downtown",
"title": "Downtown Store",
"address": { "address1": "123 Market St", "city": "San Francisco", "..." },
"hours": "Mon-Fri 9-6, Sat 10-4",
"fee": 0
}
}
The shipping address on the order is set to the merchant location
address so fulfillment / tax / invoicing flow downstream as if it were a
standard ship-to order.
When customers see what
The pickup options returned here are shown as a third grouping in
the checkout shipping-step UI, alongside merchant zones (server-side)
and shipping_rate function rates (app-side):
| Source | Group in checkout |
|---|
| Merchant shipping zones | ”Delivery” |
shipping_rate functions | ”Delivery” (mixed in with merchant) |
local_pickup_options | ”Pickup in store” |
pickup_point_options | ”Pickup at a parcel point” |
The customer picks one. The chosen group determines which post-purchase
emails the merchant sends (order_ready_for_pickup vs. order_shipped).
See also