@empathyco/x-components
Version:
Empathy X Components
422 lines (419 loc) • 14.2 kB
JavaScript
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