@meetelise/hc-scheduler-widget
v1.2.4
Published
Healthcare scheduler widget
Keywords
Readme
@meetelise/hc-scheduler-widget
An embeddable healthcare scheduling widget powered by EliseAI. Adds a modal-based appointment scheduler to any website with a single script tag.
Installation
Add the following script tag to your page:
<script type="module">
import HCScheduler from "https://cdn.eliseai.com/@meetelise/hc-scheduler-widget";
HCScheduler.start({
organizationId: "your-organization-id",
});
</script>This loads the widget, registers the eliseAi.hc global API, and makes the scheduling modal available on your page.
Quick Start
<button onclick="eliseAi.hc.openScheduling()">Schedule an Appointment</button>
<script type="module">
import HCScheduler from "https://cdn.eliseai.com/@meetelise/hc-scheduler-widget";
HCScheduler.start({
organizationId: "your-organization-id",
});
</script>That's it — clicking the button opens the scheduling modal.
Configuration
HCScheduler.start() accepts the following options:
| Option | Type | Required | Description |
| ---------------- | -------- | -------- | --------------------------------------------------------- |
| organizationId | string | Yes | Your EliseAI organization ID. |
| utm_source | string | No | Default UTM source applied to all scheduling sessions. |
| utm_medium | string | No | Default UTM medium applied to all scheduling sessions. |
| utm_campaign | string | No | Default UTM campaign applied to all scheduling sessions. |
| utm_term | string | No | Default UTM term applied to all scheduling sessions. |
| utm_content | string | No | Default UTM content applied to all scheduling sessions. |
Example with UTM defaults
<script type="module">
import HCScheduler from "https://cdn.eliseai.com/@meetelise/hc-scheduler-widget";
HCScheduler.start({
organizationId: "your-organization-id",
utm_source: "website",
utm_medium: "referral",
utm_campaign: "spring-promo",
utm_term: "obgyn",
utm_content: "homepage-hero",
});
</script>API
Once HCScheduler.start() has been called, the global eliseAi.hc object exposes:
eliseAi.hc.openScheduling(options?)
Opens the scheduling modal. Can be called with no arguments or with an options object:
| Option | Type | Description |
| ---------------- | -------- | ----------------------------------------------------------------------------------------- |
| organizationId | string | Overrides the widget-level organizationId for this session. |
| providerId | string | Opens scheduling pre-filtered to a specific provider. |
| locationId | string | Opens scheduling pre-filtered to a specific location. |
| utm_source | string | UTM source for this session. Overrides the widget-level utm_source if provided. |
| utm_medium | string | UTM medium for this session. Overrides the widget-level utm_medium if provided. |
| utm_campaign | string | UTM campaign for this session. Overrides the widget-level utm_campaign if provided. |
| utm_term | string | UTM term for this session. Overrides the widget-level utm_term if provided. |
| utm_content | string | UTM content for this session. Overrides the widget-level utm_content if provided. |
eliseAi.hc.close()
Closes the scheduling modal programmatically.
Provider & Location Pages
You can create provider-specific or location-specific booking buttons by passing providerId or locationId to openScheduling():
<!-- Provider-specific booking -->
<button onclick="eliseAi.hc.openScheduling({ providerId: '1' })">
Book with Dr. Stiles
</button>
<!-- Location-specific booking -->
<button onclick="eliseAi.hc.openScheduling({ locationId: '1' })">
Book at Irving
</button>
<!-- Both provider and location -->
<button
onclick="eliseAi.hc.openScheduling({ providerId: '22', locationId: '55' })"
>
Book with Dr. Riley at Irving
</button>UTM Tracking
UTM parameters are passed through to the scheduling URL so you can track where appointments originate.
How UTM values flow
- Widget-level defaults — Set any combination of
utm_source,utm_medium,utm_campaign,utm_term, andutm_contentinHCScheduler.start(). These apply to everyopenScheduling()call. - Per-call overrides — Pass any of those same parameters to
openScheduling(). These take priority over the widget-level defaults.
Parsing UTM from the page URL
A common pattern is to read UTM parameters from the current page's URL and pass them into the widget:
<script type="module">
import HCScheduler from "https://cdn.eliseai.com/@meetelise/hc-scheduler-widget";
const params = new URLSearchParams(window.location.search);
HCScheduler.start({
organizationId: "your-organization-id",
utm_source: params.get("utm_source") || undefined,
utm_medium: params.get("utm_medium") || undefined,
utm_campaign: params.get("utm_campaign") || undefined,
utm_term: params.get("utm_term") || undefined,
utm_content: params.get("utm_content") || undefined,
});
</script>With this setup, visiting https://yoursite.com?utm_source=google&utm_medium=cpc&utm_campaign=spring&utm_term=obgyn&utm_content=ad-123 will automatically pass those values through to the scheduler.
Important: Cookie-stored UTM values
If your site stores UTM parameters in cookies (e.g. capturing them on first visit and persisting them across pages), the widget will not read those cookies automatically. You are responsible for reading the cookie values yourself and passing them to the widget explicitly:
<script type="module">
import HCScheduler from "https://cdn.eliseai.com/@meetelise/hc-scheduler-widget";
// Example: read UTM values from your own cookies
function getCookie(name) {
const match = document.cookie.match(
new RegExp("(^| )" + name + "=([^;]+)"),
);
return match ? decodeURIComponent(match[2]) : undefined;
}
const params = new URLSearchParams(window.location.search);
HCScheduler.start({
organizationId: "your-organization-id",
utm_source: params.get("utm_source") || getCookie("utm_source"),
utm_medium: params.get("utm_medium") || getCookie("utm_medium"),
utm_campaign: params.get("utm_campaign") || getCookie("utm_campaign"),
utm_term: params.get("utm_term") || getCookie("utm_term"),
utm_content: params.get("utm_content") || getCookie("utm_content"),
});
</script>The widget operates inside an iframe on a different domain and cannot access your site's cookies. Always pass UTM values through the JavaScript API.
Google Tag Manager (GTM) Events
The scheduling iframe emits postMessage events to the parent window that can be forwarded to GTM's dataLayer. Add the following script to your page to listen for these events and push them into the data layer:
<script>
const GTM_POST_MESSAGE_TYPE = "elise-gtm-event";
function isGtmPostMessage(message) {
return (
message !== null &&
typeof message === "object" &&
message.type === GTM_POST_MESSAGE_TYPE &&
typeof message.event === "string" &&
message.properties !== null &&
typeof message.properties === "object"
);
}
function handleGtmMessage(e) {
if (!isGtmPostMessage(e.data)) return;
const { event, properties } = e.data;
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ event, ...properties });
}
window.addEventListener("message", handleGtmMessage);
</script>GTM Events
| Event | Payload | Description |
| ---------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| patientTypeSelected | { patientType: "newPatient" \| "existingPatient" } | User selects new or existing patient on the welcome page |
| phoneNumberSubmitted | — | New patient submits their phone number for verification |
| verificationCodeResent | — | User requests a new verification code to be sent |
| verificationCodeSubmitted | — | User submits their phone verification code |
| chatMessageSent | — | User sends a message in the AI triage chat |
| appointmentTypeSelected | — | Chat AI determines an appointment type and user clicks the schedule button |
| personalDetailsUpdated | — | New patient submits their personal details (name, DOB, address, etc.) |
| insuranceUpdated | — | Existing patient updates their insurance during the confirm details step |
| continuedWithSelfPay | — | Patient elects to continue with self-pay after insurance ineligibility |
| patientTransferred | { reason: string } | Patient is transferred out of the scheduling flow. Reasons include: "noAvailability", "workflow", or an EligibilityCheckReason value (e.g., "NOT_ACCEPTED", "UNKNOWN") |
| bookingSucceeded | — | Appointment(s) successfully booked |
| upcomingRescheduleInitiated| { appointmentIds: string[] } | Existing patient initiates rescheduling from the snapshot page |
| upcomingRescheduleSucceeded| — | Rescheduled appointment(s) successfully confirmed |
| upcomingAppointmentCanceled| { appointmentIds: string[] } | Existing patient cancels upcoming appointment(s) |
| upcomingAppointmentConfirmed| { appointmentIds: string[] } | Existing patient confirms upcoming appointment(s) |
Behavior
- Modal sizing — On screens wider than 600px, the modal appears centered with a max size of 900×900px. On smaller screens, it expands to fullscreen.
- Closing — Users can close the modal by pressing Escape or clicking the × button.
- Font — The widget automatically loads the Inter font if it isn't already present on the page.
