var GA_MEASUREMENT_ID; var hostname = window.location.hostname; if (hostname === 'www.myshowcasejewellery.com') { GA_MEASUREMENT_ID = 'G-VW80DV2W4G'; } else if (hostname === 'uat-showcase.rivermounts.com') { GA_MEASUREMENT_ID = 'G-NCX6XGKPZ0'; } else { GA_MEASUREMENT_ID = 'G-GMSHP9BXNZ'; } var s = document.createElement('script'); s.async = true; s.src = 'https://www.googletagmanager.com/gtag/js?id=' + GA_MEASUREMENT_ID; document.head.appendChild(s); window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); var gaConfig = { 'cookie_domain': 'auto' }; // Attach identity + currency to the initial page_view + subsequent events if a prior page // in this tab already stored them. Without this, early events (e.g. navigation abandonment) // fire before showcase_user_ready resolves, with no identity or (wrong) default currency. try { var earlyUserId = sessionStorage.getItem('showcase_ga_user_id'); var earlyRetailerId = sessionStorage.getItem('showcase_ga_retailer_id'); var earlyCurrency = sessionStorage.getItem('showcase_ga_currency'); if (earlyUserId) gaConfig.user_id = earlyUserId; if (earlyRetailerId) gaConfig.user_properties = { retailer_id: earlyRetailerId }; if (earlyCurrency) gaConfig.currency = earlyCurrency; } catch (earlyErr) {} gtag('config', GA_MEASUREMENT_ID, gaConfig); document.addEventListener('lwc_ga_event', function(e) { if (typeof gtag === 'function' && e.detail) { var params = { 'event_category': e.detail.eventCategory, 'event_label': e.detail.eventLabel, 'value': e.detail.eventValue }; if (e.detail.items) params.items = e.detail.items; if (e.detail.currency) params.currency = e.detail.currency; if (e.detail.transaction_id) params.transaction_id = e.detail.transaction_id; if (e.detail.shipping != null) params.shipping = e.detail.shipping; if (e.detail.tax != null) params.tax = e.detail.tax; if (e.detail.item_list_id) params.item_list_id = e.detail.item_list_id; if (e.detail.item_list_name) params.item_list_name = e.detail.item_list_name; if (e.detail.method) params.method = e.detail.method; if (e.detail.search_term) params.search_term = e.detail.search_term; if (e.detail.content_type) params.content_type = e.detail.content_type; // filter_* use != null so explicit empty strings from typeahead empty_search_results // reach GA4 as '' rather than being dropped. Mirrors rmUtils.trackGAEvent whitelist. if (e.detail.filter_style != null) params.filter_style = e.detail.filter_style; if (e.detail.filter_coverage != null) params.filter_coverage = e.detail.filter_coverage; if (e.detail.filter_weight != null) params.filter_weight = e.detail.filter_weight; if (e.detail.filter_width != null) params.filter_width = e.detail.filter_width; if (e.detail.filter_diamond_type != null) params.filter_diamond_type = e.detail.filter_diamond_type; if (e.detail.filter_metal != null) params.filter_metal = e.detail.filter_metal; if (e.detail.filter_finger_size != null) params.filter_finger_size = e.detail.filter_finger_size; if (e.detail.form_name) params.form_name = e.detail.form_name; if (e.detail.field_name) params.field_name = e.detail.field_name; if (e.detail.error_message) params.error_message = e.detail.error_message; if (e.detail.last_step) params.last_step = e.detail.last_step; // user_id fallback for events before showcase_user_ready fires. // retailer_id is user-scoped (see gtag 'user_properties' set in the showcase_user_ready listener), // so it must NOT be duplicated as an event-level param — GA4 would create a second event-scoped dimension. var storedUserId = null; try { storedUserId = sessionStorage.getItem('showcase_ga_user_id'); } catch (sessionErr) {} if (storedUserId) params.user_id = storedUserId; gtag('event', e.detail.eventName, params); } }); // GA4 user identity bridge (fires when LWC publishes identity) document.addEventListener('showcase_user_ready', function(e) { if (typeof gtag !== 'function' || !e.detail || !e.detail.userId) return; gtag('set', { user_id: e.detail.userId }); if (e.detail.retailerId) { gtag('set', 'user_properties', { retailer_id: e.detail.retailerId }); } // Set currency as a default so any subsequent event without an explicit currency param // inherits the retailer's ISO code. Avoids the 'GBP' fallback for non-GBP retailers on // SPA navigations between the identity publish and the next event. if (e.detail.currency) { gtag('set', { currency: e.detail.currency }); } }); // Microsoft Clarity - environment-based project ID. // PROD project ID is null until the Clarity Prod project is created. A null ID skips the // script load entirely, preventing a bogus request to https://www.clarity.ms/tag/PROD_PROJECT_ID. // Replace null with the real prod project ID before merging to main. var CLARITY_PROJECT_ID; if (hostname === 'www.myshowcasejewellery.com') { CLARITY_PROJECT_ID = null; // TODO: replace with real Clarity prod project ID before prod deploy } else { CLARITY_PROJECT_ID = 'wg4w16nzr0'; } if (CLARITY_PROJECT_ID) { (function(c,l,a,r,i,t,y){ c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); })(window, document, "clarity", "script", CLARITY_PROJECT_ID); // Clarity user identity bridge — only register when the Clarity script will actually load. // Previously this listener registered unconditionally, which meant it ran on every identity // dispatch in prod (where the project ID is still null) even though the typeof clarity // === 'function' guard kept it silent. Moving inside the if-block avoids that cost. document.addEventListener('showcase_user_ready', function(e) { if (typeof clarity === 'function' && e.detail && e.detail.userId) { clarity('identify', e.detail.userId); if (e.detail.retailerId) { clarity('set', 'retailer_id', e.detail.retailerId); } } }); }