Widget Events
Callbacks and events to respond to user actions and customize the booking flow.
Introduction
The widget emits events at different moments in the booking flow. You can subscribe to these events via callbacks in the initial configuration:
SalonBookIt.init({
apiKey: 'hh_pub_live_...',
container: '#widget',
// Event callbacks
onReady: (business) => { /* ... */ },
onStepChange: (step, data) => { /* ... */ },
onServiceSelect: (service) => { /* ... */ },
onBookingComplete: (booking) => { /* ... */ },
onError: (error) => { /* ... */ }
});
Events reference
onReady
Triggered when the widget has fully loaded and is ready to use.
Parameters
| Parameter | Type | Description |
|---|---|---|
business |
object |
Loaded business information |
Example
onReady: (business) => {
console.log('Business:', business.nombre);
console.log('Available services:', business.servicios_count);
// Update external UI
document.querySelector('.loading').style.display = 'none';
}
Object business
{
"id": "uuid-del-tenant",
"nombre": "Mi Salon",
"telefono": "+34612345678",
"email": "info@misalon.com",
"direccion": "Calle Principal 123",
"logo_url": "https://...",
"servicios_count": 12,
"profesionales_count": 5,
"moneda": "EUR",
"simbolo_moneda": "€"
}
onStepChange
Triggered when the user advances or goes back in the booking flow.
Parameters
| Parameter | Type | Description |
|---|---|---|
step |
string |
Current step name |
data |
object |
Data accumulated so far |
Available steps
'services'- Service selection'staff'- Professional selection'datetime'- Date and time selection'customer'- Customer data'payment'- Payment (if applicable)'confirmation'- Final confirmation
Example
onStepChange: (step, data) => {
console.log('Current step:', step);
// Analytics
gtag('event', 'booking_step', {
'step_name': step,
'services_selected': data.services?.length || 0
});
// Update external breadcrumbs
updateBreadcrumbs(step);
}
onServiceSelect
Triggered when the user selects or deselects a service.
Parameters
| Parameter | Type | Description |
|---|---|---|
service |
object |
Selected service |
selected |
boolean |
Whether it was selected or deselected |
allSelected |
array |
All currently selected services |
Example
onServiceSelect: (service, selected, allSelected) => {
console.log(selected ? 'Added:' : 'Removed:', service.nombre);
// Update total price in external UI
const total = allSelected.reduce((sum, s) => sum + s.precio, 0);
document.querySelector('.total-price').textContent = `€${total}`;
}
onStaffSelect
Triggered when the user selects a professional.
Example
onStaffSelect: (staff) => {
console.log('Professional:', staff.nombre);
// staff = { id, nombre, imagen_url, especialidades }
}
onDateSelect
Triggered when the user selects a date and time.
Example
onDateSelect: (datetime) => {
console.log('Date:', datetime.fecha); // '2024-01-20'
console.log('Time:', datetime.hora); // '10:30'
}
onBookingComplete
Triggered when the booking has been created successfully (before payment if applicable).
Example
onBookingComplete: (booking) => {
console.log('Booking created:', booking.id);
// Analytics
gtag('event', 'purchase', {
'transaction_id': booking.id,
'value': booking.total,
'currency': 'EUR'
});
// Redirect to confirmation page
window.location.href = `/reserva-confirmada/${booking.id}`;
}
Object booking
{
"id": 12345,
"codigo": "ABC123",
"fecha": "2024-01-20",
"hora_inicio": "10:30",
"hora_fin": "11:00",
"servicios": [
{ "id": 1, "nombre": "Classic cut", "precio": 25.00 }
],
"profesional": {
"id": 5,
"nombre": "Carlos Garcia"
},
"cliente": {
"nombre": "Juan Perez",
"email": "juan@email.com",
"telefono": "+34612345678"
},
"total": 25.00,
"estado": "confirmed",
"pago_pendiente": true
}
onPaymentComplete
Triggered when the payment has completed successfully.
Example
onPaymentComplete: (payment) => {
console.log('Payment completed');
console.log('ID:', payment.payment_intent_id);
console.log('Amount:', payment.amount);
// Show success message
showSuccessMessage('Payment received!');
}
onError
Triggered when an error occurs at any point in the flow.
Example
onError: (error) => {
console.error('Error:', error.code, error.message);
// Report to error system
Sentry.captureException(error);
// Show message to user
if (error.code === 'SLOT_UNAVAILABLE') {
alert('Sorry, that time slot is no longer available.');
}
}
Common error codes
| Code | Description |
|---|---|
INVALID_API_KEY |
Invalid API Key |
NETWORK_ERROR |
Connection error |
SLOT_UNAVAILABLE |
Schedule no longer available |
PAYMENT_FAILED |
Payment error |
VALIDATION_ERROR |
Invalid form data |
onClose
Triggered when the user closes the widget (modal mode only).
Example
onClose: () => {
console.log('Widget closed');
// Ask if they want to save draft
if (hasUnsavedData()) {
saveBookingDraft();
}
}
Widget Methods
In addition to events, you can control the widget programmatically:
// Get widget reference
const widget = SalonBookIt.init({ ... });
// Open modal (modal/button mode only)
widget.open();
// Close modal
widget.close();
// Go to a specific step
widget.goToStep('services');
// Reset the widget
widget.reset();
// Destroy the widget
widget.destroy();