import { LocalEvent } from "../../commons/types/local-event"; import { CookieUtils } from "../../commons/utils/cookie-utils"; import { EventEmitter } from "../../commons/utils/event-emitter"; import { Http } from "../../commons/utils/http"; import { SessionUtils } from "../../commons/utils/session-utils"; import { navigator } from "../../commons/utils/browser-utils"; import { EventQueue } from "../../commons/utils/event-queue"; /** * All event namespaces. * * @export * @enum {string} */ export enum EventType { // Session SessionStart = "session.start", SessionPing = "session.ping", SessionUser = "session.user", SessionCartAdd = "session.cart.add", SessionCartRemove = "session.cart.remove", // Page PageCart = "page.cart", PageConfirmation = "page.confirmation", PageEmptyCart = "page.empty_cart", PageHome = "page.home", PageCategory = "page.category", PageCategoryClick = "page.category.click", // Datalayer SearchQuery = "search.query", SearchClick = "search.click", FrontView = "front.view", FrontClick = "front.click", SearchAutocompleteQuery = "search.autocomplete.query", AutocompleteClick = "search.autocomplete.click", ProductView = "page.product", NavigationView = "navigation.view", // Conversion ApiClick = "api.click", MailClick = "mail.click", } /** * Generic event. * * Contains the underlying logic of sending an * event to the server. * * @export * @abstract * @class Event */ export abstract class Event { public abstract type: EventType; /** * Creates an instance of Event. * * @param {string} [session=undefined] * @param {string} [anonymous=undefined] * @param {string} [variant=undefined] * @param {string} [url=document?.location.href || "unknown"] * @param {string} [agent=navigator?.userAgent || "unknown"] * @memberof Event */ constructor( public session: string = undefined, public anonymous: string = undefined, public url: string = document?.location.href || "unknown", public agent: string = navigator()?.userAgent || "unknown", ) {} private variant: string; private workspace: string; public ab: string; /** * Push this event to the server. * * If you find yourself pushing multiple events * at the same time, see `BatchEventBuilder`. * * @return {Promise} * @memberof Event */ public async push(): Promise { if (!CookieUtils.enabled) { // TODO: Here we should have some kind of metric. // This metric would be used to track how many PageViews we are losing from // disabled cookies. return; } if (!this.session || !this.anonymous) { this.session = SessionUtils.getSession(); this.anonymous = SessionUtils.getAnonymous(); } if (!this.variant && (window as any).isABEnabled) this.variant = await SessionUtils.getVariant(this.anonymous); // This auto-fills the workspace/AB information on IO. if ((window as any)?.__RUNTIME__?.workspace) { const workspace = (window as any)?.__RUNTIME__?.workspace; this.withWorkspace(workspace); } if (this.variant || this.workspace) { this.ab = [this.variant, this.workspace].join("-"); } EventQueue.enqueue(this); EventEmitter.trigger(LocalEvent.EventPush, this); const result = await Http.post( `${window._RecSys.Bundle.Properties.event.url}/${window._RecSys.Bundle.Configuration.store.slug}/${window._RecSys.Bundle.Properties.event.endpoint.event}`, this, ); EventQueue.dequeue(); return result; } public withWorkspace(workspace: string): this { this.workspace = workspace; return this; } }