Multiple Instance Demo
<!-- Option A: Single widget using ID -->
<div id="bushire-nz"></div>
<!-- Option B: Multiple widgets using class -->
<div class="bushire-nz"></div>
<div class="bushire-nz"></div>
<!-- Option C: Mix both (ID and class) -->
<div id="bushire-nz"></div>
<div class="bushire-nz"></div>
Place container div(s) where you want the widget to appear. Use an ID selector for a
single widget or a class selector for multiple widgets. The widget will initialize on
all matching elements based on your widgetId config.
<script type="module"
src="https://your-widget-domain.com/demo.js"></script>
Add this script tag to load the widget. The config is embedded in the JS file.
Load the widget dynamically (e.g., after user interaction or conditionally):
// Create container
const container = document.createElement('div');
container.id = 'bushire-nz';
document.body.appendChild(container);
// Load widget script dynamically
const script = document.createElement('script');
script.type = 'module';
script.src = 'https://your-widget-domain.com/bushire-nz.js';
document.head.appendChild(script);
The widget auto-initializes when the script loads. No callback needed.
For React, Vue, or other modern frameworks, load the widget in useEffect:
// React example
import { useEffect } from 'react';
function BookingWidget() {
useEffect(() => {
import('https://your-widget-domain.com/bushire-nz.js');
}, []);
return <div id="bushire-nz" />;
}
The widget auto-initializes when loaded and finds the container by ID.
To create a new widget bundle for a different site or a different configuration,
create a new .ts file in the src/ directory. Vite will
automatically build it into a separate JS bundle.
// src/your-site.ts <-- Create this file in the src/ folder
import createWidget from './main';
createWidget({
widgetId: "your-site", // Used to find #your-site or .your-site
theme: {
primary: "#your-color",
accent: "#your-accent"
},
api: {
proxyBase: "https://your-api.com/api",
transportersBase: "https://bookings.your-site.com"
},
maps: {
apiKey: "YOUR_GOOGLE_MAPS_API_KEY",
defaultRegion: "AU"
}
});
Then run npm run build to generate dist/your-site.js.
Include this built file in your HTML:
<div id="your-site"></div>
<script type="module" src="https://cdn.your-site.com/your-site.js"></script>
The widget dispatches custom events that you can listen to for tracking, analytics, or custom integrations.
Fired when a booking form is successfully submitted. Use this to track conversions, send data to analytics, or trigger custom workflows.
window.addEventListener('form_submission_new', (event) => {
const { formData, timestamp } = event.detail;
// Example: Send to analytics
console.log('Booking submitted:', formData.orderId);
// Access the full payload
console.log('Order ID:', formData.orderId);
console.log('Contact:', formData.contactName, formData.contactEmail);
console.log('Submitted at:', timestamp);
});
Event Payload Structure:
{
detail: {
formData: {
orderId: number, // Unique order reference
vehicleType: string, // e.g., "mini-bus", "coach"
journeyType: string, // e.g., "one-way", "return", "charter"
passengers: number, // Number of passengers
suitcaseLuggage: number, // Number of large luggage items
handLuggage: number, // Number of hand luggage items
pickupLocation: {
address: string, // Full address text
lat: number, // Latitude coordinate
lng: number // Longitude coordinate
},
destination: {
address: string, // Full address text
lat: number, // Latitude coordinate
lng: number // Longitude coordinate
},
pickupDate: string, // Format: "DD/MM/YYYY"
pickupTime: string, // Format: "HH:MM"
returnDate: string | null, // For return trips
returnTime: string | null, // For return trips
charterDuration: string | null, // For charter bookings
contactName: string, // Full name (first + last)
contactEmail: string, // Email address
phoneNumber: string, // Phone (spaces removed)
contactPreferences: string[], // e.g., ["email", "phone"]
bookingDetails: string // Additional notes/details
},
timestamp: string // ISO 8601 format
}
}