The Kloudless Meeting Scheduler is a JavaScript library that allows your users to create and schedule meetings with each other. There are two main parts to the Meeting Scheduler:
- First, the organizer sets up the meeting details: name, location, duration, and recurrence. The organizer will then connect their calendar to monitor any meeting conflicts in real-time. The organizer will lastly receive a link to invite attendees when finished with the setup.
- Second, a user will choose available time slots and confirm the meeting.
The Meeting Scheduler is currently compatible with the following calendar providers using the Kloudless Calendar API:
- Google Calendar
- Outlook Calendar, and Exchange Online
- Exchange Server 2016+
- CalDAV
Integrate the Kloudless Meeting Scheduler widget into your app today by creating a Kloudless app, using our zero-configuration embed script, or importing and customizing it into your app!
- Supported Browsers
- Terminology
- Getting Started
- Configuration Examples
- Advanced Usage
- Methods
- Events
- Meeting Window API
- Migration Guide
- Contribute
- Support
- Changelog
- Google Chrome 70.0+
- Mozilla Firefox 63.0+
- Microsoft Edge
- Safari 11.1.2+
There are 2 modes available for the Kloudless Meeting Scheduler widget.
Allows the user to connect their calendar via Kloudless and describe an event. Users can add event details and available time slots in the widget. The widget then displays a public URL with a unique ID to share with others to schedule the event.
Launches the widget with a specific Event ID. Users can choose from the event's available time slots to schedule an event on their calendar. A meeting invitation will be sent from the event organizer to the user.
A Meeting Window contains detailed information for a event, such as the event title, location, host's calendar and host's availability. This object is created when user clicks "Create Event" from the Setup View.
The information in this object is then used to schedule events in the Schedule View.
A Kloudless App is required to use the Kloudless Meeting Scheduler widget.
Add the following iframe to your web page to launch the Setup View without any additional code:
<iframe src="https://kloudl.es/m/b/<app_id>" width="515px" height="695px">
Replace <app_id>
with your Kloudless App ID. You can obtain the App ID by
visiting the
App Details page of
the Kloudless developer portal.
The events created by the widget use URLs hosted by Kloudless, so you don't need to do anything else. (See this example for detailed explanation).
To launch the widget with additional options, follow the steps below to integrate the widget into your app:
You need to add your website's domain to your Kloudless app's list of
Trusted Domains
on the App Detail Page.
This allows your web page to receive access tokens to the Kloudless API.
To launch the widget with additional options, you will need to include the widget's stylesheet and script:
<link rel="stylesheet" href="https://static-cdn.kloudless.com/p/platform/sdk/kloudless.scheduler.css">
<script type="text/javascript" src="https://static-cdn.kloudless.com/p/platform/sdk/kloudless.scheduler.js"></script>
The script will expose a window.Kloudless.scheduler
object that can be used
to launch the widget:
const scheduler = new window.Kloudless.scheduler();
// launch the Setup View
scheduler.launch({
appId: '<your_app_id>',
setup: {}
})
// launch the Schedule View
scheduler.launch({
appId: '<your_app_id>',
schedule: {
// meetingWindowId is returned from Setup View
meetingWindowId: '<meeting_window_id>'
}
})
If you'd like to use the widget in your webpack project instead, it can also
be imported with the ES6 import/export syntax, as shown below. The
CSS and JS files can be found in dist/
after building the code as
described in the Building section.
import './meeting-scheduler.min.css';
import MeetingScheduler from './meeting-scheduler.min.js';
const scheduler = new MeetingScheduler();
// launch the Setup View
scheduler.launch({
appId: '<your_app_id>',
setup: {}
})
// launch the Schedule View
scheduler.launch({
appId: '<your_app_id>',
schedule: {
// meetingWindowId is returned from Setup View
meetingWindowId: '<meeting_window_id>'
}
})
Check the configuration examples below to see how the
options can be configured in scheduler.launch()
for different scenarios.
A Kloudless App ID is required to launch the Setup View. You can obtain an App ID by visiting the App Details page of the Kloudless developer portal.
To launch the Setup view, set the setup
property as an empty object to apply
default settings:
scheduler.launch({
appId: '<your_app_id>',
setup: {},
})
By default, the widget will launch as a full-screen modal display. You can choose to attach the widget to any DOM element instead as well.
Set the mode
option to attach
and the element
option to a CSS selector
for the DOM element you'd like the widget to be included within:
<div id="kloudless-meeting-scheduler"></div>
scheduler.launch({
appId: '<your_app_id>',
mode: 'attach',
element: '#kloudless-meeting-scheduler',
setup: {},
});
If you would like to launch the widget with an existing calendar account, you can import the calendar with a specific Bearer token using the widget's configuration options. The user will not need to connect an account and the widget will instead use the imported account.
scheduler.launch({
appId: '<your_app_id>',
setup: {
accountToken: '<account_bearer_token>'
}
})
By default, after creating a Meeting Window in the Setup View,
a URL link with the format https://kloudl.es/m/MEETING_WINDOW_ID
is generated.
Kloudless hosts this URL by default so your users can use this URL to launch
the Schedule View and schedule events.
However, if you'd like to host your own page that launches the Schedule View,
or if you'd like to customize the view in any way, you would need to
configure the schedule URL by using the scheduleUrl
option.
The scheduleUrl
option is a template string that contains the text
MEETING_WINDOW_ID
as a placeholder for the actual Meeting Window ID.
An example is shown below.
scheduler.launch({
appId: '<your_app_id>',
setup: {
scheduleUrl: 'https://your.website/?meetingWindowId=MEETING_WINDOW_ID'
}
})
The Meeting Scheduler will replace MEETING_WINDOW_ID
with an actual ID
to generate the appropriate URL for each Meeting Window.
Since the Schedule View is now accessible to users at a different URL, that page must take steps to launch the Schedule View as described below.
Kloudless launches the Schedule View for users visiting hosted event pages automatically. See how to customize the schedule URL for more information.
If you have the scheduleUrl
option set and put meeting window id as a
query param, you can use getQueryParams
helper method to retrieve it:
// assume meeting window id is specified in meetingWindowId query param
const { meetingWindowId } = window.Kloudless.scheduler.getQueryParams();
scheduler.launch({
appId: '<your_app_id>',
schedule: {
meetingWindowId: meetingWindowId
}
});
The above examples use launch(options)
to configure and launch the scheduler.
If you would like to configure and verify the options, but not launch the view
immediately, you can use config(options)
instead:
scheduler.config({
appId: '<your_app_id>',
setup: {
// you setup options here
}
});
/* do other things */
scheduler.launch();
By default, after scheduling an event in the Schedule View, a URL link with the
format https://kloudl.es/m/s/SCHEDULED_EVENT_ID
is generated.
Kloudless hosts this URL by default so your users can use this URL to launch
the Schedule View and re-schedule events.
However, if you'd like to host your own page that launches the Schedule View,
or if you'd like to customize the view in any way, you would need to
configure the re-schedule URL by using the rescheduleUrl
option.
The rescheduleUrl
option is a template string that contains the text
SCHEDULED_EVENT_ID
as a placeholder for the scheduled event.
An example is shown below.
scheduler.launch({
appId: '<your_app_id>',
schedule: {
rescheduleUrl: 'https://your.website/?scheduledEventId=SCHEDULED_EVENT_ID'
}
})
The Meeting Scheduler will replace SCHEDULED_EVENT_ID
with an actual ID to
generate the appropriate URL for each scheduled event.
Since the Schedule View is now accessible to users at a different URL, please refer to Edit Scheduled Event for details on launching the Schedule View in edit mode.
Your app can listen to the Meeting Scheduler's events to receive data created from the widget or perform certain actions at a desired time.
scheduler.on('open', (eventData) => {
console.log('Scheduler', eventData.scheduler, 'is launched!');
});
Refer to the Event List for available events and data provided for each event.
Make sure you have setup trusted domains for your app, otherwise your app won't receive access tokens.
To receive the connected account's access token from your app, add an event listener for the connectAccount event:
scheduler.on('connectAccount', (eventData) => {
console.log('Account', eventData.account, 'is connected.');
console.log('Account Token:', eventData.accountToken);
// save the token into your App, or make additional requests with this token
});
This can be useful for making additional requests to the Kloudless API with your app (connected to the calendar account).
To edit a Meeting Window, you need to provide both the accountToken
and
meetingWindowId
, which are all returned from the submitMeetingWindow
event
when a user creates a Meeting Window from the Setup View.
scheduler.on('submitMeetingWindow', (eventData) => {
// put your own code to record account token and meeting window id
console.log('Account Token:', eventData.accountToken);
console.log('Meeting Window ID:', eventData.meetingWindow.id);
});
scheduler.launch({
appId: '<your_app_id>',
setup: {},
});
To launch Edit Mode, pass these two values back to scheduler:
scheduler.launch({
appId: '<your_app_id>',
setup: {
accountToken: '<saved_account_token>',
meetingWindowId: '<saved_meeting_window_id>'
},
});
To edit a scheduled event, provide the scheduledEventId
attribute, which is
returned in the callback to the schedule
event when a user schedules a
meeting from the Schedule View.
scheduler.on('schedule', (eventData) => {
console.log('Scheduled Event ID:', eventData.scheduled_event_id);
});
scheduler.launch({
appId: '<your_app_id>',
schedule: {
meetingWindowId: '<your_meeting_window_id>'
},
});
To launch the Edit Mode, pass scheduledEventId
back to the Scheduler:
scheduler.launch({
appId: '<your_app_id>',
schedule: {
scheduledEventId: '<saved_scheduled_event_id>'
},
});
If you'd like to provide your own result screen instead of the default one,
use the afterSubmit.showResult
option to destroy the view, instead of showing
the result after the submit event. You will need to add an event listener to the
submitMeetingWindow
event so that your app is notified when user finishes
creating / editing a Meeting Window:
scheduler.launch({
appId: '<your_app_id>',
setup: {
afterSubmit: {
showResult: false
}
}
});
scheduler.on('submitMeetingWindow', (eventData) => {
console.log('Meeting Window details:', eventData.meetingWindow);
console.log('Schedule URL:', eventData.scheduleUrl);
// create your own result screen here
})
Similarly, it is also possible to provide your own screen for the Schedule View instead of using the default one:
scheduler.launch({
appId: '<your_app_id>',
schedule: {
afterSchedule: {
showResult: false
}
}
});
scheduler.on('schedule', (eventData) => {
console.log('calendar event details:', eventData.scheduledEvent);
// create your own result screen here
})
Refer to the submitMeetingWindow and schedule event for more details.
The form in both views can be filled in automatically with values set in the launch options. We've included an example below that sets default field values:
-
For Setup View:
scheduler.launch({ appId: '<your_app_id>', setup: { formOptions: { title: { default: "title" }, description: { default: "description" }, location: { default: "location" }, duration: { default: 60 }, organizer: { default: "shirley" }, weekday: { default: ["MON", "TUE", "FRI"] }, startHour: { default: "12:00:00" }, endHour: { default: "14:00:00" }, timeSlotInterval: { default: 60 }, availabilityRange: { default: 60 }, timeBufferBefore: { default: 30 }, timeBufferAfter: { default: 10 } } } });
-
For Schedule View:
scheduler.launch({ appId: '<your_app_id>', schedule: { meetingWindowId: '<your_meeting_window_id>', formOptions: { name: { default: "Johnny Appleseed" }, email: { default: "youremail@example.com" } } } });
Refer to options for details.
You can customize how the Meeting Scheduler looks by utilizing the
customStyleVars
configuration option. This attribute should contain an object
of the format {[variableName]: value}
, where [variableName]
refers to a
LESS variable listed in the
variables.less file in the source code. The
variables.less
file also includes notes on the purpose of each variable.
Here is an example where the Meeting Scheduler uses a dark theme with the primary text font changed to Calistoga:
Here is the corresponding JS configuration with the custom LESS variables used to alter the color scheme and font:
{
scheduler.launch({
appId:
customStyleVars: {
primary: "#FFEE58",
background: "#37474F",
secondary: "#FFCA28",
surface: "#26C6DA",
error: "#EF5350",
onPrimary: "white",
onSecondary: "#BDBDBD",
onPrimaryVariant: "black",
onSecondaryVariant: "#78909C",
disabled: "#dcdcdc",
fontFaceName: "'Calistoga'",
fontFacePath: "'https://fonts.gstatic.com/s/calistoga/v1/6NUU8F2OJg6MeR7l4e0fs8wB49dJfg.woff2'",
fontFaceFormat: "'woff2'",
fontFamily: "'Calistoga', 'sans-serif'"
},
setup: {}
});
}
Notes:
- It is unnecessary to include the
@
symbol usually prefixed to LESS variable names when specifying the variable names as attributes in thecustomStyleVars
object. - String properties such as the font family and font face URL require an additional set of quotes surrounding the text value.
If you would like to fix the connected calendar and not allow users to edit it,
you need to set the Bearer token of the calendar account and calendar ID.
Be sure the calendar is accessible by the calendar account, otherwise, a
validate error will show up.
Calendar IDs can be obtained by list calendar
endpoint.
Also, set setup.formOptions.bookingCalendarId.visible
to false
to
prevent users from changing connected calendar.
scheduler.launch({
appId: '<your_app_id>',
setup: {
accountToken: '<account_token>',
formOptions: {
bookingCalendarId: {
default: "<calendar_id>",
visible: false
},
}
}
});
By default, each event scheduled will be created based on its Meeting Window object. However, it's possible to configure additional metadata to include or override in scheduled events, using the approaches below.
When launching the Setup View, apps can configure launch options that include default calendar event metadata to apply to all scheduled events:
scheduler.launch({
appId: '<your_app_id>',
setup: {
formOptions: {
defaultEventMetadata: { transparent: true },
}
}
});
After the Meeting Window is created, all calendar events created from the
Meeting Window above will have the transparent
property set to true
.
Note that not all event properties are customizable. Please refer to the APIMeetingWindow.default_event_metadata docs for available properties.
It's also possible to customize the event metadata on a per-event basis during the scheduling process instead.
Since this potentially exposes the calendar
event to customization via client-side JS by a skilled user, Kloudless requires
the allowEventMetadata
flag to be set to true
during the setup process for
the Scheduler's configuration to take effect, as shown below:
scheduler.launch({
appId: '<your_app_id>',
setup: {
formOptions: {
allowEventMetadata: true,
}
}
});
In the Schedule view, customize calendar event metadata before creation by listening for the preSchedule JS event:
scheduler.on('preSchedule', (eventData) => {
const { meetingWindow, schedule } = eventData;
schedule.event_metadata = {
extra_description: schedule.targets[0].name
}
return schedule;
});
By setting event_metadata.extra_description
, each scheduled event will have
the attendee's name in the event description. Please refer to the
preSchedule event docs for more details and available
attributes.
For more examples, please check the launch(options) for a full list of available options and their usage.
Configure the Meeting Scheduler.
An object containing the following keys:
-
appId
: Required: String
Your Kloudless application App ID. -
mode
: Optional (default: 'modal'): 'modal' or 'attach'
If set to 'modal', a modal window is shown and the widget is displayed inside the modal. If set to 'attach', the widget will be attached to the element specified in theelement
parameter. The widget requires a validelement
option to launch correctly. -
element
: Required only forattach
mode: String or Element
The DOM element that the widget will be attached to. All contents under the element will be removed before attaching the widget. If a String is provided, it will be used to retrieve the DOM element by using document.querySelector. This option is ignored ifmode
ismodal
.- Example: Launch with attach mode
-
customStyleVars
: Optional (default: undefined): object
An object to specify LESS variables for custom UI styling. The object format is{[variableName]: value}
. See here for more details. -
setup
: Required for the Setup View: Object
Options to launch Setup View, available options:accountToken
: Optional (default: null): String
If you would like to launch the widget with an existing calendar account, you can import the calendar with a specific Bearer token using theaccountToken
option. The user will not need to connect an account and the widget will instead use this imported account.
Required for Edit existing Meeting WindowscheduleUrl
: Optional (default: 'https://kloudl.es/m/MEETING_WINDOW_ID'): String
A template string for the URL provided to users to schedule the event. TheMEETING_WINDOW_ID
in the string will be replaced with the actual meeting window ID.- Example: Customize the event URL format
meetingWindowId
: Optional (default: null): String
If specified, the scheduler will launch in Edit mode to edit the provided Meeting Window. Users can also delete this Meeting Window from the view.
Note thataccountToken
is required for edit mode.afterSubmit
: Optional (default: see below): String- An object to specify the behavior after a Meeting Window is created/updated/deleted:
showResult
: Optional (default: true): Boolean
If true, a result page will be displayed. Otherwise, the scheduler is destroyed, and you will need to use the submitMeetingWindow or deleteMeetingWindow event to catch the result.actions
: Optional (default: ['close']): Array
A list of available actions for users to choose from. Supported actions include:'close'
: Close and destroy the scheduler.'restart'
: Go back and create another Meeting Window. Note that this is not supported in the Edit Mode.
- An object to specify the behavior after a Meeting Window is created/updated/deleted:
formOptions
: Optional (default: see below): Object- An object to configure the form fields of the Setup View.
title
: Optional (default: {visible: true, default: ''}): Object Configure the default value and visibility of event title.default
: Optional (default: ''): Stringvisible
: Optional (default: true): Booleantitle.default
cannot be empty if this isfalse
.
description
: Optional (default: {visible: true, default: ''}): Object Configure the default value and visibility of event description.default
: Optional (default: ''): Stringvisible
: Optional (default: true): Boolean
location
: Optional (default: {visible: true, default: ''}): Object Configure the default value and visibility of event location.default
: Optional (default: ''): Stringvisible
: Optional (default: true): Boolean
duration
: Optional (default: {visible: true, default: 15}): Object Configure the default value and visibility of event duration.default
: Optional (default: 15): Numbervisible
: Optional (default: true): Boolean
organizer
: Optional (default: {visible: true, default: ''}): Object Configure the default value and visibility of event organizer.default
: Optional (default: ''): Stringvisible
: Optional (default: true): Booleanorganizer.default
cannot be empty if this isfalse
.
weekday.default
: Optional (default: []): Array
The default available weekdays. Possible values:SUN
,MON
,TUE
,WED
,THU
,FRI
, andSAT
.startHour.default
: Optional (default: '08:00:00'): String
An ISO 8601 timestamp without offset indicating the default availibility start time. Possible values:00:00:00
–23:00:00
.endHour.default
: Optional (default: '17:00:00'): String
An ISO 8601 timestamp without offset indicating the default availability end time. Possible values:01:00:00
–00:00:00
.timeSlotInterval
: Optional (default: {visible: true, default: 30}): Object The number of minutes between each time slot.default
: Optional (default: 30): Number Possible values: 15, 30, 45, or 60.visible
: Optional (default: true): Boolean
availabilityRange
: Optional (default: {visible: true, default: 30}): Object The number of days from the current date to show time slots for.default
: Optional (default: 30): Number Possible values: 1–99.visible
: Optional (default: true): Boolean
timeBufferBefore
: Optional (default: {visible: true, default: 0}): Object The number of minutes to leave free before each scheduled event.default
: Optional (default: 0): Number Possible values: 0–99.visible
: Optional (default: true): Boolean
timeBufferAfter
: Optional (default: {visible: true, default: 0}): Object The number of minutes to leave free after each scheduled event.default
: Optional (default: 0): Number Possible values: 0–99.visible
: Optional (default: true): Boolean
bookingCalendarId
: Optional (default: {visible: true, default: ''}): Object Configure the default value and visibility of selected calendar ID.default
: Optional (default: <The 1st calendar's ID return from Calendar List API>): String This requiressetup.accountToken
to be set. Also, please make sure the calendar is accessible by that account. Can useprimary
as an alias for the id of the primary calendar.visible
: Optional (default: true): BooleanbookingCalendarId.default
must be set if this isfalse
.
allowEventMetadata
: Optional (default: false): Boolean
Set this totrue
to allow changing the created calendar event details via a preSchedule event handler.defaultEventMetadata
: Optional (default: null): JSON Object
Additional event metadata to set for any calendar event created with this Meeting Window. See the MeetingWindow.default_event_metadata docs for properties available to include in this object.
- Example:
{ title: { default: "" }, description: { default: "" }, location: { default: "" }, duration: { default: 15 }, // 15, 30, 60 organizer: { default: "" }, weekday: { default: [] }, // SUN, MON, TUE, WED, THU, FRI, SAT startHour: { default: "08:00:00" }, // 00:00:00 – 23:00:00 endHour: { default: "17:00:00" }, // 01:00:00 – 00:00:00 timeSlotInterval: { default: 30 }, // 15, 30, 45, 60 availabilityRange: { default: 30 }, // 1 – 90 timeBufferBefore: { default: 0 }, // 0 – 99 timeBufferAfter: { default: 0 }, // 0 – 99 bookingCalendarId: { default: "primary" } }
- An object to configure the form fields of the Setup View.
authOptions
: Optional (default: see below): Object-
An object to configure the query parameters used during the Kloudless OAuth 2.0 flow to connect a calendar account.
The Meeting Scheduler leverages the Authenticator library for OAuth so will pass the
authOptions
object to the Authenticator's options.Here is the default
authOptions
object:{ scope: 'calendar:normal' }
If you want to explicitly define the available services for account connection, you can change the
scope
option. Here is an example to explicitly define Google Calendar and Outlook Calendar as available services:{ scope: 'google_calendar outlook_calendar' }
The following options cannot be overridden for consistency or security reasons:
client_id
response_type
redirect_uri
state
Please check the Authenticator options for more details on the format and attributes accepted.
-
-
schedule
: Required for the Schedule View: Object
Options to launch the Schedule View. Available options:rescheduleUrl
: Optional (default: 'https://kloudl.es/m/s/SCHEDULED_EVENT_ID'): String
A template string for the URL provided to users to edit the scheduled event. TheSCHEDULED_EVENT_ID
in the string will be replaced with the actual scheduled event ID.- Example: Customize the Re-Schedule URL
meetingWindowId
: Required: String The Meeting Window ID .- Example: Launch the Schedule View
timeZone
: Optional: String
Set the default time zone when the view is launched. The possible values are:'local'
: Use the browser's time zone. This is the default value.'organizer'
: Use the time zone from the Meeting Window.- Any IANA time zone string (e.g.
America/Los_Angeles
)
afterSchedule
: Optional: Object- An object to specify the behavior after an event is scheduler, available
options:
showResult
: Optional (default: true): Boolean
If true, a result page will be displayed. Otherwise, the scheduler is destroyed, you will need to use the schedule event to catch the result.actions
: Optional (default: ['close']): Array
A list of available actions for users to choose from. Supported actions include:'close'
: Close and destroy the scheduler.
- An object to specify the behavior after an event is scheduler, available
options:
formOptions
: Optional (default: see below): Object- An object to configure the form fields of the Setup View.
name
: Optional (default: {default: '', visible: true}): Object Configure the default value and visibility of the attendee's name.default
: Optional (default: ''): Stringvisible
: Optional (default: true): Booleanname.default
cannot be empty if this isfalse
.
email
: Optional (default: {default: '', visible: true}): Object Configure the default value and visibility of the attendee's email.default
: Optional (default: ''): Stringvisible
: Optional (default: true): Booleanemail.default
cannot be empty if this isfalse
.
extraDescription
: Optional (default: ''): Objectdefault
: Optional (default: ''): String The default notes to append to the created event's description.visible
: Optional (default:false
): Boolean Visibility of this field. If the Meeting Window object hasallow_event_metadata
set totrue
when created via the Setup process, it allows the Schedule view to alter the title and description of the created calendar event. This allows a user to add in additional notes to the calendar event description via this field. Any original description configured for the calendar event in the Setup view will not be overwritten and will still be included in addition within the calendar event description.
- Example:
{ name: { default: "Johnny Appleseed" }, email: { default: "youremail@example.com" } }
- An object to configure the form fields of the Setup View.
Note: You must specify either setup
or schedule
to launch the Meeting
Scheduler.
Launch the meeting scheduler widget. If options
is provided, it will call
config(options) to configure the scheduler before launching.
Remove the configured meeting scheduler widget from the page and free up memory.
Set global options. The widget is configured to work with default values, so these options should only be set when needed.
An object containing the following keys:
baseUrl
: String, Kloudless API server URL, you only need this when hosting your own Kloudless API server.schedulerPath
: String, URL that hosts the scheduler page, you only need this when hosting the embedded scheduler page. See Host the scheduler page for more information.
Get the global options object.
Retrieve an object representing query parameters as key-value map from current URL.
Return version number string.
Events are emitted asynchronously when conditions are met. To register an event,
use scheduler.on(eventName, callback)
. Use scheduler.off(eventName, callback)
or scheduler.off(eventName)
to unregister all callbacks from a certain event.
The callback function will receive an object as the first argument with the following properties:
scheduler
: MeetingScheduler instance that received the event.- All event data for the event will be attached as additional keys to this object, please reference to Event List for details.
The scheduler has launched.
The scheduler has closed.
The scheduler window and placeholders have been destroyed.
A calendar account has been connected.
Event Data:
account
: Object; Connected accountaccountToken
(*1): String; Bearer Token of this account
A calendar account has been removed.
A Meeting Window is about to be created or updated.
A Meeting Window has been created or updated.
Event Data:
meetingWindow
: Meeting Window objectaccountToken
(*1): String; Bearer Token of this account
A Meeting Window has been deleted.
Triggered before a time slot is booked in the Schedule view.
Event Data:
meetingWindow
: Object; The Meeting Window object this time slot selection was created for.schedule
: Object; Details for the selected time slot, including the selected time and attendee information.
Return Value:
-
Modify and return the
schedule
object provided to override details for the calendar event about to be scheduled. This requires your application to ensure themeetingWindow
object has the propertyallow_event_metadata
set totrue
during the Setup process. You can then modifyschedule
to add in the propertyevent_metadata
as shown below.schedule.event_metadata
accepts the following attributes:name
: Overrides the calendar event's nameextra_description
: Appends extra text to the calendar event's description.
Note: Users can add their own extra notes via the launch optionschedule.formOptions.extraDescription.visible
. The input text will then be populated in thisschedule.event_metadata.extra_description
property by default when included in the event data provided for this event. To still add additional text beyond the user's input, append it to the existing value of this property.
scheduler.on('preSchedule', (eventData) => { const { meetingWindow, schedule } = eventData; schedule.event_metadata = { name: meetingWindow.title + ' - Custom', extra_description: 'Custom additional description.' } return schedule; })
-
Don't return anything, or return
undefined
, if you don't want to change theschedule
object.
Triggered when a time slot is booked via the Schedule view.
Event Data:
scheduledEvent
: Object, scheduled calendar event details, including calendar event ID.
A view has been restarted.
This event is currently only emitted in the Setup View when a user has clicked 'Create another event' button to set up a new Meeting Window after setting one up.
An error response, or no response returned for an API request.
Event Data:
message
: String; Error message if available.
(*1) This data is only sent when the scheduler is launched from a Trusted Domain.
The Meeting Window object contains information used for scheduling events with the Kloudless Calendar.
Property | Type | Description | Writable | Required |
---|---|---|---|---|
id | string | The meeting window's unique identifier. | No | No |
booking_calendar_id | string | The Kloudless calendar ID to store the scheduled event. | Yes | Yes |
duration | integer | The event duration in minutes. | Yes | Yes |
title | string | The event title. | Yes | Yes |
organizer | string | The name of the event organizer. | Yes | Yes |
location | string | The event location. | Yes | No |
description | string | The event description. | Yes | No |
availability | string | A list of Availability objects. See Availability for details. | Yes | Yes |
time_zone | string | The event IANA time_zone. e.g. America/Los_Angeles |
Yes | Yes |
availability_range | integer | Indicates the number of days from the current point in time to show time slots. Defaults to 30 . |
Yes | No |
time_slot_interval | integer | Indicates the number of minutes of time between each time slots. Defaults to 30 . |
Yes | No |
time_buffer_before | integer | Indicates the number of minutes of buffer time before each scheduled event. Defaults to 0 . |
Yes | No |
time_buffer_after | integer | Indicates the number of minutes of buffer time after each scheduled event. Defaults to 0 . |
Yes | No |
allow_event_metadata | boolean | Indicates if the created calendar event can be customized when scheduling events. See the preSchedule event for details. Defaults to false . |
Yes | No |
default_event_metadata | object | Additional calendar event metadata to set when scheduling events. Defaults to {} . See the Event creation API endpoint for available attributes. The following attributes are reserved and can't be set: id , name , description , location , start , end , start_time_zone , end_time_zone , all_day , and recurrence . |
Yes | No |
The Availability object contains the rules to generate the available time slots. It is located within the Meeting Window object.
Property | Type | Description | Writable | Required |
---|---|---|---|---|
available_times | array | A list of availability rules. | Yes | Yes |
available_times[].start | string | The ISO 8601 time format in hh:mm:ss that indicates the time window's start time. |
Yes | Yes |
available_times[].end | string | The ISO 8601 time format in hh:mm:ss that indicates the time window's end time. |
Yes | Yes |
available_times[].recurring | object | The recurrence constraint for the availability range. | Yes | Yes |
available_times[].recurring.weekday | string | The weekdays to include availability for. Accepts 3 characters abbreviations with a comma as delimiter. For example, "MON, TUE" means to show availability for Mondays and Tuesdays. |
Yes | Yes |
available_times[].recurring.month | string | Currently not supported. | No | No |
available_times[].recurring.day | string | Currently not supported. | No | No |
end_repeat | string | An ISO 8601 date, or 'NEVER' . The available_times rules will be applied until this date. Defaults to 'NEVER' , which means time slots are generated for as many days as possible (subject to availability_range ). |
Yes | No |
To use the Meeting Window API, the Bearer authentication with a Kloudless bearer token is needed. See Obtaining an Access Token for more details.
Refer to Meeting Window for Meeting Window properties.
List the user's Meeting Windows. The user is identified by the bearer token.
-
Query parameters
page
Page identifierpage_size
Number of objects in each page.
-
Response
200
response body
Array of Meeting Windows. See Meeting Window for Meeting Window's properties.
{
"count": 1,
"total": 88,
"page": 1,
"objects": [
{
"id": "azOd1NlAnDNKzscCYE4g",
"booking_calendar_id": "faG9uZ2NoZW4uZGV2QGdtYWlsLmNvbQ==",
"duration": 15,
"title": "Wine Tasting Tour",
"organizer": "Peter",
"location": "Napa",
"description": "Wonderful wine tasting.",
"availability": {
"end_repeat": "NEVER",
"available_times": [
{
"start": "09:00:00",
"end": "17:00:00",
"recurring": {
"weekday": "MON, TUE, WED, THU, FRI, SAT, SUN",
"month": "*",
"day": "*"
}
}
]
},
"time_buffer_before": 0,
"time_buffer_after": 0,
"time_slot_interval": 30,
"availability_range": 60,
"time_zone": "America/Los_Angeles",
"api": "meeting_scheduler",
"allow_event_metadata": false,
"default_event_metadata": {}
}
],
"type": "object_list",
"api": "meeting_scheduler"
}
Retrieve the meeting window via meeting window ID.
- Response
200
response body
See meeting window for meeting window's properties.
{
"id": "azOd1NlAnDNKzscCYE4g",
"booking_calendar_id": "faG9uZ2NoZW4uZGV2QGdtYWlsLmNvbQ==",
"duration": 15,
"title": "Wine Tasting Tour",
"organizer": "Peter",
"location": "Napa",
"description": "Wonderful wine tasting.",
"availability": {
"end_repeat": "NEVER",
"available_times": [
{
"start": "09:00:00",
"end": "17:00:00",
"recurring": {
"weekday": "MON, TUE, WED, THU, FRI, SAT, SUN",
"month": "*",
"day": "*"
}
}
]
},
"time_buffer_before": 0,
"time_buffer_after": 0,
"time_slot_interval": 30,
"availability_range": 60,
"time_zone": "America/Los_Angeles",
"api": "meeting_scheduler",
"allow_event_metadata": false,
"default_event_metadata": {}
}
Create a Meeting Window.
- Request body
- See Meeting Window for writable and required properties.
{
"booking_calendar_id": "faG9uZ2NoZW4uZGV2QGdtYWlsLmNvbQ==",
"duration": 15,
"title": "Wine Tasting Tour",
"organizer": "Peter",
"location": "Napa",
"description": "Wonderful wine tasting.",
"availability": {
"end_repeat": "NEVER",
"available_times": [
{
"start": "09:00:00",
"end": "17:00:00",
"recurring": {
"weekday": "MON, TUE, WED, THU, FRI, SAT, SUN",
}
}
]
},
"time_zone": "America/Los_Angeles",
"availability_range": 60,
"time_slot_interval": 30,
"time_buffer_before": 0,
"time_buffer_after": 0
}
- Response
201
response body
See Meeting Window for Meeting Window properties.
{
"id": "azOd1NlAnDNKzscCYE4g",
"booking_calendar_id": "faG9uZ2NoZW4uZGV2QGdtYWlsLmNvbQ==",
"duration": 15,
"title": "Wine Tasting Tour",
"organizer": "Peter",
"location": "Napa",
"description": "Wonderful wine tasting.",
"availability": {
"end_repeat": "NEVER",
"available_times": [
{
"start": "09:00:00",
"end": "17:00:00",
"recurring": {
"weekday": "MON, TUE, WED, THU, FRI, SAT, SUN",
"month": "*",
"day": "*"
}
}
]
},
"time_buffer_before": 0,
"time_buffer_after": 0,
"time_slot_interval": 30,
"availability_range": 60,
"time_zone": "America/Los_Angeles",
"api": "meeting_scheduler",
"allow_event_metadata": false,
"default_event_metadata": {}
}
Update the meeting window.
- Request body
- See meeting window for the writable properties.
{
"description": "Agenda: Wine tasting",
}
- Response
200
response body
See meeting window for Meeting Window properties.
{
"id": "rMAABzrAGXA3CMd9sMcg",
"booking_calendar_id": "faG9uZ2NoZW4uZGV2QGdtYWlsLmNvbQ==",
"duration": 15,
"title": "Wine Tasting Tour",
"organizer": "Peter",
"location": "Napa",
"description": "Agenda: Wine tasting",
"availability": {
"end_repeat": "NEVER",
"available_times": [
{
"start": "09:00:00",
"end": "17:00:00",
"recurring": {
"weekday": "MON, TUE, WED, THU, FRI, SAT, SUN",
"month": "*",
"day": "*"
}
}
]
},
"time_buffer_before": 0,
"time_buffer_after": 0,
"time_slot_interval": 30,
"availability_range": 60,
"time_zone": "America/Los_Angeles",
"api": "meeting_scheduler",
"allow_event_metadata": false,
"default_event_metadata": {}
}
Delete the Meeting Window.
- Response
204
To monitor events scheduled by the Meeting Scheduler, you can choose to either receive WebHooks from Kloudless, or poll the account via the Activity Stream endpoint.
We recommend receiving WebHooks if possible since your application will receive a notification immediately after a time slot is booked by a user with the ID of the calendar event created.
If your application can't receive webhooks, the Activity Stream endpoint returns all activity in the connected calendar account, which your application can filter to be aware of just the calendar events created by the Meeting Scheduler.
The Kloudless API supports WebHooks to send notifications whenever activity occurs in a connected calendar account.
This includes both activity as a result of time slots booked / updated via the Meeting Scheduler as well as general usage of the calendar account.
Check the Kloudless API Docs for information on how to configure webhooks for your application.
The webhook's body URL-encodes data that your application can parse. Be aware that not all attributes will be present on each notification. Here is an example:
account=123456&event_category=calendar&event_type=add&event_subtype=meeting_scheduler_slot_booked&calendar_id=calendar_id&calendar_event_id=calendar_event_id&meeting_window_id=abcxyz12345
Most notifications only include the account ID or limited information in the payload, but notifications from the Meeting Scheduler have the following attributes that your application should check for:
Action | event_category | event_type | event_subtype |
---|---|---|---|
A slot is booked | calendar | add | meeting_scheduler_slot_booked |
A scheduled event is updated or rescheduled | calendar | update | meeting_scheduler_slot_updated |
A scheduled event is deleted | calendar | delete | meeting_scheduler_slot_deleted |
If your application sees a notification with the data above, check the remaining included data for which calendar event was associated:
meeting_window_id
: ID of the Meeting Window used to schedule the calendar event.account
: ID of the connected calendar account.calendar_id
: ID of the calendar that the event is scheduled in.calendar_event_id
ID of the scheduled calendar event.
You can then either retrieve the associated Meeting Window object, or more commonly, retrieve the scheduled calendar event via the Kloudless API.
For example, retrieving the metadata of a calendar event that was scheduled involves a GET request to the following URL based on the attributes above:
https://api.kloudless.com/v1/accounts/{account}/cal/calendars/{calendar_id}/events/{calendar_event_id}
This is currently only supported for Google Calendar or Outlook Calendar accounts connected to a Meeting Window.
The Kloudless Calendar API offers an Activity Stream that tracks new, updated, or deleted events on connected calendar accounts. Since this includes calendar events created by the Meeting Scheduler, your application can monitor an organizer's calendar to determine when an end-user books a time slot on it.
When listing new activity, you can tell if an activity object corresponds to a calendar event created by the Meeting scheduler if the following cases are all true:
- The
type
isadd
- The
metadata.api
iscalendar
- The
metadata.type
isevent
metadata.custom_properties
is a list that contains an object where thekey
is"meeting_window_id"
.
If so, the value
attribute in the metadata.custom_properties
object
described above is the ID of the Meeting Window for which the calendar event was
booked.
Below is an example activity object representing a calendar event created
by the Meeting Scheduler. The Meeting Window ID in this example is
abcxyz12345
. Notice that the metadata
property contains the entire calendar
event, and the associated Meeting Window's ID is listed within
custom_properties
.
{
"id": "activity_id",
"account": 9999,
"action": "+",
"ip": null,
"modified": "2019-08-28T03:55:02Z",
"type": "add",
"user_id": null,
"metadata": {
"api": "calendar",
"type": "event",
"id": "calendar_event_id",
"account_id": "9999",
"calendar_id": "calendar_id",
"recurrence_type": "solo",
"creator": {
"id": null,
"name": null,
"email": "creator@gmail.com"
},
"organizer": {
"id": null,
"name": "organizer",
"email": "organizer@group.calendar.google.com"
},
"attendees": [
{
"id": null,
"name": "attendee",
"email": "attendee@kloudless.com",
"status": "pending",
"required": true,
"resource": false
}
],
"created": "2019-08-28T03:55:02Z",
"modified": "2019-08-28T03:55:02Z",
"all_day": false,
"start": "2019-09-15T22:30:00-07:00",
"start_time_zone": "America/Los_Angeles",
"end": "2019-09-15T23:30:00-07:00",
"end_time_zone": "America/Los_Angeles",
"name": "event_name",
"description": "event_description",
"location": "event_location",
"status": "confirmed",
"visibility": null,
"attachments": [],
"custom_properties": [
{
"key": "meeting_window_id",
"value": "abcxyz12345"
}
],
"use_default_reminder": true,
"reminders": [],
"reminder": null
}
}
- Launch options have been redesigned to provide flexibility with configuration. Please refer to the following table to migrate your existing configuration.
Purpose | v1.1 and below | v1.2 and above |
---|---|---|
Pass the connected account's token for the Setup View | accountToken | setup.accountToken |
URL template for users to schedule the event (*1) | eventUrlFormat | setup.scheduleUrl |
Launch the Schedule View | eventId | schedule.meetingWindowId |
- *1:
EVENT_ID
in the URL template has to be changed toMEETING_WINDOW_ID
in order to generate the schedule link properly.
appId
is now required for both the Setup and Schedule View.
Clone this repository
# install dependencies
npm install
# By setting KLOUDLESS_APP_ID, the test page will populate `appId` automatically
export KLOUDLESS_APP_ID=<your_app_id>
# Set this if you'd like to specify a non-default Kloudless API server URL
export BASE_URL=<your_kloudless_api_server_url>
# serve with hot reload at localhost:8080
npm run dev
# or
npm start
Then, run the Vue debug server to debug with the widget:
npm run vue-devtools
If you encounter issues while inspecting components, try clicking the refresh button on the top right.
When launching the dev server, the setup.scheduleUrl
will be
http://localhost:8080/meetingWindowId=MEETING_WINDOW_ID
by default.
You can use this URL to test the Schedule View locally.
# install dependencies
npm install
# build for production with minification.
# the result will be in /dist.
npm run build
The build contains a scheduler
folder which renders the actual HTML and
functionalities of the widget; by default, this is hosted by Kloudless. If
you would like to host it yourself, you can set SCHEDULER_PATH
under build
options to specify the scheduler hosting URL, or use
Kloudless.scheduler.setOptions
in runtime.
You will need to add your website domain to your Kloudless app's list of
Trusted Domains
on the
App Detail Page.
This allows the hosted scheduler to receive access tokens to the Kloudless API.
You can use environment variables to configure the build, for example:
# Set this if you'd like to specify a non-default Kloudless API server URL
BASE_URL=<your_kloudless_api_server_url> npm run build
Variable Name | Purpose | Default |
---|---|---|
BASE_URL | URL to Kloudless API Server | https://api.kloudless.com |
SCHEDULER_PATH | URL for the scheduler page | https://static-cdn.kloudless.com/p/platform/scheduler/index.html |
SCHEDULE_URL | Default schedule URL | https://kloudl.es/m/MEETING_WINDOW_ID |
RESCHEDULE_URL | Default re-schedule URL | https://kloudl.es/m/s/SCHEDULED_EVENT_ID |
npm run dist-test
Open http://localhost:8080/test/dist to test the build
Feel free to contact us at support@kloudless.com with any feedback or questions.