This guide details how to integrate HubBox pickup point selection into your BigCommerce store using the HubBox Tag script added via BigCommerce's built-in Script Manager. This is the standard approach for integrating frontend features like HubBox on the BigCommerce platform.
For full details on the HubBox Tag, refer to the Tag documentation.
Tag documentation
| Requirement | Details |
|---|---|
| BigCommerce Admin access | Access to your store admin panel with permissions to manage Storefront > Script Manager |
| HubBox Tag script | The JavaScript snippet provided by your HubBox Integrations Manager — unique to your account |
Before you begin, ensure you have the correct HubBox Tag script from your HubBox Integrations Manager. This JavaScript snippet contains your unique configuration ID and the logic required to display and manage the HubBox pickup point selection interface on your BigCommerce checkout.
You can access the Tag script via Console by going to "Setup" and then "Tag Management" in the menu.
Log in to your BigCommerce Admin panel and navigate to Storefront > Script Manager in the left-hand menu.
If you manage multiple storefronts via Channel Manager, navigate to Channel Manager > Channels > Your Storefront > Scripts instead.
Click the Create a Script button and configure the settings as follows:
| Setting | Value |
|---|---|
| Name of script | HubBox Tag - Checkout |
| Description | (Optional) Loads HubBox pickup point selector on checkout |
| Location on page | Footer — ensures the script loads after the main page content is available |
| Select pages where script will be added | Checkout |
| Script category | Essential — HubBox is part of the essential checkout functionality |
| Script type | Script |


In the Script contents text box, paste the entire HubBox Tag script provided by HubBox. Ensure it is pasted exactly as received — do not modify the script.

Click Save.

Thorough testing is essential before making HubBox live for all customers. HubBox provides a built-in test mode within the Tag script.
Locate the config object within the HubBox Tag script in Script Manager. Ensure the mode property is set to "test":
config: {
mode: "test", // Set to "test" for testing
// ... other configuration options ...
}
Save the script changes in Script Manager.
When mode is set to "test", the HubBox widget only appears when a specific query parameter is appended to your checkout URL. Navigate to your store's checkout page and add ?hubboxPayloadTest=true to the end of the URL:
yourstore.mybigcommerce.com/checkout?hubboxPayloadTest=true
This allows you to see and interact with the HubBox integration without affecting regular customers.
Work through the following checklist during testing:
If you have a BigCommerce sandbox or staging environment, test there first before testing on your live site using the test mode parameter.
Once you have thoroughly tested the integration and are confident it is working correctly:
Edit the HubBox Tag script in Script Manager and change the mode property from "test" to "live":
config: {
mode: "live", // Set to "live" for deployment
// ... other configuration options ...
}
Click Save in Script Manager.
The HubBox pickup option will now be visible and available to all customers reaching your checkout page.
The HubBox Tag script includes a config object where advanced features such as product eligibility filtering and shipping rate filtering can be configured.
Use this feature to prevent the HubBox pickup option from appearing when the cart contains items unsuitable for pickup (e.g., oversized, hazardous, or high-value items). This is configured using the callbacks.getShouldBailOut function within the Tag script's config.
The function must return true to hide HubBox ("bail out") or false to show it. It typically inspects the current cart via BigCommerce Storefront APIs and applies your business logic. For guidance on eligibility strategy, refer to the /docs/product-eligibility.
The examples below should be added within config.callbacks in your HubBox Tag script.
This example uses the BigCommerce Storefront GraphQL API to check inventory for all items in the cart.
callbacks: {
getShouldBailOut: () =>
new Promise((resolve) => {
const getCart = (url) =>
fetch(url, { method: "GET", credentials: 'include' })
.then((response) => response.json())
.catch((error) => console.error(error));
const fetchProductData = (productIds, variantIds, apiToken) =>
fetch("/graphql", {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiToken}`
},
body: JSON.stringify({
query: `query ProductInventory{site{products(entityIds:${JSON.stringify(productIds)}){edges{node{entityId name variants(entityIds:${JSON.stringify(variantIds)}){edges{node{entityId sku inventory{aggregated{availableToSell warningLevel}}}}}}}}}}}`
})
})
.then((res) => res.json())
.catch((error) => console.error(error));
getCart("/api/storefront/carts?include=lineItems.physicalItems.options")
.then((cartData) => {
const productMap = {};
cartData?.[0]?.lineItems?.physicalItems?.forEach((item) => {
const productId = item.productId;
if (!Array.isArray(productMap[productId])) productMap[productId] = [];
productMap[productId].push(item.variantId);
});
return productMap;
})
.then((productMap) => {
const productIds = Object.keys(productMap).map(Number);
const variantIds = productIds.flatMap(key => productMap[key]);
const storefrontApiToken = "{{ settings.storefront_api.token }}";
if (!storefrontApiToken) {
console.error("Storefront API Token not available");
return Promise.reject("No API Token");
}
return fetchProductData(productIds, variantIds, storefrontApiToken);
})
.then((gqlResponse) =>
gqlResponse.data.site.products.edges.flatMap(pEdge =>
pEdge.node.variants.edges.flatMap(vEdge => vEdge.node.inventory)
)
)
.then((inventories) => inventories.every((i) => i.aggregated?.availableToSell > 0))
.then((areAllItemsInStock) => resolve(!areAllItemsInStock))
.catch(() => resolve(false));
})
}
The {{ settings.storefront_api.token }} Handlebars syntax may not be available in all Script Manager contexts. If it is not available, you will need to pass the Storefront API token via an alternative method.
This example fetches the cart via the REST API and checks whether any item's SKU matches a predefined list of ineligible SKUs.
callbacks: {
getShouldBailOut: () => new Promise(resolve => {
fetch('/api/storefront/cart', { credentials: 'include' })
.then(response => response.json())
.then(cartArray => {
const nonAcceptableSkuList = ['SKU-TO-BLOCK-1', 'SKU-TO-BLOCK-2']; // Define your ineligible SKUs
const cartItems = cartArray?.[0]?.lineItems?.physicalItems ?? [];
const cartSkuList = cartItems.map(item => item?.sku);
const nonAcceptableSkuExists = cartSkuList.some(cartSku =>
nonAcceptableSkuList.includes(cartSku)
);
resolve(nonAcceptableSkuExists); // Bail out if an ineligible SKU exists
})
.catch(() => resolve(false)); // Default to not bailing out on error
}),
}
Example 3: Hide pickup based on a product metafield (e.g., `shipping-groups` contains "large")
This example fetches cart items and then retrieves metafields for each product to check for ineligible shipping groups.
Fetching metafields for multiple products efficiently typically requires a custom backend endpoint or the Storefront GraphQL API (if metafields are exposed there). The fetchMetafields function below uses a placeholder endpoint — you will need to adapt this to your own implementation. Refer to the BigCommerce developer documentation for guidance on accessing metafields.
callbacks: {
getShouldBailOut: () =>
new Promise(async (resolve) => {
try {
const getCart = (url) =>
fetch(url, { method: "GET", credentials: 'include' })
.then(response => response.json())
.catch(error => console.error("Cart fetch error:", error));
const cartData = await getCart("/api/storefront/carts?include=lineItems.physicalItems.options");
const productIds = cartData?.[0]?.lineItems?.physicalItems?.map(item => item.productId) ?? [];
if (productIds.length === 0) {
resolve(false); // Empty cart, don't bail out
return;
}
const fetchMetafields = async (productId) => {
// Replace with your actual method to fetch metafields for a product ID
const apiEndpointUrl = "/your-custom-metafield-endpoint/"; // EXAMPLE ONLY
const response = await fetch(`${apiEndpointUrl}?productId=${productId}`);
const data = await response.json();
return data.metafields || [];
};
const allMetafields = await Promise.all(productIds.map(fetchMetafields));
const flatMetafields = allMetafields.flat();
const hasLargeItem = flatMetafields.some(mf => {
if (mf.key === 'shipping-groups') {
try {
const groups = JSON.parse(mf.value);
return Array.isArray(groups) && groups.some(group => group.toLowerCase() === 'large');
} catch (e) {
console.error("Error parsing shipping-groups metafield", e);
return false;
}
}
return false;
});
resolve(hasLargeItem); // Bail out if a 'large' item exists
} catch (error) {
console.error("Error in getShouldBailOut:", error);
resolve(false); // Default to not bailing out on error
}
})
}
Use this feature to show or hide specific shipping rate options on the BigCommerce checkout page based on whether the customer selects Home Delivery or HubBox Pickup. This is configured within the config.selectors.shippingMethods object in your HubBox Tag script.
config: {
// ... mode, key, etc. ...
selectors: {
shippingMethods: {
wrapper: "#checkout-shipping-options",
interactionPreventionAction: "hide li",
excludeOnLocalPickup: [
{
selectors: [
"text-fragment: Royal Mail",
],
}
],
excludeOnHomeDelivery: [
{
selectors: [
"text-fragment: Pickup",
],
}
],
},
}
// ... callbacks, etc. ...
}
Once the HubBox Tag script is correctly implemented and live:

?hubboxPayloadTest=true to the checkout URL and that mode is set to "test" in the script config.configId within the script is correct for your environment.nearest or within in request URLs).console.log statements within your callback to trace the execution path and confirm the cart data is being fetched correctly..catch() block to resolve false (not bail out).wrapper selector (#checkout-shipping-options) matches the actual element on your checkout page — this may differ depending on your theme.text-fragment values in excludeOnLocalPickup and excludeOnHomeDelivery match the exact text displayed for each shipping method on your checkout.