Widget / JS Online Booking Component for any Website
Bookla provides a widget for online booking that can be embedded into any website or application. This component allows you to offer a seamless booking experience without the need for extensive coding or integration work.
The widget is fully customizable — you can control colors, spacing, typography, localization, behavior, and form fields, all without touching CSS directly. Use the visual styler below to configure your widget interactively, then export the generated code.
Setup
Add the widget container and script to your page:
<div id="bookla-booking-widget" class="bookla-widget"></div>
<script src="https://bookla.pages.dev/booking-widget-standalone-v1.6.2.global.js"></script>
Then initialize the widget:
const container = document.getElementById('bookla-booking-widget');
BookingWidgetStandalone.initBookingWidget(container, {
apiKey: 'your-api-key', // Required
region: 'US', // Required: "US" or "EU"
companyId: 'your-company-id', // Required
serviceId: 'your-service-id', // Optional: pre-select a service
// ...configuration options
});
The initialization script handles DOMContentLoaded automatically in the exported code. Only the properties you want to override need to be specified; everything else falls back to sensible defaults.
Required Parameters
| Parameter | Type | Description |
|---|---|---|
apiKey | String | Your Bookla API key |
region | "US" | "EU" | API region endpoint |
companyId | String | Your Bookla company ID |
Optional Top-Level Parameters
| Parameter | Type | Description |
|---|---|---|
serviceId | String | Pre-select a specific service by ID |
Theme Configuration
The theme object controls the visual appearance of the widget. It is divided into three sections: colors, spacing, and typography.
Colors
General Colors
These apply globally across the widget.
| Parameter | Type | Description |
|---|---|---|
colors.background | Color or Gradient | Main background color of the widget container |
colors.text | Hex color | Primary text color |
colors.secondaryText | Hex color | Secondary/muted text color |
colors.error | Hex color | Color for error states and validation messages |
colors.success | Hex color | Color for success states |
colors.border | Border string | Default border styling (e.g. "1px solid #cccccc") |
Button Colors
Buttons support three states: normal, hover, and disabled. Each state accepts the same set of properties. There are three button variants: primary (button), secondary (secondaryButton), and icon (iconButton).
The path pattern is colors.<buttonType>.<state>.<property>.
| Property | Type | Description |
|---|---|---|
background | Color or Gradient | Button background |
text | Hex color | Button text (or icon) color |
border | Border string | Button border |
Example:
theme: {
colors: {
button: {
normal: { background: '#1a73e8', text: '#ffffff', border: '1px solid #1a73e8' },
hover: { background: '#1557b0', text: '#ffffff', border: '1px solid #1557b0' },
disabled: { background: '#e0e0e0', text: '#9e9e9e', border: '1px solid #e0e0e0' },
},
secondaryButton: {
normal: { background: '#ffffff', text: '#1a73e8', border: '1px solid #1a73e8' },
// hover, disabled...
},
iconButton: {
normal: { background: 'transparent', text: '#333333', border: 'none' },
// hover, disabled...
},
}
}
Item Colors
Items represent selectable elements like services, time slots, and date cells. They support four states: normal, selected, hover, and disabled.
Path pattern: colors.item.<state>.<property>
| Property | Type | Description |
|---|---|---|
background | Color or Gradient | Item background |
text | Hex color | Item primary text |
secondaryText | Hex color | Item secondary text |
border | Border string | Item border |
List Colors
List containers wrap groups of items. They support normal and selected states.
Path pattern: colors.list.<state>.<property>
| Property | Type | Description |
|---|---|---|
background | Hex color | List container background |
text | Hex color | List text color |
secondaryText | Hex color | List secondary text |
border | Border string | List border |
Form Colors
Form inputs support normal and error states.
Path pattern: colors.form.<state>.<property>
| Property | Type | Description |
|---|---|---|
background | Hex color | Input background |
text | Hex color | Input text color |
border | Border string | Input border |
Summary Colors
The summary section displays the booking overview before confirmation.
Path pattern: colors.summary.<property>
| Property | Type | Description |
|---|---|---|
background | Hex color | Summary section background |
text | Hex color | Summary text color |
secondaryText | Hex color | Summary secondary text |
border | Border string | Summary border |
Spacing
Spacing values control padding, border radius, and gaps throughout the widget. Most values are numbers representing pixels.
General Spacing
| Parameter | Type | Default | Description |
|---|---|---|---|
spacing.padding | Number or Padding | — | Widget container padding. A single number applies uniformly; a string like "16px 12px 16px 12px" sets top/right/bottom/left individually |
spacing.borderRadius | Number | 8 | Corner radius for the main container |
spacing.gridGap | Number | — | Gap between grid items (e.g. time slots) |
spacing.rowGap | Number | — | Gap between rows |
spacing.sectionGap | Number | — | Gap between major sections |
Text Spacing
| Parameter | Type | Description |
|---|---|---|
spacing.text.gap | Number | Gap between text elements |
spacing.text.labelGap | Number | Gap between a label and its input |
Element-Specific Spacing
Each of the following elements has padding (Number or Padding string) and borderRadius (Number) properties:
| Element | Path prefix | Description |
|---|---|---|
| Button | spacing.button | Primary and secondary buttons |
| Icon Button | spacing.iconButton | Icon-only buttons |
| Item | spacing.item | Selectable items (services, times, etc.) |
| List | spacing.list | List containers |
| Form | spacing.form | Form input fields |
| Summary | spacing.summary | Booking summary section |
Example:
theme: {
spacing: {
padding: 20,
borderRadius: 12,
gridGap: 8,
sectionGap: 24,
button: { padding: '12px 24px', borderRadius: 8 },
item: { padding: 16, borderRadius: 6 },
form: { padding: '10px 14px', borderRadius: 6 },
}
}
Typography
| Parameter | Type | Default | Description |
|---|---|---|---|
typography.fontFamily | String | — | CSS font family for all text (e.g. "Inter, sans-serif") |
typography.fontSize.base | Number | 16 | Base font size in pixels |
typography.fontSize.large | Number | 18 | Large font size in pixels |
typography.fontWeight.normal | Number | 400 | Normal font weight (100–900) |
typography.fontWeight.medium | Number | 500 | Medium font weight (100–900) |
typography.lineHeight.title | Number | 1.4 | Line height multiplier for titles |
typography.lineHeight.text | Number | 1.6 | Line height multiplier for body text |
Gradient Support
Any color property that accepts a "Color or Gradient" type can be configured as a gradient via the _gradients key on the theme. The Styler app provides a visual gradient editor for these.
// GradientValue structure
{
type: 'solid' | 'linear' | 'radial',
colors: ['#ff0000', '#0000ff'], // Array of hex colors
angle: 135, // For linear gradients (0–360)
position: 'center', // For radial gradients
}
Gradient-capable properties include background, all button state backgrounds, and all item state backgrounds.
Localization Configuration
The localization object lets you customize every text string in the widget. This is useful both for translating the widget into different languages and for tailoring the copy to your brand voice.
General
| Parameter | Type | Description |
|---|---|---|
locale | String | Locale code (e.g. "en", "es", "fr", "de") |
Time Selection
| Parameter | Type | Description |
|---|---|---|
times.selectTimeTitle | String | Title shown on the time selection step |
times.noAvailableTimes | String | Message when no times are available |
times.loadingText | String | Loading indicator text |
times.continueButton | String | Continue button label |
times.loginUrl | String or null | URL for the login link (null to hide) |
Resource Selection
| Parameter | Type | Description |
|---|---|---|
resource.selectResourceTitle | String | Title for the resource picker |
resource.anyResourceOption | String | Label for the "any resource" option |
Guest Form
| Parameter | Type | Description |
|---|---|---|
guestForm.firstNameFieldLabel | String | First name field label |
guestForm.firstNameFieldError | String | First name validation error |
guestForm.lastNameFieldLabel | String | Last name field label |
guestForm.lastNameFieldError | String | Last name validation error |
guestForm.emailFieldLabel | String | Email field label |
guestForm.emailFieldError | String | Email required error |
guestForm.emailFieldInvalidError | String | Email format error |
Result Screens
Success Screen:
| Parameter | Type | Description |
|---|---|---|
successScreen.title | String | Title after successful booking |
successScreen.description | String | Description text |
successScreen.bookAgain | String | "Book again" button text |
Pending Screen:
| Parameter | Type | Description |
|---|---|---|
pendingScreen.title | String | Title when booking is pending approval |
pendingScreen.description | String | Description text |
pendingScreen.bookAgain | String | "Book again" button text |
Error Screen:
| Parameter | Type | Description |
|---|---|---|
errorScreen.title | String | Title on error |
errorScreen.description | String | Description text |
errorScreen.reload | String | Reload/retry button text |
Buttons
| Parameter | Type | Description |
|---|---|---|
bookButton | String | Primary "Book" button label |
loginButton | String | Login button label |
backButton | String | Back navigation button label |
loadingText | String | Generic loading text |
Service Selection
| Parameter | Type | Description |
|---|---|---|
serviceSelection.title | String | Service list title |
serviceSelection.description | String | Service list subtitle |
Group and Duration Selection
| Parameter | Type | Description |
|---|---|---|
group.selectTitle | String | Title for group/category selection |
duration.selectTitle | String | Title for duration selection |
Tickets
| Parameter | Type | Description |
|---|---|---|
tickets.selectTicketsTitle | String | Title for ticket selection |
tickets.selectTicketsDescription | String | Description for ticket selection |
tickets.noTicketsAvailable | String | Empty state message |
tickets.continueButton | String | Continue button label |
tickets.ticketsSummaryTitle | String | Summary title for selected tickets |
Days (Check-in/Check-out)
| Parameter | Type | Description |
|---|---|---|
days.checkIn | String | Check-in label |
days.checkOut | String | Check-out label |
days.night | String | Singular form of "night" |
days.nights | String | Plural form of "nights" |
Terms and Conditions
| Parameter | Type | Description |
|---|---|---|
terms.acceptText | String | Checkbox label text |
terms.urls | Array | Array of { text: string, url: string } objects linking to legal documents |
Form
| Parameter | Type | Description |
|---|---|---|
form.isRequiredText | String | Text for required field indicators |
form.selectOption | String | Default placeholder for select inputs |
Coupon/Code
| Parameter | Type | Description |
|---|---|---|
code.fieldLabel | String | Code input label |
code.fieldError | String | Code field error message |
code.notFoundError | String | Error when code is not found |
Add-ons
| Parameter | Type | Description |
|---|---|---|
addons.title | String | Add-ons section title |
addons.required | String | "Required" badge text |
addons.selectOption | String | Default dropdown option text |
addons.totalLabel | String | Total price label |
Subscriptions (Subscription Widget)
| Parameter | Type | Description |
|---|---|---|
subscriptions.title | String | Subscription list title |
subscriptions.subtitle | String | List subtitle |
subscriptions.summaryTitle | String | Summary title |
subscriptions.buyText | String | Purchase button text |
subscriptions.noSubscriptions | String | Empty state message |
subscriptions.visits | String | Visits limit text |
Gift Cards (Gift Card Widget)
| Parameter | Type | Description |
|---|---|---|
giftCards.title | String | Gift card list title |
giftCards.subtitle | String | List subtitle |
giftCards.summaryTitle | String | Summary title |
giftCards.buyText | String | Purchase button text |
giftCards.noGiftCards | String | Empty state message |
giftCards.validityText | String | Validity period label |
giftCards.taxIncludedText | String | "Tax included" indicator |
giftCards.taxExcludedText | String | "Tax excluded" indicator |
Booking Configuration
All booking configuration parameters are passed at the top level of the configuration object (not nested under a config key).
General Options
| Parameter | Type | Default | Description |
|---|---|---|---|
transitionType | "slide" | "fade" | "flip" | "stack" | "slide" | Page transition animation between steps |
showServiceSelector | Boolean | false | Show the service selection screen as the first step |
hideResourcePicker | Boolean | false | Hide the resource picker (staff, room, etc.). Set to true to skip resource selection |
guestEnabled | Boolean | — | Allow guest booking without authentication |
termsEnabled | Boolean | — | Show terms and conditions checkbox |
addonsEnabled | Boolean | — | Enable the add-ons selection step |
preselectedDate | Date | — | Pre-select a specific date when the widget loads |
Pricing
| Parameter | Type | Description |
|---|---|---|
showPrice | Boolean | Display prices in the UI |
showComparedPrice | Boolean | Show original price alongside discounted price |
showDecimalPlaces | Boolean | Show decimal places in price display |
Days (Multi-day Bookings)
| Parameter | Type | Default | Description |
|---|---|---|---|
minNights | Number | 1 | Minimum number of nights for a booking |
maxNights | Number | 365 | Maximum number of nights for a booking |
Coupon/Code
| Parameter | Type | Description |
|---|---|---|
code.enabled | Boolean | Show the coupon/code input field |
code.required | Boolean | Make the code field mandatory |
Service Overrides
You can override titles and behavior for individual services via the servicesConfig object:
servicesConfig: {
services: [
{
serviceId: 'service-abc-123', // Required: Bookla service ID
title: 'Premium Massage', // Override display title
description: 'A luxurious 60-min session', // Override description
hideResourcePicker: true, // Hide resource picker for this service
selectResourceTitle: 'Choose your therapist',
anyResourceOption: 'No preference',
}
]
}
Ticket Overrides
ticketsConfig: {
tickets: [
{
ticketId: 'ticket-xyz-789', // Required: Bookla ticket ID
title: 'VIP Entry', // Override display title
}
]
}
Subscription Overrides
subscriptionsConfig: {
subscriptions: [
{
subscriptionId: 'sub-001',
title: 'Monthly Unlimited',
description: 'Unlimited access for 30 days',
}
]
}
Gift Card Overrides
giftCardsConfig: {
giftCards: [
{
giftCardId: 'gc-001',
title: 'Birthday Gift Card',
description: 'The perfect gift for someone special',
}
]
}
Custom Form Fields
You can add custom fields to the booking form to collect additional information from customers.
Each custom field supports the following properties:
| Property | Type | Required | Description |
|---|---|---|---|
type | "text" | "number" | "textarea" | "phone" | "url" | "select" | "multiselect" | Yes | Input type |
labelText | String | Yes | Label displayed above the field |
required | Boolean | Yes | Whether the field is mandatory |
errorText | String | If required | Error message shown on validation failure |
inputWidth | "auto / span 1" | "auto / span 2" | No | Column span — span 1 for half-width, span 2 for full-width |
options | String | For select/multiselect | Comma-separated or newline-separated list of options |
Example:
customFormFields: [
{
type: 'text',
labelText: 'Company Name',
required: false,
inputWidth: 'auto / span 2',
},
{
type: 'phone',
labelText: 'Phone Number',
required: true,
errorText: 'Please enter your phone number',
inputWidth: 'auto / span 1',
},
{
type: 'select',
labelText: 'How did you hear about us?',
required: false,
inputWidth: 'auto / span 2',
options: 'Google,Social Media,Friend,Other',
},
{
type: 'textarea',
labelText: 'Special Requests',
required: false,
inputWidth: 'auto / span 2',
},
]
Complete Example
Here is a full configuration bringing together all sections. The HTML setup:
<div id="bookla-booking-widget" class="bookla-widget"></div>
<script src="https://bookla.pages.dev/booking-widget-standalone-v1.6.2.global.js"></script>
The initialization script:
const container = document.getElementById('bookla-booking-widget');
BookingWidgetStandalone.initBookingWidget(container, {
// Required
apiKey: 'your-api-key',
region: 'US',
companyId: 'your-company-id',
// Optional: pre-select a service
serviceId: 'your-service-id',
// Booking behavior
transitionType: 'fade',
showServiceSelector: true,
hideResourcePicker: false,
guestEnabled: true,
termsEnabled: true,
addonsEnabled: false,
// Theme
theme: {
colors: {
background: '#ffffff',
text: '#1a1a1a',
secondaryText: '#6b7280',
error: '#dc2626',
success: '#16a34a',
border: '1px solid #e5e7eb',
button: {
normal: { background: '#2563eb', text: '#ffffff', border: 'none' },
hover: { background: '#1d4ed8', text: '#ffffff', border: 'none' },
disabled: { background: '#d1d5db', text: '#9ca3af', border: 'none' },
},
item: {
normal: { background: '#f9fafb', text: '#1a1a1a', secondaryText: '#6b7280', border: '1px solid #e5e7eb' },
selected: { background: '#eff6ff', text: '#1e40af', secondaryText: '#3b82f6', border: '1px solid #2563eb' },
hover: { background: '#f3f4f6', text: '#1a1a1a', secondaryText: '#6b7280', border: '1px solid #d1d5db' },
disabled: { background: '#f9fafb', text: '#d1d5db', secondaryText: '#d1d5db', border: '1px solid #f3f4f6' },
},
},
spacing: {
padding: 24,
borderRadius: 12,
gridGap: 8,
sectionGap: 20,
button: { padding: '12px 24px', borderRadius: 8 },
item: { padding: 14, borderRadius: 8 },
},
typography: {
fontFamily: 'Inter, system-ui, sans-serif',
fontSize: { base: 15, large: 18 },
fontWeight: { normal: 400, medium: 600 },
lineHeight: { title: 1.3, text: 1.5 },
},
},
// Localization
localization: {
locale: 'en',
times: {
selectTimeTitle: 'Pick a time',
noAvailableTimes: 'No availability for this date',
continueButton: 'Continue',
},
bookButton: 'Confirm Booking',
backButton: 'Back',
successScreen: {
title: "You're all set!",
description: 'Your booking has been confirmed. Check your email for details.',
bookAgain: 'Make another booking',
},
terms: {
urls: [{ text: 'terms and conditions', url: '/terms' }],
},
},
// Custom form fields
customFormFields: [],
// Service & ticket overrides
servicesConfig: { services: [] },
ticketsConfig: { tickets: [] },
});