Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | 2x 2x 2x 2x 6x 6x 3x 3x 1x 8x 8x 8x 8x 8x 8x 6x 2x | /**
* Privacy-safe booking analytics. Emits English, PII-free events that cross
* Shadow DOM via document + composed CustomEvent. If etracker is present on
* the host page, also forwards object/category/action. Never throws.
*/
export const APPOINTMENT_TRACK_EVENT = "zms-appointment-track";
export const APPOINTMENT_TRACK_CATEGORY = "appointment";
export type AppointmentTrackObject =
| "appointment"
| "appointment_detail"
| "appointment_slider"
| "appointment_overview"
| "service_finder"
| "service_combination"
| "appointment_selection"
| "contact"
| "summary"
| "reserved"
| "updated"
| "preconfirmed"
| "confirmed"
| "cancelled"
| "rebooking"
| "login";
export type AppointmentTrackAction =
"view" | "click" | "success" | "started" | "abandoned";
export type AppointmentTrackFlow = "new" | "rebooking";
export type AppointmentTrackSlotUi = "list" | "calendar";
export type AppointmentTrackWidget =
| "appointment"
| "appointment_detail"
| "appointment_slider"
| "appointment_overview";
export type AppointmentTrackPayload = {
object: AppointmentTrackObject;
action: AppointmentTrackAction;
flow?: AppointmentTrackFlow;
slot_ui?: AppointmentTrackSlotUi;
widget?: AppointmentTrackWidget;
};
const BOOKING_SCREENS: Record<number, AppointmentTrackObject> = {
1: "appointment_selection",
2: "contact",
3: "summary",
};
declare global {
interface Window {
_etracker?: {
sendEvent?: (event: unknown) => void;
};
et_UserDefinedEvent?: new (
objectName: string,
category: string,
action?: string,
type?: string
) => unknown;
}
}
export function bookingFlow(isRebooking: boolean): AppointmentTrackFlow {
return isRebooking ? "rebooking" : "new";
}
export function trackAppointmentScreenFromView(view: number): void {
const object = BOOKING_SCREENS[view];
if (!object) {
return;
}
trackAppointmentEvent({ object, action: "view" });
}
export function trackWidgetView(widget: AppointmentTrackWidget): void {
trackAppointmentEvent({ object: widget, action: "view" });
}
export function trackAppointmentEvent(payload: AppointmentTrackPayload): void {
try {
document.dispatchEvent(
new CustomEvent(APPOINTMENT_TRACK_EVENT, {
detail: payload,
bubbles: true,
composed: true,
})
);
sendToEtracker(payload);
} catch {
// Tracking must never break the booking flow.
}
}
function sendToEtracker(payload: AppointmentTrackPayload): void {
const sendEvent = window._etracker?.sendEvent;
const UserDefinedEvent = window.et_UserDefinedEvent;
if (!sendEvent || !UserDefinedEvent) {
return;
}
sendEvent(
new UserDefinedEvent(
payload.object,
APPOINTMENT_TRACK_CATEGORY,
payload.action
)
);
}
|