HubBox Software Development Kit (SDK) Integration

This guide covers integrating HubBox pickup point functionality into custom-built ecommerce websites, headless commerce setups, or heavily customised platform checkouts using the HubBox Software Development Kit (SDK).

The SDK offers the highest degree of flexibility and control over the user experience and integration logic, allowing you to embed HubBox features within your unique checkout flow. This approach requires frontend development to interact with HubBox components and backend development to handle data persistence, filtering logic, and order processing.

SDK vs. Tag: If you need a quicker, lower-code frontend solution with less customisation required, consider the HubBox Tag solution. The SDK provides maximum control but involves more development effort.


Prerequisites


Reference Guides

You need to be logged in to Console to access the above documentation.


Core Concepts

The SDK integration involves several key pieces working together:

  1. Launch Experience UI - You design and build the UI elements within your checkout that allow the customer to choose between Home Delivery and Local Pickup (e.g., buttons, toggles, radio options, or a shipping method choice). Alternatively, you can implement this UI using HubBox's pre-built web components for a toggle launch experience.

  2. HubBox Map Widget (SingleWidgetManager) - The core piece, managed by the @hubbox/single-widget-manager JavaScript library, loads and displays the interactive map and list of pickup locations within an iframe. It can be presented either embedded directly on the page or within a modal pop-up.

  3. Event-Driven Communication - Your frontend JavaScript interacts with the SingleWidgetManager using a publish/subscribe event system (events.subscribe, events.emit) to trigger searches, open the widget, and receive data about the user's selection.

  4. Configuration - Key settings like your configId (defining networks, styling), locale, and environment (sandbox/production) are passed during initialisation of the SingleWidgetManager.

  5. Backend Interaction (Retailer Built) - Your frontend JavaScript communicates the selected pickup point data (address, ID, network) to your backend server (e.g., via AJAX/Fetch). Your backend logic must then:

    • Update the user's session or cart/checkout object with the chosen location data and pickup flag.
    • Potentially filter available shipping rates based on the pickup selection.
    • Persist the HubBox location details when the order is placed.
  6. Order Data Sharing - Sending details of completed pickup orders back to HubBox via the Order Processing API or Tracking Pixel allows you to leverage HubBox data dashboards.


Integration Steps

Installation

Install the necessary HubBox packages into your frontend project using NPM or Yarn:

npm install @hubbox/single-widget-manager @hubbox/web-components
# or
yarn add @hubbox/single-widget-manager @hubbox/web-components

If you don't use NPM or Yarn, contact HubBox Integrations for CDN URLs or minified versions.

If using TypeScript or certain module bundlers, import the packages as follows:

import SingleWidgetManager from '@hubbox/single-widget-manager';
import "@hubbox/web-components"; // Imports and registers custom elements like <hubbox-modal>

Design and Implement the Launch Experience UI

Before initialising the widget, decide how customers will opt into pickup and build the corresponding UI.

Choose a pattern:

You can build this UI using standard HTML elements (buttons, radio inputs, search fields) with appropriate event listeners, or use the pre-built /docs/hubbox-components/components-installation such as <hubbox-local-pickup-toggles>, <hubbox-home-delivery-toggles>, <hubbox-local-pickup-multi-button>, and <hubbox-home-delivery-multi-button>.

Pickup as a Shipping Method Pickup as Toggles

This approach presents HubBox pickup options directly alongside your standard home delivery rates within the shipping method selection step of your checkout.

shipping-method-ux-sdk

User flow:

  1. Customer enters their shipping address.
  2. Your ecommerce platform calculates available shipping methods based on the address, cart contents, and your backend configuration. This list includes both your standard home delivery rates and the specific pickup point rate(s) you've configured (e.g., "Standard Pickup").
  3. The checkout frontend displays this list of shipping methods, typically as radio buttons or selectable options.
  4. If the customer selects a shipping method designated as a HubBox pickup option:
    • Your frontend JavaScript detects this specific selection.
    • The HubBox SDK map widget (usually modal) is triggered, allowing the customer to choose a specific location for that selected service.
  5. Once a location is confirmed via the SDK, its details are stored, and the customer proceeds to payment with the pickup rate and location selected.

Key considerations:

This pattern presents customers with a clear, high-level choice between "Home Delivery" and "Pickup Points" early in the shipping step, often before they interact with the main shipping address form fields.

toggles-ux-sdk

User flow:

  1. Customer arrives at the shipping stage of the checkout.
  2. They are immediately presented with distinct options, usually styled as clickable boxes, tabs, or large radio buttons (referred to as "toggles"), labelled e.g., "Deliver to my Address" and "Collect from Pickup Point".
  3. If the customer selects "Pickup":
    • The UI visually highlights the pickup choice.
    • The standard home delivery address input fields are typically hidden or disabled via JavaScript.
    • The HubBox map widget (usually modal) is triggered, prompting the user to search for and select a specific pickup location.
    • Once a location is confirmed via the SDK, its details are saved, and appropriate (filtered) shipping rates for pickup are displayed.
  4. If the customer selects "Home Delivery":
    • The UI visually highlights the home delivery choice.
    • The standard home delivery address input fields are displayed and enabled.
    • Any previously selected pickup location data is cleared.
    • Standard home delivery shipping rates are displayed.

Key considerations:

Initialise SingleWidgetManager

Instantiate the manager in your frontend JavaScript. Choose one of the following modes:

Modal Mode (Recommended) Embedded Mode

The Widget appears in a pop-up modal. This is the recommended approach for most checkout implementations.

import SingleWidgetManager from '@hubbox/single-widget-manager';

const singleWidgetManager = new SingleWidgetManager({
    deferRender: true, // IMPORTANT: Prevents the iframe from rendering immediately
    iframeUrl: SingleWidgetManager.iframeUrls.PRODUCTION, // Use .SANDBOX for testing
    // healthCheck: false, // Optional: Disable polling check if causing issues
    // isDebug: true,      // Optional: Enable verbose logging during development
    iframeParams: {
        configId: "YOUR_HUBBOX_CONFIG_ID", // Provided by HubBox
        locale: "en-GB"                    // Match your store's locale (e.g., en-US, fr-FR)
        // Add other config params like 'translations' if needed
    }
});

You'll also need to create and manage the <hubbox-modal> component (see Step 4) or use your own modal UI.

The Widget appears directly within a container element on your page.

import SingleWidgetManager from '@hubbox/single-widget-manager';

// Ensure this div exists in your HTML: <div id="hubbox-widget-container"></div>
const widgetContainer = document.getElementById("hubbox-widget-container");

const singleWidgetManager = new SingleWidgetManager({
    container: widgetContainer, // REQUIRED: The DOM element to inject the iframe into
    iframeUrl: SingleWidgetManager.iframeUrls.PRODUCTION, // Use .SANDBOX for testing
    // isDebug: true,
    iframeParams: {
        configId: "YOUR_HUBBOX_CONFIG_ID",
        locale: "en-GB"
    }
});

Implement Widget Triggering

Connect your Launch Experience UI (from Step 2) to the SingleWidgetManager.

widget

Modal Mode Embedded Mode

1. Add the modal component to your page (on load or dynamically):

<hubbox-modal></hubbox-modal>

Or create it dynamically via JavaScript:

const hubboxModal = document.createElement("hubbox-modal");
document.body.appendChild(hubboxModal); // Append somewhere appropriate

2. Configure the modal and link the iframe (usually after the manager initialises):

const hubboxModal = document.querySelector("hubbox-modal");
if (hubboxModal && singleWidgetManager.iframeElem) {
    hubboxModal.locale = "en-GB"; // Match config locale
    hubboxModal.open = false;     // Start closed
    hubboxModal.appendChild(singleWidgetManager.iframeElem); // Place iframe inside modal
}

3. Add an event listener to your "Choose Pickup Location" button/link:

const pickupButton = document.getElementById('choose-pickup-button');
const hubboxModal = document.querySelector("hubbox-modal");
const searchInput = document.getElementById('pickup-search-input'); // Optional search input

pickupButton.addEventListener('click', () => {
    if (searchInput && searchInput.value) {
        // Optional: Pre-fill search if the user has already entered a postcode
        singleWidgetManager.events.emit(
            singleWidgetManager.topics.emit.MAP_SEARCH_QUERY,
            searchInput.value
        );
    }
    if (hubboxModal) {
        hubboxModal.open = true; // Open the modal
    }
});

1. Ensure the container is initially hidden (e.g., via a CSS class):

<div id="hubbox-widget-container" style="display: none;"></div>

2. Add event listeners to your search input/button:

const searchButton = document.getElementById("hubbox-search-button");
const searchInput = document.getElementById("hubbox-search-input");
const widgetContainer = document.getElementById("hubbox-widget-container");

searchButton.addEventListener("click", function () {
    const searchQuery = searchInput.value;
    if (searchQuery && widgetContainer) {
        singleWidgetManager.events.emit(
            singleWidgetManager.topics.emit.MAP_SEARCH_QUERY,
            searchQuery
        );
        widgetContainer.style.display = 'block'; // Show the widget container
        // Or remove a hidden class: widgetContainer.classList.remove("hubbox-hidden");
    }
});

Handle Core Callbacks

Subscribe to events emitted by the SingleWidgetManager using events.subscribe to react to user actions within the widget iframe.

// --- Essential Callback: Collect Point Confirmed ---
const onCollectPointConfirmed = (messageAndTopic) => {
    const collectPointData = messageAndTopic.message; // Contains selected location details
    console.log("Pickup Point Confirmed:", collectPointData);

    // 1. Populate frontend address fields
    document.querySelector('#shipping-address1').value = collectPointData.address.street1 || '';
    document.querySelector('#shipping-company').value = collectPointData.name || '';
    document.querySelector('#shipping-address2').value = collectPointData.address.street2 || '';
    document.querySelector('#shipping-city').value = collectPointData.address.city || '';
    document.querySelector('#shipping-postcode').value = collectPointData.address.postcode || '';
    document.querySelector('#shipping-state').value = collectPointData.address.region || '';
    // Trigger change events if your checkout requires them for validation/updates
    document.querySelector('#shipping-postcode').dispatchEvent(new Event('change', { bubbles: true }));

    // 2. Send data to your backend (CRITICAL)
    const payload = {
        action: 'select_pickup',
        collectPointId: collectPointData.id,
        collectPointName: collectPointData.name,
        collectPointNetwork: collectPointData.network, // e.g., 'ups', 'dpd', 'dhl'
        collectPointType: collectPointData.type,       // e.g., 'public', 'private'
        address: collectPointData.address              // Full address object
    };
    fetch('/your-checkout-api/update-shipping', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' /* Add CSRF token etc. */ },
        body: JSON.stringify(payload)
    })
    .then(response => response.json())
    .then(data => {
        console.log('Backend updated:', data);
        // 3. Trigger shipping rate recalculation if needed
        // yourPlatform.recalculateShippingRates();

        // 4. Show confirmation UI (see Step 6)
        showPickupConfirmation(collectPointData);

        // 5. Close modal if using modal mode
        const hubboxModal = document.querySelector("hubbox-modal");
        if (hubboxModal) hubboxModal.open = false;

        // 6. Optionally move to the next checkout step
        // yourPlatform.goToNextStep();
    })
    .catch(error => console.error('Error sending pickup data to backend:', error));
};

// --- Essential Callback: Collect Point Unselected (user cancels/closes modal) ---
const onCollectPointUnselected = (messageAndTopic) => {
    console.log("Pickup Point Unselected");

    // 1. Clear frontend address fields (or restore original address)
    // ... your logic to clear fields ...

    // 2. Notify backend of deselection
    fetch('/your-checkout-api/update-shipping', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' /* CSRF etc. */ },
        body: JSON.stringify({ action: 'deselect_pickup' })
    })
    .then(() => {
        console.log('Backend updated: Pickup deselected');
        // 3. Trigger shipping rate recalculation (show home delivery rates)
        // yourPlatform.recalculateShippingRates();

        // 4. Hide confirmation UI
        hidePickupConfirmation();
    })
    .catch(error => console.error('Error sending deselection to backend:', error));
};

// --- Other Useful Callbacks ---
const onWidgetReady = (messageAndTopic) => {
    console.log("HubBox Widget Iframe Ready:", messageAndTopic.message);
    // Widget iframe content is loaded; safe to emit initial search queries
};

const onBootFailed = (messageAndTopic) => {
    console.error("HubBox Widget Boot Failed:", messageAndTopic.message);
    // Handle errors - consider hiding the pickup option or showing an error message
};

const onCollectPointSelected = (messageAndTopic) => {
    console.log("Point Selected (not yet confirmed):", messageAndTopic.message);
    // Optional: Use for preliminary UI updates before confirmation
};

// Subscribe to events
singleWidgetManager.events.subscribe(singleWidgetManager.topics.subscribe.COLLECT_POINT_CONFIRMED, onCollectPointConfirmed);
singleWidgetManager.events.subscribe(singleWidgetManager.topics.subscribe.COLLECT_POINT_UNSELECTED, onCollectPointUnselected);
singleWidgetManager.events.subscribe(singleWidgetManager.topics.subscribe.WIDGET_READY, onWidgetReady);
singleWidgetManager.events.subscribe(singleWidgetManager.topics.subscribe.BOOT_FAILED, onBootFailed);
singleWidgetManager.events.subscribe(singleWidgetManager.topics.subscribe.COLLECT_POINT_SELECTED, onCollectPointSelected);

Implement robust logic within COLLECT_POINT_CONFIRMED and COLLECT_POINT_UNSELECTED to update frontend fields, communicate with your backend, and trigger necessary UI changes and recalculations.

For detailed event schemas and additional topics, see the /docs/manager-js.

Implement the Confirmation UI

After a user confirms a pickup point, display a clear confirmation message showing the selected location.

confirmation-component

Option A: HubBox Component Option B: Custom UI

Use the <hubbox-pickup-confirmation-modern> component from @hubbox/web-components.

1. Add the component to your HTML (initially hidden):

<hhubbox-pickup-confirmation-modern
    id="hubbox-confirmation"
    class="hubbox-hidden"
    locale="en-GB">
</hubbox-pickup-confirmation-modern>

2. Populate and show it in your onCollectPointConfirmed callback:

function showPickupConfirmation(collectPointData) {
    const confirmationElement = document.getElementById('hubbox-confirmation');
    if (confirmationElement) {
        confirmationElement.address = collectPointData.address;
        confirmationElement.openingTimes = collectPointData.openingTimes; // If available
        confirmationElement.name = collectPointData.name;
        // Optionally set map coordinates to show a map in the component
        // confirmationElement.coords = {
        //     lat: collectPointData.address.latitude,
        //     lng: collectPointData.address.longitude
        // };
        confirmationElement.classList.remove('hubbox-hidden');
        confirmationElement.style.display = 'block';
    }
}

function hidePickupConfirmation() {
    const confirmationElement = document.getElementById('hubbox-confirmation');
    if (confirmationElement) {
        confirmationElement.style.display = 'none';
        confirmationElement.classList.add('hubbox-hidden');
    }
}

Remember to call hidePickupConfirmation() inside your onCollectPointUnselected callback.

Build your own confirmation display using the collectPointData object received in the onCollectPointConfirmed callback. At a minimum, ensure you clearly display the selected location name and full address.

Implement Backend Logic

Your server-side checkout logic must handle the following responsibilities:

  1. Receive data - Expose an API endpoint (e.g., /your-checkout-api/update-shipping) that accepts the pickup selection data (ID, name, network, address, pickup flag) sent from the frontend.
  2. Update session/cart - Store this data in the user's session or associate it with their cart/checkout object on the server. Mark the shipment as a pickup order.
  3. Persist on order - When the order is placed, save the relevant HubBox details (at minimum collectPointId, collectPointNetwork, collectPointName) with the order data in your database. This is required for fulfillment and manifesting.
  4. Filtering logic (if needed) - Implement logic to filter shipping rates or validate product eligibility based on the pickup flag stored in the session/cart.

Methods for Sending Pickup Data to Your Backend

Once onCollectPointConfirmed fires, you must send the selected location's details to your server. Choose the method that best suits your checkout architecture.

Hidden Input Fields (Traditional Forms)

Add hidden <input> fields to your main checkout <form>. In the onCollectPointConfirmed callback, use JavaScript to populate these fields with the relevant HubBox data. When the user submits the form, this data is sent along with other form data.

Best for: Traditional multi-page checkouts relying on standard form submissions.

Not suitable for: SPA checkouts or headless setups where data is sent via APIs.

Example HTML:

<input type="hidden" name="shipping[hubbox_location_id]" id="hubbox-location-id">
<input type="hidden" name="shipping[hubbox_network]" id="hubbox-network">
<input type="hidden" name="shipping[hubbox_location_name]" id="hubbox-location-name">

Example JS (within onCollectPointConfirmed):

document.getElementById('hubbox-location-id').value = collectPointData.id || '';
document.getElementById('hubbox-network').value = collectPointData.network || '';
document.getElementById('hubbox-location-name').value = collectPointData.name || '';

On deselection (onCollectPointUnselected): Clear the values of these hidden fields.

Custom REST API Call (Recommended for SPAs/Headless)

Create a dedicated API endpoint on your backend server (e.g., /api/checkout/set-hubbox-selection). In the onCollectPointConfirmed callback, use fetch or XMLHttpRequest to POST the collectPointData as JSON to this endpoint.

Best for: Modern web applications (SPAs, headless). Allows for more complex data exchange and immediate backend validation.

Example JS:

function sendPickupDataToBackend(collectPointData) {
    const payload = {
        action: 'select_pickup',
        collectPointId: collectPointData.id,
        collectPointName: collectPointData.name,
        collectPointNetwork: collectPointData.network,
        collectPointType: collectPointData.type,
        address: collectPointData.address
    };
    fetch('/api/checkout/set-hubbox-selection', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            // Include necessary headers like CSRF tokens, Auth tokens etc.
            // 'X-CSRF-Token': getCsrfToken()
        },
        body: JSON.stringify(payload)
    })
    .then(response => {
        if (!response.ok) { throw new Error('Network response was not ok'); }
        return response.json();
    })
    .then(data => {
        console.log('Backend successfully updated for pickup:', data);
        // Trigger UI updates based on response if needed
        // e.g., yourPlatform.recalculateShippingRates();
    })
    .catch(error => {
        console.error('Error sending pickup selection to backend:', error);
        // Handle error - consider reverting UI or showing an error message
    });
}

Backend example concept (SFCC - for illustration only):

The backend endpoint needs to receive the JSON payload, validate it, update the cart/shipment object, and potentially recalculate shipping. The following is a conceptual example using SFCC server-side JS:

"use strict";
var server = require("server");
server.extend(module.superModule);
var csrfProtection = require("*/cartridge/scripts/middleware/csrf");
var HubBoxHelper = require("*/cartridge/scripts/helpers/HubBoxHelper");
var BasketMgr = require("dw/order/BasketMgr");

server.post("SetHubboxSelection", server.middleware.https, csrfProtection.validateAjaxRequest, function (req, res, next) {
    var currentBasket = BasketMgr.getCurrentBasket();
    if (!currentBasket) { /* Handle error */ }
    var shipment = currentBasket.defaultShipment;

    var requestData = JSON.parse(req.body);

    if (requestData.action === 'select_pickup' && requestData.collectPointId) {
        HubBoxHelper.copyHubBoxDataToShipment(
            shipment,
            requestData.collectPointId,
            requestData.collectPointName,
            requestData.collectPointType,
            requestData.collectPointNetwork
        );
        res.json({ success: true, message: "HubBox selection saved." });
    } else if (requestData.action === 'deselect_pickup') {
        HubBoxHelper.clearHubBoxDataFromShipment(shipment);
        res.json({ success: true, message: "HubBox selection cleared." });
    } else {
        res.setStatusCode(400);
        res.json({ error: true, message: "Invalid request." });
    }
    return next();
});
module.exports = server.exports();

On deselection (onCollectPointUnselected): Make a similar fetch call to your endpoint with action: 'deselect_pickup' so the backend can clear the relevant data and revert to home delivery logic.

Cookies (Fallback Method)

In the onCollectPointConfirmed callback, use document.cookie to set a cookie containing the necessary HubBox data (e.g., location ID). Your backend code then reads this cookie value during checkout processing.

Best for: Last resort on highly restrictive platforms where modifying forms or making JS API calls is not possible.

Limitations:

On deselection (onCollectPointUnselected): Delete the cookie or set its value to indicate deselection.

The cookie method is generally not recommended unless other methods are not feasible for your platform.

Manifesting and Labelling Pickup Orders

Depending on your chosen carrier for pickup services, you may need to make changes to the way your WMS creates shipments and/or generates labels.

In some instances, you will need to take the id property from the COLLECT_POINT_CONFIRMED event and either place this code within the shipping address for the order or store it as metadata.

Refer to our documentation on Manifesting Pickup Orders for full details or contact HubBox if you require support.


Sharing Order Data with HubBox

Sharing details of completed pickup orders back to HubBox enables data analysis and reporting features within the HubBox Console dashboard. This provides insights into pickup adoption rates, ROI, carrier performance, and operational trends.

Order Processing API (Recommended)

A server-to-server API call made after a customer successfully places a pickup order.

How it works: Your backend server makes a direct, secure API call to the HubBox Order Processing API endpoint after order placement.

Data sent: Order ID, collectPointId, collectPointNetwork, order value, currency, item count, and optionally anonymised customer details.

Pros: Most reliable method - server-to-server, less prone to browser issues (e.g., ad blockers), and supports retries on failure.

HubBox Order Processing API Documentation

Tracking Pixel (Frontend)

A JavaScript snippet added to your Order Confirmation page.

How it works: When the confirmation page loads in the customer's browser, the script gathers order details and sends them directly to HubBox. Does not require backend changes specifically for HubBox data sharing.

Pros: Simpler frontend implementation.

HubBox Tracking Pixel Documentation

Key data points typically required:

Data shared with HubBox is anonymised and does not include any personally identifiable information (PII) or payment/card information (PCI).

Choose the method that best fits your technical capabilities and reliability requirements. The Order Processing API is generally preferred for accuracy and resilience.


Customisation

Styling

Launch and Confirmation Components

If using HubBox Components for the launch experience, style them using CSS ::part() and CSS Custom Properties (:root variables) as detailed in HubBox Components documentation.

Widget Modal/iframe

The internal look and feel of the map widget (colours, pins, map style within the iframe) is primarily controlled by the configId used during SingleWidgetManager initialisation. This configuration is managed within the HubBox platform. See Widget Configuration documentation.


Text and Language (Translations)

Set Locale

Pass the correct locale code (e.g., "fr-FR") in iframeParams.locale when initialising SingleWidgetManager.

Override Text

Pass a translations object within iframeParams to override default text within the widget iframe. For text in components rendered directly on your page (such as the confirmation component), set the .translations property on the component instance after creating it. Refer to the Component Translations documentation for available translation keys.


Advanced Features

Implementing features like eligibility and rate filtering with the SDK requires custom logic within your application, triggered by SDK events.

Product Eligibility Filtering

Prevent users from selecting pickup if their cart contains ineligible items.

Implementation:

  1. Develop backend logic to determine if a cart is eligible based on its contents (checking product attributes, categories, dimensions, etc. against your rules). Expose this eligibility status via an API endpoint or a data attribute on the page.
  2. In your frontend JavaScript, before triggering the HubBox widget (e.g., before opening the modal or running a search), check the cart's eligibility status.
  3. If ineligible, disable or hide your "Choose Pickup Location" button/UI elements. Optionally display a message explaining why pickup is unavailable.
function isBasketEligibleForPickup(cartItems) {
    // Assumes 'isEligibleForPickup' is a boolean property on each cart item
    return cartItems.every((item) => item.isEligibleForPickup);
}

const cartItems = getCartItems(); // Replace with your platform's method
const pickupOptionElement = document.getElementById("pickupOption");

if (isBasketEligibleForPickup(cartItems)) {
    pickupOptionElement.style.display = "block"; // Show pickup option
} else {
    pickupOptionElement.style.display = "none"; // Hide pickup option
}

For more information, see /docs/product-eligibility.


Shipping Rate Filtering

Show only relevant shipping rates after the user selects either Home Delivery or Local Pickup. This is essential for "Toggles" style launch experiences.

Implementation:

  1. In your frontend JavaScript onCollectPointConfirmed callback, send a "pickup selected" flag (and optionally the chosen network/location details) to your backend API. In onCollectPointUnselected, send a "home delivery selected" flag.
  2. Your backend logic (which calculates or retrieves shipping rates) must receive this flag.
  3. Based on the flag, filter the list of available shipping methods before returning them to the frontend for display.
  4. Your frontend may need to trigger a refresh of the shipping rates section after the selection is confirmed by the backend.
function filterShippingRates(availableRates, isPickupOrder) {
    if (isPickupOrder) {
        return availableRates.filter((rate) => rate.id === "local_pickup"); // Only keep "Local Pickup"
    } else {
        return availableRates.filter((rate) => rate.id !== "local_pickup"); // Filter out "Local Pickup"
    }
}

const isPickupOrder = order.hasFlag("pickup"); // Replace with your logic
const allShippingRates = getAvailableShippingRates(); // Replace with your platform's method
const filteredRates = filterShippingRates(allShippingRates, isPickupOrder);

// Update the UI or recalculate totals using 'filteredRates'

For more information, see Shipping Rate Filtering documentation.


Testing

Thorough end-to-end testing on a staging or development environment is critical for SDK implementations.

Testing Checklist

Installation and Initialisation

UI and Widget Flow

Callback Logic

Backend Communication

Filtering and Confirmation UI

Order Placement and Data

Cross-Browser and Device Testing

To access HubBox's UAT guide, see the Testing documentation.


Example Integration Project

An example project demonstrating basic SDK setup and interaction is available to download.

Ensure you are logged in to download. Contact your HubBox representative if you need access.

Download SDK Integration Example