{"version":3,"file":"static/js/76d0377871a9e3dcf790.bundle.js","mappings":"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","sources":["webpack://united-malt/./src/modules/analytics-ga4/analytics-ga4.tsx?e0e5","webpack://united-malt/./src/utilities/analytics/analytics-dispatcher.ts?75be","webpack://united-malt/./lib/analytics-ga4/module-registration.js?3107","webpack://united-malt/external var \"React\"?0d3b"],"sourcesContent":["//==============================================================================\r\n//==============================================================================\r\nimport * as React from 'react';\r\n\r\nimport { subscribe } from '../../utilities/analytics/analytics-dispatcher';\r\nimport {\r\n AddToCartEvent,\r\n AddToWishlistEvent,\r\n CheckoutPaymentEvent,\r\n CheckoutShippingEvent,\r\n CheckoutStartEvent,\r\n ImpressionEvent,\r\n PDPVisitEvent,\r\n RemoveFromCartEvent,\r\n SingleProductEvent,\r\n TransactionEvent\r\n} from '../../utilities/analytics/analytics-events';\r\n\r\nimport * as GA4 from './ga4-typings';\r\n\r\nimport { IAnalyticsGa4Data } from './analytics-ga4.data';\r\nimport { IAnalyticsGa4Props } from './analytics-ga4.props.autogenerated';\r\n\r\n//==============================================================================\r\n// INTERFACES\r\n//==============================================================================\r\ndeclare const dataLayer: any[] | undefined;\r\n\r\n//----------------------------------------------------------\r\n// Client-specific custom fields\r\n//----------------------------------------------------------\r\ninterface ExtendedProductData extends GA4.GA4_Item {\r\n uom?: string; // Unit of measure\r\n milling?: string; // Milling grade\r\n}\r\n\r\n//==============================================================================\r\n// CLASS DEFINITION\r\n//==============================================================================\r\n/**\r\n * AnalyticsGa4 component\r\n * @extends {React.PureComponent>}\r\n */\r\nclass AnalyticsGa4 extends React.PureComponent> {\r\n\r\n private SUBSCRIBER_NAME = 'GOOGLE_ANALYTICS_4';\r\n\r\n //----------------------------------------------------------\r\n // Subscribe to events\r\n // NOTE: Currently, events can only be emitted from the\r\n // client. If we run this in the constructor, it occurs\r\n // during SSR and is cached across page views. Singletons\r\n // that maintain state are kept in memory on the server,\r\n // making them dangerous.\r\n // In the future the analytics system will queue\r\n // up events emitted during SSR. When that happens, the\r\n // system will need to switch to data actions to prevent\r\n // subscriptions from persisting globally on the server.\r\n //----------------------------------------------------------\r\n public componentDidMount() {\r\n this.addToCart = this.addToCart.bind(this);\r\n this.removeFromCart = this.removeFromCart.bind(this);\r\n this.purchase = this.purchase.bind(this);\r\n this.addToWishlist = this.addToWishlist.bind(this);\r\n this.productDetailView = this.productDetailView.bind(this);\r\n this.impression = this.impression.bind(this);\r\n this.checkoutStart = this.checkoutStart.bind(this);\r\n this.checkoutShipping = this.checkoutShipping.bind(this);\r\n this.checkoutPayment = this.checkoutPayment.bind(this);\r\n\r\n subscribe(this.SUBSCRIBER_NAME, 'addToCart', this.addToCart);\r\n subscribe(this.SUBSCRIBER_NAME, 'removeFromCart', this.removeFromCart);\r\n subscribe(this.SUBSCRIBER_NAME, 'purchase', this.purchase);\r\n subscribe(this.SUBSCRIBER_NAME, 'addToWishlist', this.addToWishlist);\r\n subscribe(this.SUBSCRIBER_NAME, 'productDetailView', this.productDetailView);\r\n subscribe(this.SUBSCRIBER_NAME, 'impression', this.impression);\r\n subscribe(this.SUBSCRIBER_NAME, 'checkoutStart', this.checkoutStart);\r\n subscribe(this.SUBSCRIBER_NAME, 'checkoutShipping', this.checkoutShipping);\r\n subscribe(this.SUBSCRIBER_NAME, 'checkoutPayment', this.checkoutPayment);\r\n }\r\n\r\n //----------------------------------------------------------\r\n // No visuals are involved\r\n //----------------------------------------------------------\r\n public render(): null {\r\n return null;\r\n }\r\n\r\n //==============================================================================\r\n // Helpers\r\n //==============================================================================\r\n\r\n //----------------------------------------------------------\r\n // Convert generic event data to a GA4_Item record\r\n //----------------------------------------------------------\r\n private formatProduct(product: SingleProductEvent): ExtendedProductData {\r\n\r\n return {\r\n item_id: product.itemID,\r\n item_name: product.name,\r\n item_variant: product.variant,\r\n\r\n quantity: product.quantity,\r\n currency: product.currency,\r\n price: product.price,\r\n discount: product.discount,\r\n\r\n item_brand: product.brand,\r\n location_id: product.pickupInStore,\r\n\r\n // Custom: non-standard GA4\r\n uom: product.unitOfMeasure,\r\n milling: product.attributes?.CartLineMillGrade,\r\n };\r\n }\r\n\r\n //----------------------------------------------------------\r\n //----------------------------------------------------------\r\n private emit(event: unknown) {\r\n if (typeof dataLayer !== 'undefined') {\r\n dataLayer.push(event);\r\n }\r\n }\r\n\r\n //==============================================================================\r\n // EVENT HANDLERS\r\n //==============================================================================\r\n\r\n //----------------------------------------------------------\r\n // Add to Cart\r\n //----------------------------------------------------------\r\n private addToCart(data: AddToCartEvent): void {\r\n\r\n // Create an event rather than directly pushing to the data layer to enforce typing\r\n const event: GA4.AddToCartEvent = {\r\n event: 'add_to_cart',\r\n ecommerce: {\r\n currency: data.currency,\r\n value: (data.price || 0) * data.quantity,\r\n items: [this.formatProduct(data)],\r\n }\r\n };\r\n\r\n this.emit(event);\r\n }\r\n\r\n //----------------------------------------------------------\r\n // Remove from Cart\r\n //----------------------------------------------------------\r\n private removeFromCart(data: RemoveFromCartEvent): void {\r\n\r\n // Create an event rather than directly pushing to the data layer to enforce typing\r\n const event: GA4.RemoveFromCartEvent = {\r\n event: 'remove_from_cart',\r\n ecommerce: {\r\n currency: data.currency,\r\n value: (data.price || 0) * data.quantity,\r\n items: [this.formatProduct(data)],\r\n }\r\n };\r\n\r\n this.emit(event);\r\n }\r\n\r\n //----------------------------------------------------------\r\n // Purchase Complete\r\n //----------------------------------------------------------\r\n private purchase(data: TransactionEvent): void {\r\n\r\n // Create an event rather than directly pushing to the data layer to enforce typing\r\n const event: GA4.PurchaseEvent = {\r\n event: 'purchase',\r\n ecommerce: {\r\n transaction_id: data.id,\r\n currency: data.currency,\r\n value: data.total,\r\n shipping: data.shipping,\r\n tax: data.tax,\r\n coupon: data.coupons?.join('|'),\r\n items: data.lines.map(entry => this.formatProduct(entry)),\r\n }\r\n };\r\n\r\n this.emit(event);\r\n }\r\n\r\n //----------------------------------------------------------\r\n // Add to wishlist\r\n //----------------------------------------------------------\r\n private addToWishlist(data: AddToWishlistEvent): void {\r\n\r\n const event: GA4.AddToWishlistEvent = {\r\n event: 'add_to_wishlist',\r\n ecommerce: {\r\n currency: data.currency,\r\n value: (data.price || 0) * data.quantity,\r\n items: [this.formatProduct(data)],\r\n }\r\n };\r\n\r\n this.emit(event);\r\n }\r\n\r\n //----------------------------------------------------------\r\n // Product Detail View (PDP visited)\r\n //----------------------------------------------------------\r\n private productDetailView(data: PDPVisitEvent): void {\r\n\r\n const event: GA4.ProductViewEvent = {\r\n event: 'view_item',\r\n ecommerce: {\r\n currency: data.currency,\r\n value: data.price,\r\n items: [this.formatProduct(data)],\r\n }\r\n };\r\n\r\n this.emit(event);\r\n }\r\n\r\n //----------------------------------------------------------\r\n // Product Impressions\r\n // Currently used for PLPs and product collections,\r\n // so we'll use the view_item_list event\r\n //----------------------------------------------------------\r\n private impression(data: ImpressionEvent): void {\r\n\r\n const event: GA4.ProductListViewEvent = {\r\n event: 'view_item_list',\r\n ecommerce: {\r\n item_list_id: data.list,\r\n item_list_name: data.context,\r\n items: data.products.map(entry => this.formatProduct(entry)),\r\n }\r\n };\r\n\r\n this.emit(event);\r\n }\r\n\r\n //----------------------------------------------------------\r\n // Checkout Start\r\n //----------------------------------------------------------\r\n private checkoutStart(data: CheckoutStartEvent): void {\r\n\r\n const event: GA4.CheckoutStartEvent = {\r\n event: 'begin_checkout',\r\n ecommerce: {\r\n currency: data.currency,\r\n value: data.subtotal,\r\n items: data.lines.map(entry => this.formatProduct(entry)),\r\n }\r\n };\r\n\r\n this.emit(event);\r\n }\r\n\r\n //----------------------------------------------------------\r\n // Checkout Start\r\n //----------------------------------------------------------\r\n private checkoutShipping(data: CheckoutShippingEvent): void {\r\n\r\n const event: GA4.CheckoutShippingEvent = {\r\n event: 'add_shipping_info',\r\n ecommerce: {\r\n shipping_tier: data.shippingMethod,\r\n currency: data.currency,\r\n value: data.shippingCost,\r\n coupon: data.coupon,\r\n items: data.lines?.map(entry => this.formatProduct(entry)),\r\n }\r\n };\r\n\r\n this.emit(event);\r\n }\r\n\r\n //----------------------------------------------------------\r\n // Checkout Start\r\n //----------------------------------------------------------\r\n private checkoutPayment(data: CheckoutPaymentEvent): void {\r\n\r\n const event: GA4.CheckoutPaymentEvent = {\r\n event: 'add_payment_info',\r\n ecommerce: {\r\n payment_type: data.paymentMethod,\r\n currency: data.currency,\r\n value: data.amount,\r\n items: data.lines?.map(entry => this.formatProduct(entry)),\r\n }\r\n };\r\n\r\n this.emit(event);\r\n }\r\n\r\n}\r\n\r\nexport default AnalyticsGa4;\r\n","//==============================================================================\r\n// Analytics Event Dispatcher (Simple Pub-Sub system)\r\n//\r\n// This module receives events and forwards them to the appropriate handlers\r\n// Subscriptions are managed using a subscriber ID to aid in unsubscribing\r\n//\r\n// NOTE: Singletons aren't compatible with SSR. This module acts as a singleton,\r\n// maintaining its data as a global. Modules MUST call subscribe on the client\r\n// ONLY (via componentDidMount).\r\n//\r\n// @TODO: Currently, only client-side events will be processed. Events generated\r\n// during server-side renders will be lost. If we move data to a data action\r\n// it can be persisted from server to client. That will allow us to queue up\r\n// events generated on the server or before subscriptions occur, and emit\r\n// them immediately upon subscription.\r\n//==============================================================================\r\nimport { EventHandler } from \"./analytics-events\";\r\n\r\n//==============================================================================\r\n// INTERFACES\r\n//==============================================================================\r\n\r\n// List of subscribers to a single event\r\ninterface EventSubscribers {\r\n [subscriber: string]: EventHandler;\r\n}\r\n\r\n//==============================================================================\r\n// GLOBALS\r\n//==============================================================================\r\n\r\n// List of subscriptions, organized by event name and then subscriber name\r\nconst subscriptions: { [eventName: string]: EventSubscribers } = {};\r\n\r\n//==============================================================================\r\n// FUNCTIONS\r\n//==============================================================================\r\n\r\n//==========================================================\r\n// Called by event emitters when an event occurs\r\n//\r\n// NOTE: This should only be called on the client! Events on\r\n// the server will be lost. They should instead be queued\r\n// via a data action cache.\r\n//==========================================================\r\nexport function publish(eventName: string, eventData: unknown): void {\r\n\r\n // Get the list of subscribers for this event\r\n const subscribers = Object.keys(subscriptions[eventName] || {});\r\n\r\n // Notify each subscriber\r\n subscribers.forEach(subscriber => subscriptions[eventName][subscriber](eventData));\r\n}\r\n\r\n//==========================================================\r\n// Called by event handlers when they self-register for events\r\n//==========================================================\r\nexport function subscribe(subscriber: string, eventName: string, handler: EventHandler): void {\r\n\r\n // If it's a new event, create an entry\r\n subscriptions[eventName] = subscriptions[eventName] || {};\r\n\r\n // Ensure this subscriber isn't already subscribed to this event\r\n if (subscriptions[eventName][subscriber]) {\r\n throw new Error(`Duplicate subscription request for ${subscriber}: ${eventName}`);\r\n }\r\n\r\n // Add the subscription\r\n subscriptions[eventName][subscriber] = handler;\r\n}\r\n\r\n//==========================================================\r\n// Unsubscribe from a single event\r\n//==========================================================\r\nexport function unsubscribe(subscriber: string, eventName: string): void {\r\n if (subscriptions[eventName] && subscriptions[eventName][subscriber]) {\r\n delete subscriptions[eventName][subscriber];\r\n }\r\n}\r\n","const binding = { modules: {}, dataActions: {} };\n\n (binding.modules['analytics-ga4'] = {\n c: () => require('partner/modules/analytics-ga4/analytics-ga4.tsx'),\n $type: 'contentModule',\n da: [],\n \n iNM: false,\n ns: '__local__',\n n: 'analytics-ga4',\n p: '__local__',\n \n pdp: '',\n \n \n md: 'src/modules/analytics-ga4'\n });\n \n\n \n window.__bindings__ = window.__bindings__ || {};\n window.__bindings__.modules = {\n ...window.__bindings__.modules || {},\n ...binding.modules\n };\n \n window.__bindings__.dataActions = {\n ...window.__bindings__.dataActions || {},\n ...binding.dataActions\n };","module.exports = React;"],"names":["AnalyticsGa4","React","constructor","SUBSCRIBER_NAME","componentDidMount","this","addToCart","bind","removeFromCart","purchase","addToWishlist","productDetailView","impression","checkoutStart","checkoutShipping","checkoutPayment","subscribe","render","formatProduct","product","_product$attributes","item_id","itemID","item_name","name","item_variant","variant","quantity","currency","price","discount","item_brand","brand","location_id","pickupInStore","uom","unitOfMeasure","milling","attributes","CartLineMillGrade","emit","event","dataLayer","push","data","ecommerce","value","items","_data$coupons","transaction_id","id","total","shipping","tax","coupon","coupons","join","lines","map","entry","item_list_id","list","item_list_name","context","products","subtotal","_data$lines","shipping_tier","shippingMethod","shippingCost","_data$lines2","payment_type","paymentMethod","amount","subscriptions","publish","eventName","eventData","Object","keys","forEach","subscriber","handler","Error","binding","modules","dataActions","c","require","$type","da","iNM","ns","n","p","pdp","md","window","__bindings__","_objectSpread","module","exports"],"sourceRoot":""}