feat: add booker lifecycle SDK events for embed tracking (#25569)
* feat: add embed prerendering support and enhance event handling - Introduced `useIsEmbedPrerendering` hook to determine if the embed is in prerender mode. - Updated `useAvailabilityEvents` to prevent firing events during prerendering. - Added `bookerLoadedEvent` and `availabilityRefreshed` types to `EventDataMap`. - Implemented `useFirebookerLoadedEvent` to manage firing the booker loaded event conditionally. - Refactored event firing logic in `useSchedule` and `BookerWebWrapper` components to utilize new hooks. * feat: add embed prerendering support and enhance event handling - Introduced `useIsEmbedPrerendering` hook to determine if the embed is in prerender mode. - Updated `useAvailabilityEvents` to prevent firing events during prerendering. - Added `bookerLoadedEvent` and `availabilityRefreshed` types to `EventDataMap`. - Implemented `useFirebookerLoadedEvent` to manage firing the booker loaded event conditionally. - Refactored event firing logic in `useSchedule` and `BookerWebWrapper` components to utilize new hooks. * feat: enhance embed event handling and introduce link reopening detection - Added `useEmbedReopened` hook to track when the embed is reopened. - Updated `BookerWebWrapper` to reset event firing state upon embed reopening. - Refactored event firing logic to use `bookerViewed` instead of `bookerLoadedEvent`. - Introduced scheduling for event firing in `useSchedule` to ensure correct order of events during prerendering. * feat: add lifecycle diagrams for inline and modal embeds - Introduced `inline-embed-lifecycle.mermaid` and `modal-embed-lifecycle.mermaid` files to visualize the lifecycle events and states of inline and modal embeds. - Updated `LIFECYCLE.md` to reference the new diagrams and provide a clearer explanation of the embed lifecycle processes. - Added `modal-prerendering-flow.mermaid` to illustrate the prerendering flow for modal embeds. - Enhanced the routing playground with new features and improved event handling for availability and booking events. * refactor: update event handling for booker lifecycle events - Replaced `availabilityLoaded` event with `bookerReady` to better reflect the state when the booker view is fully loaded and ready for interaction. - Updated related documentation and diagrams to reflect changes in event triggers and descriptions. - Adjusted internal state management to track `viewId` instead of `reopenCount` for distinguishing between initial views and reopens. - Added tests for new event handling logic to ensure correct firing of `bookerViewed`, `bookerReopened`, and `bookerReady` events. * refactor: enhance embed event handling and state management - Updated event handling for booker lifecycle events, replacing `resetViewVariables` with `resetPageData` to manage page-specific state. - Introduced new utility functions for managing event firing states and reload initiation. - Refactored `fireBookerViewedEvent` and `fireBookerReadyEvent` to utilize the new state management functions. - Added comprehensive tests for the updated event handling logic and state resets to ensure correct functionality across various scenarios. * refactor: update embed iframe configuration and utility functions - Reduced `slotsStaleTimeMs` from 30 seconds to 10 seconds and `iframeForceReloadThresholdMs` from 100 seconds to 30 seconds for improved responsiveness. - Refactored utility functions to use `isBrowser` for client-side checks instead of `isClientSide`. - Removed unused `isPrerendering` function and updated related documentation for clarity. - Enhanced event handling by exporting `useBookerEmbedEvents` from the appropriate module for better accessibility. * refactor: update embed iframe configuration and utility functions - Reduced `slotsStaleTimeMs` from 30 seconds to 10 seconds and `iframeForceReloadThresholdMs` from 100 seconds to 30 seconds for improved responsiveness. - Refactored utility functions to use `isBrowser` for client-side checks instead of `isClientSide`. - Removed unused `isPrerendering` function and updated related documentation for clarity. - Enhanced event handling by exporting `useBookerEmbedEvents` from the appropriate module for better accessibility. * fix cubic feedback
This commit is contained in:
@@ -3,13 +3,16 @@
|
||||
import { useEffect, useRef, useState, useCallback } from "react";
|
||||
import { mapOldToNewCssVars } from "./ui/cssVarsMap";
|
||||
import type { Message } from "./embed";
|
||||
import { embedStore, EMBED_IFRAME_STATE } from "./embed-iframe/lib/embedStore";
|
||||
import { embedStore, EMBED_IFRAME_STATE, resetPageData, setReloadInitiated, incrementView } from "./embed-iframe/lib/embedStore";
|
||||
import {
|
||||
runAsap,
|
||||
isBookerReady,
|
||||
isLinkReady,
|
||||
recordResponseIfQueued,
|
||||
keepParentInformedAboutDimensionChanges,
|
||||
isPrerendering,
|
||||
isBrowser,
|
||||
log,
|
||||
} from "./embed-iframe/lib/utils";
|
||||
import { sdkActionManager } from "./sdk-event";
|
||||
import type {
|
||||
@@ -24,6 +27,7 @@ import type {
|
||||
setNonStylesConfig,
|
||||
} from "./types";
|
||||
import { useCompatSearchParams } from "./useCompatSearchParams";
|
||||
export { useBookerEmbedEvents } from "./embed-iframe/react-hooks";
|
||||
|
||||
// We don't import it from Booker/types because the types from this module are published to npm and we can't import packages that aren't published
|
||||
type BookerState = "loading" | "selecting_date" | "selecting_time" | "booking";
|
||||
@@ -34,10 +38,11 @@ const eventsAllowedInPrerendering = [
|
||||
"__iframeReady",
|
||||
// so that iframe height is adjusted according to the content, and iframe is ready to be shown when needed
|
||||
"__dimensionChanged",
|
||||
|
||||
// When this event is fired, the iframe is still in prerender state but is going to be moved out of prerender state
|
||||
"__connectInitiated",
|
||||
|
||||
"linkPrerendered",
|
||||
|
||||
// For other events, we should consider introducing prerender specific events and not reuse existing events
|
||||
];
|
||||
|
||||
@@ -54,7 +59,6 @@ declare global {
|
||||
}
|
||||
|
||||
let isSafariBrowser = false;
|
||||
const isBrowser = typeof window !== "undefined";
|
||||
|
||||
if (isBrowser) {
|
||||
window.CalEmbed = window?.CalEmbed || {};
|
||||
@@ -66,24 +70,6 @@ if (isBrowser) {
|
||||
}
|
||||
}
|
||||
|
||||
function log(...args: unknown[]) {
|
||||
if (isBrowser) {
|
||||
const namespace = getNamespace();
|
||||
|
||||
const searchParams = new URL(document.URL).searchParams;
|
||||
const logQueue = (window.CalEmbed.__logQueue = window.CalEmbed.__logQueue || []);
|
||||
args.push({
|
||||
ns: namespace,
|
||||
url: document.URL,
|
||||
});
|
||||
args.unshift("CAL:");
|
||||
logQueue.push(args);
|
||||
if (searchParams.get("debug")) {
|
||||
console.log("Child:", ...args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const setEmbedStyles = (stylesConfig: EmbedStyles) => {
|
||||
embedStore.styles = stylesConfig;
|
||||
for (const [, setEmbedStyle] of Object.entries(embedStore.reactStylesStateSetters)) {
|
||||
@@ -431,7 +417,11 @@ export const methods = {
|
||||
makeBodyVisible();
|
||||
log("renderState is 'completed'");
|
||||
embedStore.renderState = "completed";
|
||||
sdkActionManager?.fire("linkReady", {});
|
||||
if (isPrerendering()) {
|
||||
sdkActionManager?.fire("linkPrerendered", {});
|
||||
} else {
|
||||
sdkActionManager?.fire("linkReady", {});
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -496,6 +486,10 @@ export const methods = {
|
||||
toRemoveParams,
|
||||
});
|
||||
},
|
||||
__reloadInitiated: function __reloadInitiated(_unused: unknown) {
|
||||
log("Method: __reloadInitiated called");
|
||||
setReloadInitiated(true);
|
||||
},
|
||||
};
|
||||
|
||||
export type InterfaceWithParent = {
|
||||
@@ -568,6 +562,15 @@ function main() {
|
||||
}
|
||||
});
|
||||
|
||||
sdkActionManager?.on("linkReady", () => {
|
||||
// Even though linkReady isn't fired in prerendering phase, this is a safe guard for future
|
||||
if (isPrerendering()) {
|
||||
return;
|
||||
}
|
||||
resetPageData();
|
||||
incrementView();
|
||||
});
|
||||
|
||||
sdkActionManager?.on("*", (e) => {
|
||||
if (isPrerendering() && !eventsAllowedInPrerendering.includes(e.detail.type)) {
|
||||
return;
|
||||
@@ -676,10 +679,6 @@ async function connectPreloadedEmbed({
|
||||
};
|
||||
}
|
||||
|
||||
const isPrerendering = () => {
|
||||
return new URL(document.URL).searchParams.get("prerender") === "true";
|
||||
};
|
||||
|
||||
export function getEmbedBookerState({
|
||||
bookerState,
|
||||
slotsQuery,
|
||||
|
||||
Reference in New Issue
Block a user