Booking Widget Integration Guide (v3)

The purpose of this article is to provide guidance on how to integrate the ADA compliant “Booking Widget“ v3 to your website.

Migrating from Booking Widget v2

If you are migrating from Booking Widget v2 to Booking Widget v3, please consult the following document to learn what has changed and how to update your implementation.

 

Before proceeding further, let’s have a look at the properties supported by this new implementation.

Properties

Here is a complete list of properties supported by the new Booking widget. A button can be assigned one or several of these properties. Some properties have (*) limited support.

Properties

Description

apiKey

The Merchant API Key. Mandatory for the button to be created.

mode*

Set how the widget will be displayed in iFrame or popup. Only iFrame is supported for now, and that mode also works well with mobile.

iframeId 

User-defined id. Can be used to assign a top level style to Book Now.

language

Property to set the language in which the booking widget will be loaded.

fallbackLanguage

Fallback language  when translations aren’t available  in a selected language.

bookingFlow*

Property to set the widget’s booking flow.

serviceTags

Filter service list by service tag, user-defined values in the back office.

locationTags

Filter stores by location tag, user-defined values.

serviceCategoryId

Preselect a service category when opening the booking widget.

serviceId

Preselect a specific service when opening the booking widget.

staffId

Automatically set staff ID when a service is selected. When used, a serviceId must be provided.

onClose

Callback function that receives an object as its argument when the widget is closed.

onBookedRedirectTo

Redirect URL when a booking is created or updated successfully.

onAbortRedirectTo

Redirect URL when Booking Widget is closed without a successful booking.

googleAnalytics

ga() function to send Google Analytics events to.

googleTag

gtag() function to send Google Tag Manager events to.

showDescriptions

Display merchant, location, category, and service extended descriptions: 

  • always - always visible
  • never - never visible, 
  • expand - initially collapsed w/button to expand. (Default Value)

client

Set of properties used to prefill the client section. For more details regarding this object, please consult "client prefilling" below.

 

Implementation

To integrate a Booking button to your webpage, the below javascript must be included in the header of your page’s HTML code. Select the right URL based on your hosting region.

Americas

<head>
   <script src="https://www.booxi.com/booknow/booknow.js" async="">
</script>
</head>

Europe

<head>
   <script src="https://www.booxi.eu/booknow/booknow.js" async="">
   </script>
</head>

 

If you are migrating from a previous version of the Booking Widget, please pay close attention to the URL format above to make sure the right javascript is included.

Integrated Button

Online booking can be integrated to your webpage by mapping a button’s “onclick” event to BookNow.open(...) . Doing so requires configuring properties at the time of calling that function. As shown below, the function call must be made between quotes, your data delimited between brackets and parameters between single quotes.

<body>

   <button onclick="BookNow.open({apiKey:'YOUR_API_KEY_HERE', language:'en'})">
   Book Now
   </button>

</body>

 

The following example showcases how to create a pair of buttons with different properties.

<body>

   <button onclick="BookNow.open({apiKey:'YOUR_API_KEY_HERE',
                    language:'fr', bookingFlow:'locations', mode:'iframe'})">
   Réserver
    </button>


   <button onclick="BookNow.open({apiKey:'YOUR_API_KEY_HERE',
                    language:'en', serviceTags:'athome'})">
   Book Now
   </button>

</body>

 

The resulting buttons should look as below:

Automatically Loading the Booking Widget on a Landing Page

The Booking Widget can be automatically launched upon loading a webpage. This feature can be used to prompt the widget for a specific store, a set or subset of services or for a specific event. For further details on how load the Booking Widget on a landing page, consult the following article.

 

Customizing the Location Booking Flow

Booxi provides the ability to customize the location booking flow by allowing a merchant to select what step comes first in the booking process. The property bookingFlow can be used for that purpose and supports two different values: “locations” and “merchants”.

The booking flow can further be supplemented with the geolocation option allowing clients to select stores sorted by proximity. However, this feature must be activated by Booxi.

Using the bookingFlow Property

 

Using the bookingFlow property allows you to set how the widget will be prompted. 

Values

Definition

locations

When setting the booking flow to “locations”, clients will be asked to select a store location before proceeding further with their booking.

A merchant must define a group of locations in the Back Office for this feature to work as expected.

 

The following examples showcase how to manually set the “bookingFlow” property in your HTML code. Remember that the same result can be achieved with the code generator if you need assistance. 

<!-- Set booking flow to “locations” -->

<body>

  <button onclick="BookNow.open({apiKey: 'YOUR_API_KEY_HERE', bookingFlow:'locations'})">
  Select Store
</button>

</body>

 

The above code will display all store locations in the widget (or up to 50 if their count exceeds that number ). If stores are categorized or sorted by regions, the property “locationCategory” can be employed to require the user to select a category or region instead of listing all stores at once.

Using the locationCategory Property

 

The property “locationCategory can be used to supplement a “locations” booking flow. By activating this property, users will be required to select a region, regardless of how many stores a merchant has. The widget will display all stores assigned to the selected region. Take note that the property “bookingFlow” must be used and set to “locations” for this feature to work as expected.

The following example showcases how to activate the “locationCategory” property.

<!-- Set booking flow to “locations” and enable “locationCategory” -->

<body>

  <button onclick="BookNow.open({apiKey: 'YOUR_API_KEY_HERE', 
                                 bookingFlow:'locations',
                                 locationCategory:'required'})">
   Select Store </button>

</body> 

 

This feature can be disabled by setting its value to ‘default’ or by removing it entirely.

<!-- Set booking flow to “locations” and disable “locationCategory” -->

<body>

  <button onclick="BookNow.open({apiKey: 'YOUR_API_KEY_HERE', 
                                 bookingFlow:'locations',
                                 locationCategory:'default'})">
   Select Store </button>

</body> 

To further control and filter the content displayed by the widget, you must employ location and service tags.

Using Location and Service Tags

User-defined location and service tags are defined and assigned in the Back Office. They can then be used as parameters to filter content. 

The following examples showcase how to include and format serviceTags and locationTags.

 

Single Location Tag

<!-- Filter stores assigned with the tag “downtown” -->

<body>

   <button onclick="BookNow.open({apiKey: 'YOUR_API_KEY_HERE',
                    bookingFlow:'locations',
                    locationTags:'downtown'})">
   Book Now
    </button>

</body>

 

Single Service Tag

<!-- Filter services assigned with the service tag “vip” -->

<body>

   <button onclick="BookNow.open({apiKey:'YOUR_API_KEY_HERE',
                    serviceTags:'vip'})">
   Book Now
    </button>

</body>

 

Locations can also be filtered using serviceTags as its parameter.

Location Tag Using serviceTags

<!-- Filter locations offering at least one service with the tag “vip” -->

<body>

   <button onclick="BookNow.open({apiKey:'YOUR_API_KEY_HERE',
                    bookingFlow:'locations',
                    locationTags:'service:vip'})">
   Book Now
    </button>

</body>

 

Combining Tags using Logical Expressions

Service and Location tags can be combined to create complex filters using logical expressions. To combine tags as an “AND” expression, separate each tag with a comma “ , ”; to combine tags as an “OR” expression, separate each tag with a pipe “ | ”.  See below examples for proper formatting and usage. Take note that services will have to match all tags to appear as a result and only service tags support the “OR” expression.

  • AND : serviceTags: ‘A,B,C‘

The above will result in a match if an entry contains tag A and B and C.

  • OR : serviceTags: A|B|C

    The above will result in a match if an entry contains A or B or C.

  • AND with OR: serviceTags: A|B , C|D

    The above will result in a match if an entry contains A and B or C and D.

 

Multiple Tags using Logical Expressions

<!-- Filter locations assigned with the tag “downtown” and  -->
<!-- offering at least one “vip” or “special” service       -->

<body>

   <button onclick="BookNow.open({apiKey:'YOUR_API_KEY_HERE',
                    locationTags:'downtown',
                    serviceTags:'vip|special'})">
   Book Now
    </button>

</body>

Using the serviceId property

Use this property to open the booking widget with a preselected service ID.

<!-- Preselect a group event ID” -->

<body>
   <button onclick="BookNow.open({apiKey: 'YOUR_API_KEY_HERE',
                    serviceId: 'YOUR_SERVICE_ID'})">
   Book Now
   </button>
</body>

Using the staffId property

Use this property to open the booking widget with a preselected staff ID. Take note that this property also requires a valid service ID.

<!-- Preselect a group event ID” -->

<body>
   <button onclick="BookNow.open({apiKey: 'YOUR_API_KEY_HERE',
                    staffId: 'YOUR_STAFF_ID',
                    serviceId: 'YOUR_SERVICE_ID'})">
   Book Now
   </button>
</body>

Using the groupEventId property

Use this property to open the booking widget with a preselected group event ID. To skip the category selection screen, assign the appropriate value to “serviceCategoryId”.

<!-- Preselect a group event ID” -->

<body>
   <button onclick="BookNow.open({apiKey: 'YOUR_API_KEY_HERE',
                    groupEventId: 'YOUR_GROUP_EVENT_ID',
                    serviceCategoryId: 'YOUR_CATEGORY_ID'})">
   Book Now
   </button>
</body>

Using the availabilityTags Property

This property provides the ability to filter availability to time slots assigned with one or several tags. Each time slot supports up to 10 tags and 100 characters. Tags can be defined from the Booking API.

The following example showcases how to include and format the property availabilityTags.

Single Availability Tag

<!-- List availabilities assigned with the tag “accessible” -->

<body>
   <button onclick="BookNow.open({apiKey: 'YOUR_API_KEY_HERE',
                    bookingFlow:'locations',
                    locationTags:'downtown'
                    availabilityTags: 'accessible'})">
   Book Now
    </button>

</body>

 

Multiple Tags Using Logical Expressions

<!-- Filter availabilities assigned with the tag “accessible” and “vip”  -->

<body>
   <button onclick="BookNow.open({apiKey: 'YOUR_API_KEY_HERE',
                    locationTags:'downtown'
                    availabilityTags: 'accessible,vip'})">
   Book Now
   </button>
</body>

Callback Functions and Redirections

Callback Priority

Please take note that callback functions and redirections are subject to the following priorities:

Call Priority

Function

First

onClose

Second

onBookedRedirectTo / onAbortRedirectTo

Third

merchant.shoppingCartUrl

onClose

The callback function “onClose” receives an object as its argument when the widget is closed. That object contains booking data at the time of closure. It is therefore crucial to validate the value of “bookNowStatus” to identify if a booking has been successfully completed or aborted. When “onClose” is mapped, calls to that function will have priority over any URL redirection.

Redirect URLs

As an alternative to “onClose”, customers can be redirected to predefined URLs upon completing or aborting a booking. URLs must be assigned to their appropriate parameters (see below for reference and example).

 

onBookedRedirectTo

Redirect to the assigned URL once a booking is successfully created or updated. Upon such redirection the value of “bookNowStatus” is “booked”.

 

onAbortRedirectTo

Redirect to the assigned URL when a booking is aborted. Upon such redirection, the value of “bookNowStatus” is “abort”.

<!-- Assigning redirect URL for successful and aborted booking -->

<body>

   <button onclick="BookNow.open({apiKey:'YOUR_API_KEY_HERE',
                     onBookedRedirectTo:'https://booxi.com/thankyou.html',
                    onAbortRedirectTo:'https://booxi.com/home.html'})">
   Book Now
    </button>

</body>


Retrieving Booking Data

Booking data is passed as an argument to the callback function “onClose” or as a URL query parameter named booking if URL redirection is used. Its value is a JSON object encoded as a base 64 UTF-8 string.

To retrieve booking data follow these steps, assuming “query” has been previously parsed:

  1. Create a temporary buffer.
  2. Decode data from the base64 string using Buffer.from().
  3. Parse the resulting string into a JSON using JSON.parse().

Here’s an example for URL redirection

// Assuming query has been extracted from URL

const buffer = Buffer.from(query.booking, "base64");
const booking =  JSON.parse(buffer.toString("utf-8"));
  1. Data within “booking” is now accessible. See below for a list of properties.

Properties

Type

Description

bookNowStatus 

string

Whether the booking is complete or was aborted.  

  • Abort: user aborted before completing booking.
  • Booked: booking complete

bookingMethod

string

Type of booking.

  • Appointment
  • GroupReservation
  • Rental

bookingId

string

ID associated with completed booking.

groupEventId

integer

Group event ID for group reservations.

staffId

integer

ID of the selected staff, if any.

staffFirstName

string

First name of the selected staff, if any.

staffLastName

string

Last name of the selected staff, if any.

startsOn

string

Booking start date/time in RFC-3339/ISO-8601 format 

(ex. 2021-01-02T12:34:56Z)

clientCount

integer

Number of attendees.

payment

object

Information about the Payment stored as an object.

client

object

Information about the Client stored as an object.

items

array

Array of Items (services) associated with a booking.



Take note that properties might not be set if they are irrelevant to the booking method or if the client didn’t provide meaningful values. If a booking status is set to “abort” do not rely on the information as it will be partial.

Payment

Properties

Type

Description

onlinePaymentAmount

string

Payment amount due.

onlinePaymentId

string

Unique ID associated with a Payment.

total

string

Total Payment amount due.

 

Example of a “payment” found in the URL query parameter “booking”.

"payment": 
{
   "onlinePaymentAmount": "1.00",
   "onlinePaymentId": "P012345",
    "total": "1.00"
}

 

Items

Properties

Type

Description

serviceId

integer

ID of the service associated with an appointment or reservation.

serviceName

string

Name of the service.

serviceCategoryName

string

Name of the service's category.

productId

string

User-defined product ID. Can be assigned to a service in the Back Office once online payment + shopping cart are enabled. 

reservedTimeSpan.duration

integer

Duration of the booked appointment or reservation, in minutes.

 

Example of an “item” found in the URL query parameter “booking”.

"items":
[
{
     "serviceId": 789,
     "serviceName": "Group Activity",
     "serviceCategoryName": "Main Services",
     "productId": "PRODUCT-123",
     "reservedTimespan": { "duration": 60 }
  }
]

 

Using the showDescriptions Property

The property “showDescriptions” provides the ability to display merchant, location, category and service extended descriptions. By default, this property is set to “expand” where it is initially collapsed with a button to expand. To display all descriptions, set its value to ‘always’, to hide set its value to ‘never’.

 

Implementation

<body>

   <button onclick="BookNow.open({apiKey:'YOUR_API_KEY_HERE',
                   showDescriptions: 'always'})">
  Book Now
   </button>

</body>

Client Object

The table below lists all supported properties of the object “client” used to prefill the client section.  Take note that fields marked with an asterisk (*) are mandatory when prefilling the client info. Furthermore, fields in italic are not returned by the callback function and are not available when retrieving the booking data.

Properties

Type

Description

client.IsAttending

boolean

Is the client attending? Default value is true.

client.firstName*

string

Client’s first name.

client.lastName*

string

Client’s last name.

client.email

string

Client’s email address.

client.mobilePhoneNumber

string

Client’s mobile phone number in E164 format. If an invalid phone number is provided, the field will be left blank.

client.remindByEmail

boolean

Whether a client requests reminders via email.

client.remindBySMS

boolean

Whether a client requests reminders via text message.

client.address

array

Array of property describing a client’s address. If set, street, city, country and postal code are mandatory. If the address is located in North America (US and Canada), its state is also mandatory.

      client.address.street*

string

Client’s street address. Mandatory field.

      client.address.city*

string

Client’s city. Mandatory field.

      client.address.country*

string

Client’s country. Mandatory field.

      client.address.state*

string

Client’s state, province or territory Mandatory field (US and Canada only).

      client.address.postalCode*

string

Client’s ZIP or postal code. Mandatory field.

client.additionalRequest

string

Client’s request.

client.hideAdditionalRequest

boolean

Hides the additional request field from the client info form. Default value is "false".

client.membershipId

string

Client’s membership Id.

client.customerId

string

Client’s customer Id.

client.skipClientForm

boolean

Skips the client info form if provided info is valid and complete.

 

<button onclick="BookNow.open({ 

                apiKey: 'YOUR_API_KEY_HERE',
                client:
{
                   clientCount: 1,
                   isAttending: true,
                   firstName: 'John',
                   lastName: 'Smith',
                   email: 'john.smith@example.org',
                   mobilePhoneNumber: '+17219992437',
                   remindByEmail: true,
                   remindBySMS: false,
address: {
street: '42b Avenue',
city: 'Montreal',
country: 'CA',
state: 'QC',
postalCode: 'L5W0A1'
},
                   additionalRequest: 'Must leave before 2PM'
                   hideAdditionalRequest: true,
                   membershipId: 'MEMBER-123',
                   customerId: 'CUSTOMER-123',
                   skipClientForm: false
}
                 })">
Book Now
</button>

Supported Languages (ISO 639-1)

Here is the list of languages supported by the booking widget. For best results, provide both a language and region (e.g. fr-CA is preferred over just fr). Refer to examples provided below.

 

Language

Code

 

Language

Code

 

Language

Code

Bulgarian

bg

 

French

fr

 

Romanian

ro

Chinese

zh

 

Greek

el

 

Russian

ru

Czech

cs

 

Italian

it

 

Spanish

es

Danish

da

 

Japanese

ja

 

Swedish

sv

Deutsch

de

 

Korean

ko

 

Turkish

tr

Dutch

nl

 

Polish

pl

     

English

en

 

Portuguese

pt

     

Language + Region

  • en-KW: English, Kuwait
  • fr-FR: French, France region
  • fr-NC: French, New Caledonia
  • zh-HK: Chinese, Hong Kong region
  • zh-TW: Chinese, Taiwan region

Take note that any value assigned to the language property will supersede the language preferences set by a user in its browser or OS. If a customer wishes to display Book Now in the user's preferred language, the language property should be left unset.

The property “fallbackLanguage” can be used when English is not the default fall back language or for unsupported languages or missing translations.

Country Codes (ISO 3166)

Country, Region

Code

 

Country, Region

Code

 

Country, Region

Code

Algeria

DZ

  Hong Kong HK  

Peru

PE

Argentina

AR

 

Hungary

HU

 

Philippine

PH

Aruba AW  

Iceland

IS

 

Poland

PL

Australia

AU

 

India

IN

 

Portugal

PT

Austria

AT

 

Indonesia

ID

 

Puerto Rico

PR

Belgium

BE

  Ireland IE  

Qatar

QA

Bermuda

BM

 

Israel

IL

 

Romania

RO

Brazil

BR

 

Italy

IT

 

Saudi Arabia

SA

Bulgaria

BG

 

Japan

JP

 

Singapore

SG

Canada

CA

 

Kenya

KE

 

Slovakia

SK

Chile

CL

 

Korea

KR

 

Slovenia

SI

Colombia

CO

 

Kuwait

KW

 

South Africa

ZA

Costa Rica

CR

 

Latvia

LV

 

Spain

ES

Croatia

HR

 

Lebanon

LB

 

Sweden

SE

Cyprus

CY

 

Lithuania

LT

 

Switzerland

CH

Czech Republic

CZ

 

Luxembourg

LU

 

Taiwan

TW

Denmark

DK

  Macau MO  

Thailand

TH

Dominican Republic

DO

 

Malaysia

MY

 

The Bahamas

BS

Ecuador

EC

 

Malta

MT

 

Trinidad & Tobago

TT

Egypt EG  

Martinique

MQ

 

Tunisia

TN

Estonia

EE

 

Mexico

MX

 

Turkey

TR

Finland

FI

 

Morocco

MA

 

United Arab Emirates

AE

France

FR

 

Netherlands

NL

 

United Kingdom

GB

French Guiana

GF

 

New Caledonia

NC

 

United States

US

Germany

DE

 

New Zealand

NZ

 

Uruguay

UY

Greece

GR

 

Norway

NO

 

Vietnam

VN

Guadeloupe

GP

 

Panama

PA

     

Guyana

GY

 

Paraguay

PY

 

 

 

Rendering in a Webview

If you intend to use the Booking Widget in a webview within a mobile application, the widget might be displayed in 2 columns (like it would be on PC) or as a single column but with very small font making its content unreadable. To avoid such problems, add the following code in the <head> tag of the web page containing the widget.

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
</head>

 

Stack Order

The CSS property “z-index” can be used to set the stack order in which the booking widget will be displayed.

 

CSS Syntax

z-index: auto | number | initial | inherit;

Implementation

In a .CSS file, create an id selector with a “z-index” property and assign it with a numeral value. Elements with higher stack order are displayed in front of those with lower stack order.

 

CSS

<style>
  #my_custom_iframe_id { z-index: 500;}
</style>

 

On your webpage, upon calling the method “BookNow.open()”, add the parameter “iframeId” and set its value as shown below.

 

HTML

<button onclick="BookNow.open({ 
                apiKey: 'YOUR_API_KEY_HERE',
                iframeId: 'my_custom_iframe_id',
                })"> Book Now
</button>

UI Customization

All UI customizations are performed by Booxi and solely on a request basis. Please contact your CSM or AM to make such requests.

 

Customizations are currently limited to:

  • Font Family*
  • Colors
  • UI Styles

For further details, please consult the Widget Customization Guide.
* If you are expecting to use a proprietary font or font without a free license, please contact your Booxi presentative.

Test and Validation

Before integrating any changes to your webpage, testing and validation can be performed on an unbound landing page or using an online HTML editor. For a simple solution use w3schools Tryit Editor.


Limitations

The current version of Book Now (ADA compliant) has limited functionalities. Here’s a summary of the functionalities you should pay attention to:

  • The property “bookingFlow” can only be set to “locations” or “merchants”.
  • The property “mode” only supports “iFrame”.
  • Book Now will filter out services it doesn’t support
    • Rental 
    • At Home services
    • Requesting the client availability
  • Other unsupported features
    • Online payments

Google Analytics 4 Integration

To enable Google Analytics (GA4), consult the following integration guide.