import 'rollup-plugin-inject-process-env'; /** * Service for tracking form widget interaction events * * API Endpoint: POST /cms/widget/events * @see https://github.com/XappMedia/chat-widget/blob/master/docs/widget-events-api.md */ import { StentorApi } from "../api/stentor-api"; import { FormOpenEventData, EngagedEventData, NextStepEventData, PreviousStepEventData, StepChangeEventData, SubmitEventData, SubmitFailureEventData, CloseEventData, PartialDataEventData, HandoffRenderedEventData, HandoffNoRenderEventData, HandoffScheduledEventData, HandoffErrorEventData } from "../types/events"; /** * Service for tracking form widget interaction events. * This service provides methods to track user interactions with the form widget * without blocking the user experience (all tracking is async and errors are logged). * * Events are sent to POST /cms/widget/events and stored in OpenSearch as: * - form_open -> eventName: "WIDGET_FORM_OPEN" * - engaged -> eventName: "WIDGET_FORM_ENGAGED" * - next_step -> eventName: "WIDGET_FORM_STEP" * - previous_step -> eventName: "WIDGET_FORM_PREV_STEP" * - step_change -> eventName: "WIDGET_FORM_STEP_CHANGE" * - submit -> eventName: "WIDGET_FORM_SUBMIT" * - close -> eventName: "WIDGET_FORM_CLOSE" * - partial_data -> eventName: "WIDGET_FORM_ABANDON" * - handoff_rendered -> eventName: "WIDGET_FORM_HANDOFF_RENDERED" * - handoff_no_render -> eventName: "WIDGET_FORM_HANDOFF_NO_RENDER" * - handoff_scheduled -> eventName: "WIDGET_FORM_HANDOFF_SCHEDULED" * - handoff_error -> eventName: "WIDGET_FORM_HANDOFF_ERROR" */ export declare class EventTrackingService { private api; private sessionId; private formId; constructor(api: StentorApi, sessionId: string, formId: string); /** * Track a form_open event when the form widget is first displayed * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_OPEN" */ trackFormOpen(data: FormOpenEventData): Promise; /** * Track an engaged event the first time a user takes a genuine action on * the form (manual open, chip click, or first step transition). * Additive to form_open - does not replace it. Callers are responsible * for only calling this once per session. * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_ENGAGED" */ trackEngaged(data: EngagedEventData): Promise; /** * Track a next_step event when user navigates to the next form step * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_STEP" */ trackNextStep(data: NextStepEventData): Promise; /** * Track a previous_step event when user navigates back to a previous step * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_PREV_STEP" */ trackPreviousStep(data: PreviousStepEventData): Promise; /** * Track a step_change event for any step navigation (forward or backward) * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_STEP_CHANGE" */ trackStepChange(data: StepChangeEventData): Promise; /** * Track a submit event when user submits the final form * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_SUBMIT" */ trackSubmit(data: SubmitEventData): Promise; /** * Track a submit that failed to reach the server, after retries. * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_SUBMIT_FAILURE" * * trackSubmit above fires on this endpoint *before* the FORM_SUBMIT dispatch that * actually creates the lead, so a submit event alone never proved a lead existed. * This is its counter-signal: submit events minus submit_failure events is the * number of submissions that were genuinely dispatched (issue #1373). */ trackSubmitFailure(data: SubmitFailureEventData): Promise; /** * Track a close event when user explicitly closes the form widget * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_CLOSE" */ trackClose(data: CloseEventData): Promise; /** * Track a partial_data event when user abandons form (tab close or timeout) * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_ABANDON" * * @param data - Event data including abandonmentReason ("close_tab" | "timeout") */ trackPartialData(data: PartialDataEventData): Promise; /** * Track a handoff_rendered event when a booking-widget handoff step's anchor * gains content within its render timeout. * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_HANDOFF_RENDERED" */ trackHandoffRendered(data: HandoffRenderedEventData): Promise; /** * Track a handoff_no_render event when a booking-widget handoff step's render * timeout elapses with an empty anchor. * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_HANDOFF_NO_RENDER" */ trackHandoffNoRender(data: HandoffNoRenderEventData): Promise; /** * Track a handoff_scheduled event when the partner script invokes the * configured success callback. This is how the booking outcome reaches * stentor_events -- joinable on sessionId with the lead. * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_HANDOFF_SCHEDULED" */ trackHandoffScheduled(data: HandoffScheduledEventData): Promise; /** * Track a handoff_error event when a booking-widget handoff step's partner * script fails to load, or its scriptSrc is rejected. * Stored as: eventType: "AnalyticsEvent", eventName: "WIDGET_FORM_HANDOFF_ERROR" */ trackHandoffError(data: HandoffErrorEventData): Promise; /** * Track a partial_data event using beacon/keepalive for page unload scenarios. * Use this when the page is being unloaded and you need reliable delivery. * * @param data - Event data including abandonmentReason ("close_tab" | "timeout") * @returns true if the beacon was queued, false otherwise */ trackPartialDataBeacon(data: PartialDataEventData): boolean; /** * Build event metadata from current context. * * Each optional enrichment (userId, currentUrl, UTM/click-id params) is isolated in its * own try/catch. localStorage access in particular can throw synchronously - not just * return null - in Safari ITP, a sandboxed iframe without allow-same-origin, or under an * enterprise storage policy. Without isolation, one such throw used to take down metadata * building entirely, silently dropping the event (including userAgent/currentUrl, which * don't depend on storage) via the try/catch in trackFormOpen et al. See issue #1504. */ private buildMetadata; /** * Get user ID from localStorage */ private getUserId; /** * Get tracking parameters from localStorage */ private getTrackingParameters; /** * Send event to backend API */ private sendEvent; }