feat(GRO-1794): add booking funnel analytics events
- New analytics utility (src/lib/analytics.ts) with ANALYTICS_EVENTS constants and fireAnalyticsEvent() – thin wrapper over window.dispatchEvent, no-op safe Built for Plausible/GTM integration later. - Public booking wizard (Book.tsx): fires step-transition events at each step (service → time → contact → submit) plus booking_confirmed on the dedicated confirmation page. - Portal BookingFlow (Appointments.tsx): fires equivalent events for the portal booking flow. booking_confirmed fires via useEffect when the inline success state is shown. - BookingErrorPage: fires booking_error on mount (no PII in payload). Events include step name and flow type (public/portal) but contain no PII: no names, emails, phone numbers, or pet names in any payload. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
// Analytics event names — single source of truth
|
||||
export const ANALYTICS_EVENTS = {
|
||||
BOOKING_STEP_SERVICE: "booking_step_service",
|
||||
BOOKING_STEP_TIME: "booking_step_time",
|
||||
BOOKING_STEP_CONTACT: "booking_step_contact",
|
||||
BOOKING_STEP_SUBMIT: "booking_step_submit",
|
||||
BOOKING_CONFIRMED: "booking_confirmed",
|
||||
BOOKING_ERROR: "booking_error",
|
||||
} as const;
|
||||
|
||||
export type AnalyticsEventName = (typeof ANALYTICS_EVENTS)[keyof typeof ANALYTICS_EVENTS];
|
||||
|
||||
export type AnalyticsPayload = {
|
||||
step?: string;
|
||||
flow?: "public" | "portal";
|
||||
[key: string]: string | undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fires a lightweight analytics event via window.dispatchEvent.
|
||||
* No-op safe: failures are swallowed so analytics never breaks the booking flow.
|
||||
* Designed for later Plausible/GTM integration.
|
||||
*/
|
||||
export function fireAnalyticsEvent(
|
||||
eventName: AnalyticsEventName,
|
||||
payload: AnalyticsPayload = {}
|
||||
): void {
|
||||
try {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent(eventName, {
|
||||
detail: {
|
||||
...payload,
|
||||
timestamp: new Date().toISOString(),
|
||||
},
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
// no-op: analytics must never break the booking flow
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user