We are building a brand new plugin (currently in tech preview). Want to try it out? Click here.
The Skedify plugin works by executing javascript on the page. Upon initialization, it
instantiates a SkedifyPluginInstance inside every block-level element that has a
skedify-plugin
class set on it. To communicate with the Skedify API, every
SkedifyPluginInstance needs a client-id or an access token. These can be set by
configuring a html attribute: skedify:oauth.client
or
skedify:oauth.token
.
<head>
...
<link type="text/css" rel="stylesheet" href="https://plugin.skedify.io/senso/SkedifyPlugin.css" />
</head>
<div
class="skedify-plugin"
id="skedify-plugin-wrapper"
skedify:language="nl-BE"
skedify:customer.timezone="Europe/Brussels"
skedify:oauth.client="MS4yGE5riR3jnvYBRHjebJMJSO99BxDaO04BnpNA"
>
<script src="https://plugin.skedify.io/senso/skedify-plugin.js" defer></script>
</div>
window.Skedify.Plugin
has been resolved, it's possible to manually
re-initiate the plugin by calling:
const pluginElement = document.querySelector("#skedify-plugin-wrapper");
window.Skedify.Plugin(pluginElement);
The plugin can be configured to behave in a certain way or have some values prefilled. You can do this by adding extra attributes.
default
(enabled)disabled
schedule
, reschedule
, invite
, edit
,
cancel
. This parameter is mostly used by redirects from external sources
(e.g. e-mails) and should usually not be provided manually.
office
, phone
, video
, on_location
.
disable_initial_scroll_on_schedule
, default
.
enable_timezone_selection
, disable_timezone_selection
. The
default is disable_timezone_selection
.
enable_timezone_selection
, disable_timezone_selection
. The
default is disable_timezone_selection
.
geolocation
& formatted_address
are required.
lat;lng
S
: Subject. The step that allows the customer to pick a subject.
O
: Office. The step that allows the customer to pick an office.
E
: Employee. The step that allows the customer to pick an employee.
T
: Timetable. The step that allows the customer to suggest one or more
time slots for their appointment.
Q
: Questions. The step that allows the customer to answer any addition
questions specific to the chosen subject.
C
: Customer. The step that allows the customer to provide his/her
contact information.
'
: [start]. Indicate the first step that should be shown is the first
one following this character.
#
: [locked]. Indicate that the step is locked and can not be edited.
This means that a value must be provided.
T
, Q
,
C
.
S
is not present, it is mandatory that an external mechanism will
provide the appointment.subject_id
or
external_subject_id
configuration option instead.
O
is not present, it is mandatory that an external mechanism will
provide the appointment.office_id
or
external_office_id
configuration option instead.
S
or O
are present, they can never occur at a position
after T
.
S
is present, it can never occur at a position after Q
.
'
) is present, it can never occur at a
position after T
. If the start character is ommitted, it will be
assumed that the first character also specifies the first step to be shown.
'SOTQC
will be assumed. This will be the case if no value was provided or
if the provided value fails these constraints.
<div
class="skedify-plugin"
id="skedify-plugin-wrapper"
skedify:appointment.office_id="<office-id here>"
skedify:appointment.subject_id="<subject-id here>"
skedify:flow="S'TQC"
skedify:language="nl-BE"
skedify:customer.timezone="Europe/Brussels"
skedify:oauth.client="MS4yGE5riR3jnvYBRHjebJMJSO99BxDaO04BnpNA"
>
<script src="https://plugin.skedify.io/senso/skedify-plugin.js" defer></script>
<!-- Insert a fallback for when the plugin fails here, for example: -->
<!--
<p class="enterprise-fallback">
U kunt momenteel geen afspraak maken via deze module. Probeer binnen enkele minuten opnieuw of neem contact op via
<a href="mailto:contact@example.com">e-mail</a> of telefonisch op
<a href="tel:0032800000000">0800 00 00 00</a>.
</p>
-->
<!-- <a href="skedify.me" style="color:transparent;font-size:1pt;letter-spacing:-3.5pt;cursor:default;">
scheduling software</a> -->
</div>
oauth.resource_code
(see above).
appointment.subject_id
(see above).
external_subject_id
(see above).
appointment.listing_id
(see above).
appointment.external_listing_id
(see above).
lead_segment_code
(see above).
appointment.office_id
(see above).
external_office_id
(see above).
hints.intent
(see above).
hints.contacts
(see above).
hints.external_employee_ids
(see above).
search.country
(see above).
flow
(see above).
meeting_types
(see above).
application.scroll
(see above).
application.timezone_selection
(see above).
language
(see above).
session
(see above).
session.status
(see above).
session.id
(see above).
session.source_tags
(see above).
customer
(see above).
customer.timezone
(see above).
customer.first_name
(see above).
customer.last_name
(see above).
customer.email
(see above).
customer.phone_number
(see above).
customer.customer_number
(see above).
location
(see above).
location.formatted_address
(see above).
location.geolocation
(see above).
location.city
(see above).
location.country
(see above).
location.postal_code
(see above).
location.state
(see above).
location.street_1
(see above).
To prevent naming collisions with parameters of the containing website, Skedify chose to
encode these parameters. To provide parameters, insert
'skedify' + encoded_params
into the hash part of the URL, making sure the
first character following that is not an alpha-numeric character. An implementation for
encoding the parameters is
made available by Skedify
and as a package on
NPM.
/* eslint-disable */
const skedify_params_to_encode = {
sub: "subject_id_1",
flo: "'SOTQC",
};
const encoded_params = Skedify.encodeURIParameters(skedify_params_to_encode);
// skedify_params_to_encode ~= Skedify.decodeURIParameters(encoded_params);
document.location.replace(
"http://example.com/page-containing-plugin" + "#skedify" + encoded_params
);
// URL should now be 'http://example.com/page-containing-plugin#skedifyeyJzdWIiOiJzdWJqZWN0X2lkXzEiLCJmbG8iOiInU0xUUUMifQg'
The Skedify plugin also offers a Javascript API. Upon initialisation, it registers one
global object in the window scope:
Skedify.Plugin
. This object implements the following SkedifyPlugin interface.
[interface] Skedify.Plugin: {
/**
* EVENT TYPES
*/
[constant] EVENT_INIT, // This event is triggered when the Skedify.Plugin global is registered.
[constant] EVENT_CREATION, // This event is triggered when an instance of Skedify.Plugin was created.
[constant] EVENT_MISCONFIGURED, // This event is triggered when an URL- or DOM-style initialisation was not properly configured.
[constant] EVENT_ERROR, // This event is triggered when a fatal error occurred within a plugin instance.
[constant] EVENT_APPOINTMENT_CREATED, // This event is triggered when an appointment request was made.
[constant] EVENT_APPOINTMENT_EDITED, // This event is triggered when an appointment was edited.
[constant] EVENT_APPOINTMENT_CANCELLED, // This event is triggered when an appointment was cancelled.
/**
* EVENT SUBTYPES
*/
// Misconfigured sub types
[constant] MISCONFIGURED_SUBJECT_ID, // Subtype of `EVENT_MISCONFIGURED`. Set if the cause of a misconfiguration was an invalid subject_id.
[constant] MISCONFIGURED_OFFICE_ID, // Subtype of `EVENT_MISCONFIGURED`. Set if the cause of a misconfiguration was an invalid office_id.
[constant] MISCONFIGURED_RESOURCE_CODE, // Subtype of `EVENT_MISCONFIGURED`. Set if the cause of a misconfiguration was an invalid resource_code.
[constant] MISCONFIGURED_CLIENT_ID, // Subtype of `EVENT_MISCONFIGURED`. Set if the cause of a misconfiguration was an invalid client_id.
[constant] MISCONFIGURED_INTENT_WITHOUT_RESOURCE_CODE, // Subtype of `EVENT_MISCONFIGURED`. Set if a requested intent is only allowed for appointment contexts, but no resource_code was provided.
// Error sub types
[constant] ERROR_API_DOWN, // Subtype of `EVENT_ERROR`. Set if the API unexpectedly cannot respond to a request that is necessary for the plugin to function correctly.
/**
* Intents
*/
[constant] INTENT_SCHEDULE, // Can be provided to hint.intent to indicate intent to schedule an appointment
[constant] INTENT_RESCHEDULE, // Can be provided to hint.intent to indicate intent to reschedule an appointment
[constant] INTENT_INVITE, // Can be provided to hint.intent to indicate intent to invite a customer to schedule an appointment
[constant] INTENT_EDIT, // Can be provided to hint.intent to indicate intent to edit an appointment
[constant] INTENT_CANCEL, // Can be provided to hint.intent to indicate intent to cancel an appointment
getInstance(index /* 0-based */: int): SkedifyPluginInstance, // Get one of the instances
count: int, // The current amount of instances
version: string, // Semver version number
[alias] dispose, // Alias to getInstance(0).dispose
[alias] addEventListener, // Alias to getInstance(0).addEventListener
[alias] customer, // Alias to getInstance(0).customer
[alias] appointment, // Alias to getInstance(0).appointment
[alias] hints // Alias to getInstance(0).hints
}
Skedify.Plugin(DOMElement, { ...options }) // Factory function to create a plugin instance.
// DOMElement: Is the element in which the plugin will be rendered
// (Can contain any of the supported option attributes).
// Options: Can be any of the supported options.
// E.g.:
// Skedify.Plugin(document.createElement('div'), {
// oauth: {
// client: 'your-id-here',
// },
// });
[interface] SkedifyPluginInstance: {
dispose(), // Destroy the instance
addEventListener( // Add an event listener
/* [optional] */
Skedify.Plugin.EVENT_*,
/* [Callback] */
function(event) {
}
),
[read-only] intention : string, // The current intention
customer: { // Provide known information about the customer
[read-write] company : string,
[read-write] customer_number : string,
[read-write] email : string,
[read-write] external_id : string,
[read-write] first_name : string,
[read-write] is_existing : boolean,
[read-write] language : string,
[read-write] last_name : string,
[read-write] phone_number : string,
[read-write] timezone : string,
},
appointment: { // Reads known information about the appointment
[read-only] id: string,
[read-only] location: { // Reads information about the location of the appointment
[read-only] id: string,
},
[read-only] meeting_type: string, // Reads information about the meeting type of the appointment
subject: { // Reads information about the subject of the appointment
[read-only] id: string,
[read-only] category_id: string,
},
meta: { // Store meta-information about the appointment (for your own use)
// Keys and values must be JSON-serializeable
get(key, defaultValue), // Retrieve the value associated with the key, or retrieve the defaultValue if no value was present
set(key, value), // Associate the value with the key
remove(key), // Remove a key and its associated value
}
},
}
Other javascript on the page can be informed by the availability of the Skedify.Plugin
global by listening on document for a
SkedifyPluginEvent
event using the native event handler functionality.
Similarly, you can detect a plugin instance being created and hook specific event
callbacks on that.
(function () {
function initBindingWithSkedify(instance) {
// You can listen for specific events
instance.addEventListener(window.Skedify.Plugin.EVENT_APPOINTMENT_CREATED, function (event) {
console.log("An appointment (request) was made.");
});
// You can listen for all events
instance.addEventListener(function (event) {
// any event for the instance will be caught
// determine the type based on `event.detail.type`
if (event.detail.type === window.Skedify.Plugin.EVENT_MISCONFIGURED) {
console.log("The configuration provided to the instance was invalid");
if (event.detail.subtype === window.Skedify.Plugin.MISCONFIGURED_SUBJECT_ID) {
console.log(" the provided subject_id was invalid");
} else if (event.detail.subtype === window.Skedify.Plugin.MISCONFIGURED_OFFICE_ID) {
console.log(" the provided office_id was invalid");
} else if (event.detail.subtype === window.Skedify.Plugin.MISCONFIGURED_RESOURCE_CODE) {
console.log(" the provided resource_code was invalid");
}
} else if (event.detail.type === window.Skedify.Plugin.EVENT_ERROR) {
console.log("The Skedify API is down, or an unexpected runtime exception occurred");
}
});
}
if (window.Skedify && window.Skedify.Plugin) {
// If Skedify.Plugin is already available, use that instance.
initBindingWithSkedify(window.Skedify.Plugin.getInstance(0));
} else {
// If the Skedify.Plugin is loaded async, we have to wait for an instance.
document.addEventListener("SkedifyPluginEvent", function (event) {
// every event will have a `event.detail.type` attribute, so different events can be distinguished.
if (event.detail.type === window.Skedify.Plugin.EVENT_CREATION) {
initBindingWithSkedify(event.detail.instance);
}
});
}
})();