UNPKG

@empathyco/x-components

Version:
422 lines (419 loc) • 14.2 kB
import { DefaultSessionService } from '@empathyco/x-utils'; import { createOrigin } from '../../utils/origin.js'; import '../../utils/storage.js'; import { namespacedWireCommit, namespacedWireDispatch } from '../../wiring/namespaced-wires.factory.js'; import { namespacedDebounce } from '../../wiring/namespaced-wires.operators.js'; import { wireServiceWithoutPayload, wireService } from '../../wiring/wires.factory.js'; import { filter, filterTruthyPayload, mapWire } from '../../wiring/wires.operators.js'; import { createWiring } from '../../wiring/wiring.utils.js'; import { DefaultExternalTaggingService } from './service/external-tagging.service.js'; /** * `tagging` {@link XModuleName | XModule name}. * * @internal */ const moduleName = 'tagging'; /** * Debounce function for the module. */ const moduleDebounce = namespacedDebounce(moduleName); /** * WireCommit for {@link TaggingXModule}. * * @internal */ const wireCommit = namespacedWireCommit(moduleName); /** * WireDispatch for {@link TaggingXModule}. * * @internal */ const wireDispatch = namespacedWireDispatch(moduleName); /** * Wires without payload factory for {@link DefaultSessionService}. */ const wireSessionServiceWithoutPayload = wireServiceWithoutPayload(DefaultSessionService.instance); /** * Wires factory for {@link DefaultExternalTaggingService}. */ const wireExternalTaggingService = wireService(DefaultExternalTaggingService.instance); /** * Stores the given result on the local storage. * * @public */ const storeClickedResultWire = wireExternalTaggingService('storeResultClicked'); /** * Stores the result added to cart on the local storage. * * @public */ const storeAddToCartWire = wireExternalTaggingService('storeAddToCart'); /** * Moves the result information from the local storage to session storage. * * @public */ const moveClickedResultToSessionWire = mapWire(wireExternalTaggingService('moveToSessionStorage'), (payload) => { return payload === 'url' ? undefined : payload; }); /** * Triggers the add to cart tracking. * * @public */ const trackAddToCartFromSessionStorage = wireExternalTaggingService('trackAddToCart'); /** * Clears the session id. * * @public */ const clearSessionWire = filter(wireSessionServiceWithoutPayload('clearSessionId'), ({ eventPayload: consent }) => !consent); /** * Sets the tagging state `consent`. * * @public */ const setConsent = wireCommit('setConsent'); /** * Sets the tagging state `noResultsTaggingEnabled`. * * @public */ const setNoResultsTaggingEnabledWire = wireCommit('setNoResultsTaggingEnabled'); /** * Sets the tagging config state. * * @public */ const setTaggingConfig = wireCommit('mergeConfig'); /** * Tracks the tagging of the query. * * @public */ const trackQueryWire = filter(wireDispatch('track'), ({ eventPayload, store }) => eventPayload.params.totalHits > 0 || !store.state.x.tagging.noResultsTaggingEnabled); /** * Sets the tagging state of the query tagging info using a debounce which ends if the user * accepts a query. * * @public */ const setQueryTaggingInfo = moduleDebounce(wireCommit('setQueryTaggingInfo'), ({ state }) => state.config.queryTaggingDebounceMs, { cancelOn: 'UserClearedQuery', forceOn: [ 'UserClickedAResult', 'UserClickedAPromoted', 'UserClickedABanner', 'UserClickedARedirection', 'UserReachedResultsListEnd', ], }); /** * Sets the tagging state of the query tagging info using. * * @public */ const setQueryTaggingFromQueryPreview = createSetQueryTaggingFromQueryPreview(); /** * Tracks the tagging of the result. * * @public */ const trackResultClickedWire = createTrackWire('click'); /** * Tracks the tagging of the banner. * * @public */ const trackBannerClickedWire = createTrackWire('click'); /** * Tracks the click on a promoted result. * * @public */ const trackPromotedClickedWire = createTrackWire('click'); /** * Performs a track of a result added to the cart. * * @public */ const trackAddToCartWire = createTrackWire('add2cart'); /** * Performs a track of a display result being clicked. * * @public */ const trackDisplayClickedWire = createTrackDisplayWire('displayClick'); /** * Performs a track of a display result being clicked. * * @public */ const trackToolingDisplayClickedWire = createTrackToolingDisplayWire(); /** * Performs a track of a display result being clicked. * * @public */ const trackToolingAdd2CartWire = createTrackToolingAdd2CartWire(); /** * Performs a track of a clicked related prompt. * * @public */ const trackRelatedPromptToolingDisplayClickWire = createTrackRelatedPromptToolingDisplayClickWire(); /** * Performs a track of a display element appearing. * * @public */ const trackElementDisplayedWire = createTrackDisplayWire('display'); /** * Factory helper to create a wire for the track of a taggable element. * * @param property - Key of the tagging object to track. * @returns A new wire for the given property of the taggable element. * * @public */ function createTrackWire(property) { return filter(wireDispatch('track', ({ eventPayload: { tagging }, metadata: { location } }) => { const taggingInfo = tagging[property]; taggingInfo.params.location = location; return taggingInfo; }), ({ eventPayload: { tagging }, metadata: { ignoreInModules } }) => // eslint-disable-next-line ts/no-unsafe-member-access !!tagging?.[property] && !ignoreInModules?.includes(moduleName)); } /** * Performs a track of a query with no results that used related prompts or semantic queries as fallback. * The totalHits will be changed to -1 if related prompts or semantic queries are found in order to differentiate * it from scenarios where the user encounters a no-results page without any related prompts or semantic queries. * * @public */ const trackNoResultsQueryWithFallbackWire = filter(wireDispatch('track', ({ eventPayload, state }) => { const { queryTaggingInfo } = state; const totalHits = eventPayload.length > 0 ? -1 : 0; return { params: { ...queryTaggingInfo?.params, totalHits }, url: queryTaggingInfo?.url ?? '', }; }), ({ store }) => Number(store.state.x.tagging.queryTaggingInfo?.params.totalHits) === 0); /**. * Debounced version of {@link trackNoResultsQueryWithFallbackWire} * * @public */ const trackNoResultsQueryWithFallbackWireDebounced = moduleDebounce(trackNoResultsQueryWithFallbackWire, ({ state }) => state.config.queryTaggingDebounceMs, { cancelOn: ['QueryPreviewUnmounted', 'RelatedPromptsUnmounted'] }); /** * Performs a track of a query with no results that used semantic queries as fallback. * The totalHits will be changed to -1 if semantic queries are found in order to differentiate * it from scenarios where the user encounters a no-results page without any semantic queries. * * @public * @deprecated - Use {@link trackNoResultsQueryWithFallbackWire} instead. */ const trackNoResultsQueryWithSemanticsWire = trackNoResultsQueryWithFallbackWire; /** * Debounced version of {@link trackNoResultsQueryWithFallbackWire} * * @public * @deprecated - Use {@link trackNoResultsQueryWithFallbackWireDebounced} instead. */ const trackNoResultsQueryWithSemanticsWireDebounced = trackNoResultsQueryWithFallbackWireDebounced; /** * Performs a track of clicking the AI overview expand button when the playload (expanded) is false. * * @public */ const trackAiOverviewButtonClickedWire = filterTruthyPayload(wireDispatch('track', ({ metadata: { toolingDisplayClick, suggestionText } }) => { const taggingInfo = { ...toolingDisplayClick, params: { ...toolingDisplayClick.params, productId: 'EXPAND', title: suggestionText, url: 'none', }, }; return taggingInfo; })); /** * Factory helper to create a wire for the track of the display click. * * @param property - Key of the tagging object to track. * @returns A new wire for the display click of the taggable element. * * @public */ function createTrackDisplayWire(property) { return filter(wireDispatch('track', ({ eventPayload: { tagging }, metadata }) => { const taggingInfo = tagging[property]; const location = metadata.location; taggingInfo.params.location = location; taggingInfo.params.displayFamily = createOrigin({ feature: metadata.feature, location, }); taggingInfo.params.q = metadata.displayOriginalQuery; return taggingInfo; }), // eslint-disable-next-line ts/no-unsafe-member-access ({ eventPayload: { tagging } }) => !!tagging?.[property]?.url); } /** * Update the tooling tagging params with the result information. * * @param taggingRequest - The tooling tagging request to be updated. * @param result - The clicked result. * @returns The tagging request updated. * * @internal */ function updateToolingTaggingWithResult(taggingRequest, result) { taggingRequest.params.productId = result.id; taggingRequest.params.title = result.name; taggingRequest.params.url = result.url; return taggingRequest; } /** * Factory helper to create a wire for the track of the tooling display click. * * @returns A new wire for the tooling display click of the taggable element. * * @public */ function createTrackToolingDisplayWire() { return filter(wireDispatch('track', ({ eventPayload, metadata }) => { const taggingInfo = metadata.toolingTagging; const resultInfo = eventPayload; updateToolingTaggingWithResult(taggingInfo, resultInfo); return taggingInfo; }), ({ metadata }) => !!metadata?.toolingTagging); } /** * Factory helper to create a wire for the track of the tooling display add to cart. * * @returns A new wire for the tooling display add to cart of the taggable element. * * @public */ function createTrackToolingAdd2CartWire() { return filter(wireDispatch('track', ({ eventPayload, metadata }) => { const taggingInfo = metadata.toolingAdd2CartTagging; const resultInfo = eventPayload; updateToolingTaggingWithResult(taggingInfo, resultInfo); return taggingInfo; }), ({ metadata }) => !!metadata?.toolingAdd2CartTagging); } /** * Factory helper to create a wire for the track of the tooling display click in a related prompt. * * @returns A new wire for the tooling display click of the taggable element. * * @public */ function createTrackRelatedPromptToolingDisplayClickWire() { return filter(wireDispatch('track', ({ metadata }) => { const relatedPrompt = metadata.relatedPrompt; const taggingInfo = relatedPrompt.tagging.toolingDisplayClickTagging; taggingInfo.params.productId = 'EXPAND'; taggingInfo.params.title = relatedPrompt.suggestionText; taggingInfo.params.url = 'none'; return taggingInfo; }), ({ metadata }) => { const relatedPrompt = metadata.relatedPrompt; const isUnselected = metadata?.selectedPrompt === -1; const taggingInfo = relatedPrompt?.tagging?.toolingDisplayClickTagging; return isUnselected && !!taggingInfo; }); } /** * Factory helper to create a wire to set the queryTagging. * * @returns A new wire for the query of a result of a queryPreview. * * @public */ function createSetQueryTaggingFromQueryPreview() { return filter(wireCommit('setQueryTaggingInfo', ({ metadata: { queryTagging } }) => queryTagging), ({ metadata: { queryTagging } }) => !!queryTagging); } /** * Wiring configuration for the {@link TaggingXModule | tagging module}. * * @internal */ const taggingWiring = createWiring({ ConsentProvided: { setConsent, }, ConsentChanged: { clearSessionWire, }, PDPIsLoaded: { moveClickedResultToSessionWire, }, ResultURLTrackingEnabled: { moveClickedResultToSessionWire, }, SearchTaggingChanged: { setQueryTaggingInfo, }, SearchTaggingReceived: { trackQueryWire, }, TrackableElementDisplayed: { trackElementDisplayedWire, }, TaggingConfigProvided: { setTaggingConfig, }, UserClickedAResult: { trackResultClickedWire, storeClickedResultWire, }, UserClickedResultAddToCart: { trackAddToCartWire, trackResultClickedWire, storeAddToCartWire, }, UserClickedPDPAddToCart: { trackAddToCartFromSessionStorage, }, UserClickedABanner: { trackBannerClickedWire, }, UserClickedAPromoted: { trackPromotedClickedWire, }, UserClickedADisplayResult: { trackDisplayClickedWire, setQueryTaggingFromQueryPreview, }, SemanticQueriesResponseChanged: { trackNoResultsQueryWithFallbackWireDebounced, }, RelatedPromptsResponseChanged: { trackNoResultsQueryWithFallbackWireDebounced, }, ModuleRegistered: { setNoResultsTaggingEnabledWire, }, UserClickedARelatedPromptResult: { trackToolingDisplayClickedWire, }, UserClickedARelatedPromptAdd2Cart: { trackToolingAdd2CartWire, }, UserSelectedARelatedPrompt: { trackRelatedPromptToolingDisplayClickWire, }, UserClickedAiOverviewExpandButton: { trackAiOverviewButtonClickedWire, }, }); export { createSetQueryTaggingFromQueryPreview, createTrackDisplayWire, createTrackRelatedPromptToolingDisplayClickWire, createTrackToolingAdd2CartWire, createTrackToolingDisplayWire, createTrackWire, setConsent, setNoResultsTaggingEnabledWire, setQueryTaggingFromQueryPreview, setQueryTaggingInfo, setTaggingConfig, taggingWiring, trackAddToCartWire, trackAiOverviewButtonClickedWire, trackBannerClickedWire, trackDisplayClickedWire, trackElementDisplayedWire, trackNoResultsQueryWithFallbackWire, trackNoResultsQueryWithFallbackWireDebounced, trackNoResultsQueryWithSemanticsWire, trackNoResultsQueryWithSemanticsWireDebounced, trackPromotedClickedWire, trackQueryWire, trackRelatedPromptToolingDisplayClickWire, trackResultClickedWire, trackToolingAdd2CartWire, trackToolingDisplayClickedWire }; //# sourceMappingURL=wiring.js.map