HubBox can be implemented on a BigCommerce site via the HubBox Tag script - this is a piece of JavaScript that is added to the checkout via BigCommerce's Script Manager functionality.
For more information on Tag and customization features, please refer to the Tag documentation.
To add the script in BigComemrce you will need to go to the Script Manager by clicking on ‘Storefront’ in the left-hand menu and then ‘Script Manager’. If you have multiple channels, you may first need to go to 'Channel Manager' and then 'Scripts'. Once in the Script Manager, follow the below steps:
Settings | |
---|---|
Location on page | Footer |
Select pages where script will be added | Checkout |
Script category | Essential |
Script type | Script |
The HubBox Integrations team, they will provide you with your Tag script. You will need to add this to your checkout and test.
If you do not have a test site, you can add the script to your live site with the below added to the config
of the Tag script.
mode: "test",
When mode
is set to "test"
you will need to add the below string to the end of the checkout URL in order to view the Tag. This stops live customers from seeing the integration whilst you are testing.
?hubboxPayloadTest=true
The URL will look like this, for example: https://hubbox-store.com/checkout?hubboxPayloadTest=true
Once testing is completed you can then set mode
to "live"
and customers will be able to see the pickup option.
Retailers with diverse product catalogs may be required to exclude certain products from the pickup service. In this instance, you will need to hide the pickup option for baskets that contain ineligible items. For example, if the customer has an item in their basket that is too large for a pickup location, you will need to ensure that they cannot see the pickup option at checkout. To implement this behavior we can use the bailoutOnCondition
callback which will "bailout" the Tag script based on certain criteria.
Below are some BigCommerce examples of using the bailoutOnCondition
callback to hide the pickup UI. Please note the callbacks sit within the config
of the Tag script.
callbacks: {
bailoutOnCondition: () =>
new Promise((resolve) => {
const getCart = (url) =>
fetch(url, { method: "GET" })
.then((response) => response.json())
.catch((error) => console.error(error));
const fetchProductData = (productIds, variantIds) =>
fetch("/graphql", {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer {{ settings.storefront_api.token }}`
},
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((data) => {
const productMap = {};
data.forEach((d) =>
d.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 keys = Object.keys(productMap).map((key) => Number(key));
return fetchProductData(
keys,
keys.flatMap((key) => productMap[key])
);
})
.then((data) =>
data.data.site.products.edges.flatMap((productEdge) => productEdge.node.variants.edges.flatMap((variantEdge) => variantEdge.node.inventory))
)
.then((inventories) => inventories.every((i) => i.aggregated?.availableToSell > 0) === true)
.then((areAllItemsInStock) => resolve(!areAllItemsInStock))
.catch(() => resolve(false));
});
}
callbacks: {
bailoutOnCondition: () => new Promise(resolve => {
fetch('/api/storefront/cart', {
credentials: 'include'
}).then((response) => {
return response.json();
}).then((cartArray) => {
const nonAcceptableSkuList = ['ABC123','XYZ987',];
const cartSkuList = cartArray.shift()?.lineItems?.physicalItems.map(item => item?.sku);
const nonAcceptableSkuExists = cartSkuList.some(cartSku => nonAcceptableSkuList.includes(cartSku));
resolve(nonAcceptableSkuExists);
}).catch(() => resolve(false));
}),
}
callbacks: {
bailoutOnCondition: () =>
new Promise(async (resolve) => {
const getCart = (url) =>
fetch(url, { method: "GET" })
.then((response) => response.json())
.catch((error) => console.error(error));
const cartData = await getCart("/api/storefront/carts?include=lineItems.physicalItems.options");
// noinspection JSUnresolvedReference
const productIds = cartData.flatMap((d) => d.lineItems.physicalItems.map((item) => item.productId));
const apiEndpointUrl = "https://api.bigcommerce.hub-box.com/v1/tag/product/metafield";
const storeHash = "hkpifbogfq";
const results = await Promise.all(
productIds.map((productId) =>
fetch(`${apiEndpointUrl}?storeHash=${storeHash}&productId=${productId}`)
.then((response) => response.json())
.then((dataContainer) => dataContainer["data"])
)
);
const doesMediumExist = results
.flat(2)
.filter((item) => item.key === "shipping-groups")
.map((item) => JSON.parse(item.value))
.some((shippingGroups) => shippingGroups.some((shippingGroup) => shippingGroup.toLowerCase() === "large"));
resolve(doesMediumExist);
});
}
If you use multiple carriers or wish to offer pickup at a different price or service level, you will need to show and hide particular shipping rates depending on whether the customer has chosen home delivery or pickup.
In order to manage and filter the rates that are displayed to a customer when pickup is selected, you can use the shippingRates
configuration and using xpath set the rates you wish to show/hide. The HubBox Integrations team can help you configure this for your site.
Below is an example of the shippingRates
configuration hiding the "Standard Home Delivery rate" if a pickup location is chosen and hiding the "Stanard Pickup" rate if home delivery is being used by the customer. The shippingRates
configuration sits within the selectors
which sits inside the config
.
shippingRates: {
wrapper: "#checkout-shipping-options",
hiddenShippingRates: {
network: [
"xpath://*[contains(@class, 'form-checklist-header')][div/label/div/div/span[contains(text(),'Standard Delivery')]]",
],
},
hiddenPickupRates: {
network: [
"xpath://*[contains(@class, 'form-checklist-header')][div/label/div/div/span[contains(text(),'Pickup Delivery')]]",
],
},
}
shippingMethods: {
excludeOnLocalPickup: [{
networks: ["ups", "dpd"],
selectors: [
"xpath://*[contains(@class, 'form-checklist-header')][div/label/div/div/span[contains(text(),'Standard Delivery')]]"
],
"mode": "first"
}, {
selectors: [
"xpath://any"
],
"mode": "all"
}],
excludeOnHomeDelivery: [{
selectors: [
"xpath://*[contains(@class, 'form-checklist-header')][div/label/div/div/span[contains(text(),'Pickup Delivery')]]",
".two",
".three"
]
}]
}
HubBox can also offer additional features upon request:
These features require HubBox customization so please contact the HubBox Integrations team if you would like to find out more at clientsupport@hub-box.com.
Once the Tag has been setup and the script has been added to your checkout, your customers will see the pickup option presented in the checkout. If the customer clicks the pickup option, they will be able to search for, view and select an available pickup location.
Once the customer has selected a location, they will complete checkout as normal. The shipping address
will be the customer's chosen pickup location address.
If you have any issues during set up, please contact clientsupport@hub-box.com.