@hifilabs/pixel 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.js CHANGED
@@ -8,7 +8,7 @@ var ArtistPixel = (() => {
8
8
 
9
9
  // src/browser.ts
10
10
  (function() {
11
- const PIXEL_VERSION = "0.10.0";
11
+ const PIXEL_VERSION = "0.11.0";
12
12
  function parseUserAgent(ua) {
13
13
  let device_type = "desktop";
14
14
  if (/ipad|tablet|android(?!.*mobile)/i.test(ua))
@@ -202,6 +202,7 @@ var ArtistPixel = (() => {
202
202
  let fanIdHash = null;
203
203
  let consent = null;
204
204
  let attribution = {};
205
+ let linkRegistry = {};
205
206
  let eventQueue = [];
206
207
  let flushTimer = null;
207
208
  let currentStorageTier = "session";
@@ -901,6 +902,29 @@ var ArtistPixel = (() => {
901
902
  function hasConsent(type) {
902
903
  return consent?.[type] === true;
903
904
  }
905
+ function registerLinks(links) {
906
+ for (const [url, metadata] of Object.entries(links)) {
907
+ try {
908
+ const normalizedUrl = normalizeUrlForRegistry(url);
909
+ linkRegistry[normalizedUrl] = metadata;
910
+ } catch {
911
+ linkRegistry[url] = metadata;
912
+ }
913
+ }
914
+ log("Registered", Object.keys(links).length, "links for tracking enrichment");
915
+ }
916
+ function normalizeUrlForRegistry(url) {
917
+ try {
918
+ const parsed = new URL(url);
919
+ return `${parsed.protocol}//${parsed.host}${parsed.pathname}${parsed.search}`;
920
+ } catch {
921
+ return url;
922
+ }
923
+ }
924
+ function getLinkMetadata(url) {
925
+ const normalizedUrl = normalizeUrlForRegistry(url);
926
+ return linkRegistry[normalizedUrl] || null;
927
+ }
904
928
  async function hashEmail(email) {
905
929
  const normalized = email.toLowerCase().trim();
906
930
  const encoder = new TextEncoder();
@@ -1284,15 +1308,22 @@ var ArtistPixel = (() => {
1284
1308
  }
1285
1309
  function trackExternalClick(url, element) {
1286
1310
  const platform = detectPlatform(url);
1287
- const linkText = element?.textContent?.trim().substring(0, 100) || "";
1288
- const linkId = element?.id || element?.getAttribute("data-link-id") || void 0;
1289
- log("External link clicked:", { url, platform, linkText });
1311
+ const registeredMeta = getLinkMetadata(url);
1312
+ const linkText = registeredMeta?.title || element?.textContent?.trim().substring(0, 100) || "";
1313
+ const linkId = registeredMeta?.id || element?.id || element?.getAttribute("data-link-id") || void 0;
1314
+ const linkCategory = registeredMeta?.category;
1315
+ log("External link clicked:", { url, platform, linkText, linkId, fromRegistry: !!registeredMeta });
1290
1316
  track("page_link_click", {
1291
1317
  link_url: url,
1292
1318
  link_text: linkText,
1293
1319
  link_id: linkId,
1294
1320
  platform,
1295
- link_type: "external"
1321
+ link_type: "external",
1322
+ ...linkCategory && { link_category: linkCategory },
1323
+ // Include any additional custom properties from registry
1324
+ ...registeredMeta && Object.fromEntries(
1325
+ Object.entries(registeredMeta).filter(([key]) => !["title", "id", "category"].includes(key)).map(([key, value]) => [`link_${key}`, value])
1326
+ )
1296
1327
  });
1297
1328
  }
1298
1329
  const originalWindowOpen = window.open;
@@ -1411,6 +1442,7 @@ var ArtistPixel = (() => {
1411
1442
  setConsent,
1412
1443
  getConsent,
1413
1444
  hasConsent,
1445
+ registerLinks,
1414
1446
  _version: PIXEL_VERSION
1415
1447
  // Expose version for collision detection
1416
1448
  };
@@ -1,4 +1,4 @@
1
- var ArtistPixel=(()=>{var It=Object.defineProperty;var Ct=(p,w,m)=>w in p?It(p,w,{enumerable:!0,configurable:!0,writable:!0,value:m}):p[w]=m;var $=(p,w,m)=>(Ct(p,typeof w!="symbol"?w+"":w,m),m);(function(){let p="0.10.0";function w(e){let t="desktop";/ipad|tablet|android(?!.*mobile)/i.test(e)?t="tablet":/mobile|iphone|android.*mobile|blackberry|iemobile/i.test(e)&&(t="mobile");let n="Unknown";/edg/i.test(e)?n="Edge":/opr|opera/i.test(e)?n="Opera":/firefox/i.test(e)?n="Firefox":/chrome/i.test(e)?n="Chrome":/safari/i.test(e)&&(n="Safari");let o="Unknown";return/iphone|ipad/i.test(e)?o="iOS":/android/i.test(e)?o="Android":/windows/i.test(e)?o="Windows":/mac os/i.test(e)?o="macOS":/linux/i.test(e)?o="Linux":/cros/i.test(e)&&(o="ChromeOS"),{device_type:t,browser:n,os:o}}let m=null;function Ne(){if(!m)try{m=w(navigator.userAgent)}catch{m={device_type:"desktop",browser:"Unknown",os:"Unknown"}}return m}let s=document.currentScript,B=s?.dataset.artistId,W=s?.dataset.projectId,G=W?He(W):void 0;function He(e){return!e||e.startsWith("release_")||e.startsWith("merch_")||e.startsWith("link_")||e.startsWith("custom_")?e:`custom_${e}`}let K=s?.dataset.emulator==="true",ge=s?.dataset.debug==="true",Y=parseInt(s?.dataset.heartbeatInterval||"120000",10),me=s?.dataset.heartbeat!=="false",pe=s?.dataset.source,we=s?.dataset.endpoint,h=window.__artistPixelConfig||{},L=s?.dataset.metaPixelId||h.metaPixelId,C=s?.dataset.tiktokPixelId||h.tiktokPixelId,f=s?.dataset.googleAdsId||h.googleAdsId,he=s?.dataset.googleAdsConversionLabel||h.googleAdsConversionLabel,_={pageview:(s?.dataset.forwardPageview??h.forwardPageview)!=="false",purchase:(s?.dataset.forwardPurchase??h.forwardPurchase)!=="false",addToCart:(s?.dataset.forwardAddToCart??h.forwardAddToCart)!=="false",lead:(s?.dataset.forwardLead??h.forwardLead)!=="false",custom:(s?.dataset.forwardCustom||h.forwardCustom||"").split(",").filter(Boolean)},R=!!(L||C||f),J=s?.dataset.consentUi==="true",ze=s?.dataset.consentStyle||"brutalist",Ve=s?.dataset.primaryColor,$e=s?.dataset.bannerPosition||"bottom",be=s?.dataset.excludePages?.split(",").filter(Boolean)||[],ye=s?.dataset.trackFileDownloads==="true",Be=s?.dataset.hashRouting==="true";function We(){if(pe)return pe;let e=typeof window.dataLayer<"u"&&Array.isArray(window.dataLayer),t=typeof window.gtag=="function";return e&&t?"gtm":"pixel"}let N="pixel";if(!B){I(" Error: data-artist-id attribute is required");return}let ve="session_id",X="session_timestamp",_e="attribution",ke="fan_id_hash",Q="visitor_id",H="artistPixel_consent",Ge=365*24*60*60*1e3,Ke=30*24*60*60*1e3,Ye=60*60*1e3,S="balance_";function Je(e){let t=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp("^"+t+"$")}function Xe(e){if(be.length===0)return!1;try{let t=new URL(e,window.location.origin).pathname;return be.some(n=>Je(n).test(t))}catch{return!1}}let Qe=[".pdf",".zip",".tar",".gz",".rar",".7z",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".mp3",".wav",".flac",".aac",".ogg",".mp4",".mov",".avi",".mkv",".webm",".exe",".dmg",".pkg",".deb",".rpm",".csv",".json",".xml",".txt"];function xe(e){try{let t=new URL(e,window.location.origin).pathname.toLowerCase();return Qe.some(n=>t.endsWith(n))}catch{return!1}}function Ze(e,t){try{let o=new URL(e,window.location.origin).pathname.split("/").pop()||"unknown",c=o.includes(".")?o.split(".").pop():"unknown";a("File download tracked:",{url:e,fileName:o,fileExtension:c});let l=k({event_name:"custom",metadata:{event_type:"file_download",file_url:e,file_name:o,file_extension:c,link_text:t?.textContent?.trim().substring(0,100)||""}});x(l)}catch(n){I("Failed to track file download:",n)}}let et="https://balance-pixel-proxy.hifilabs.workers.dev",Ie="https://us-central1-artist-os-distro.cloudfunctions.net/ingestEvents",P=we||(K?"http://localhost:5001/artist-os-distro/us-central1/ingestEvents":et),D=null,g=null,b=null,u=null,E={},y=[],Z=null,v="session",T=null,ee=0,te=0,A=0,O=!0,ne=0,ae=!1,tt=2*60*1e3,Ce=Date.now(),M=!1,nt=!ge,a=(...e)=>{ge&&console.log("[artistPixel]",...e)},I=(...e)=>{nt||console.error("[artistPixel]",...e)},oe={base:`
1
+ var ArtistPixel=(()=>{var Re=Object.defineProperty;var De=(p,w,m)=>w in p?Re(p,w,{enumerable:!0,configurable:!0,writable:!0,value:m}):p[w]=m;var V=(p,w,m)=>(De(p,typeof w!="symbol"?w+"":w,m),m);(function(){let p="0.11.0";function w(t){let e="desktop";/ipad|tablet|android(?!.*mobile)/i.test(t)?e="tablet":/mobile|iphone|android.*mobile|blackberry|iemobile/i.test(t)&&(e="mobile");let n="Unknown";/edg/i.test(t)?n="Edge":/opr|opera/i.test(t)?n="Opera":/firefox/i.test(t)?n="Firefox":/chrome/i.test(t)?n="Chrome":/safari/i.test(t)&&(n="Safari");let i="Unknown";return/iphone|ipad/i.test(t)?i="iOS":/android/i.test(t)?i="Android":/windows/i.test(t)?i="Windows":/mac os/i.test(t)?i="macOS":/linux/i.test(t)?i="Linux":/cros/i.test(t)&&(i="ChromeOS"),{device_type:e,browser:n,os:i}}let m=null;function Wt(){if(!m)try{m=w(navigator.userAgent)}catch{m={device_type:"desktop",browser:"Unknown",os:"Unknown"}}return m}let s=document.currentScript,B=s?.dataset.artistId,W=s?.dataset.projectId,G=W?Gt(W):void 0;function Gt(t){return!t||t.startsWith("release_")||t.startsWith("merch_")||t.startsWith("link_")||t.startsWith("custom_")?t:`custom_${t}`}let K=s?.dataset.emulator==="true",pt=s?.dataset.debug==="true",Y=parseInt(s?.dataset.heartbeatInterval||"120000",10),wt=s?.dataset.heartbeat!=="false",ht=s?.dataset.source,bt=s?.dataset.endpoint,h=window.__artistPixelConfig||{},R=s?.dataset.metaPixelId||h.metaPixelId,S=s?.dataset.tiktokPixelId||h.tiktokPixelId,f=s?.dataset.googleAdsId||h.googleAdsId,yt=s?.dataset.googleAdsConversionLabel||h.googleAdsConversionLabel,_={pageview:(s?.dataset.forwardPageview??h.forwardPageview)!=="false",purchase:(s?.dataset.forwardPurchase??h.forwardPurchase)!=="false",addToCart:(s?.dataset.forwardAddToCart??h.forwardAddToCart)!=="false",lead:(s?.dataset.forwardLead??h.forwardLead)!=="false",custom:(s?.dataset.forwardCustom||h.forwardCustom||"").split(",").filter(Boolean)},D=!!(R||S||f),J=s?.dataset.consentUi==="true",Kt=s?.dataset.consentStyle||"brutalist",Yt=s?.dataset.primaryColor,Jt=s?.dataset.bannerPosition||"bottom",vt=s?.dataset.excludePages?.split(",").filter(Boolean)||[],kt=s?.dataset.trackFileDownloads==="true",Xt=s?.dataset.hashRouting==="true";function Qt(){if(ht)return ht;let t=typeof window.dataLayer<"u"&&Array.isArray(window.dataLayer),e=typeof window.gtag=="function";return t&&e?"gtm":"pixel"}let N="pixel";if(!B){C(" Error: data-artist-id attribute is required");return}let _t="session_id",X="session_timestamp",xt="attribution",It="fan_id_hash",Q="visitor_id",z="artistPixel_consent",Zt=365*24*60*60*1e3,te=30*24*60*60*1e3,ee=60*60*1e3,P="balance_";function ne(t){let e=t.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp("^"+e+"$")}function ae(t){if(vt.length===0)return!1;try{let e=new URL(t,window.location.origin).pathname;return vt.some(n=>ne(n).test(e))}catch{return!1}}let ie=[".pdf",".zip",".tar",".gz",".rar",".7z",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".mp3",".wav",".flac",".aac",".ogg",".mp4",".mov",".avi",".mkv",".webm",".exe",".dmg",".pkg",".deb",".rpm",".csv",".json",".xml",".txt"];function Ct(t){try{let e=new URL(t,window.location.origin).pathname.toLowerCase();return ie.some(n=>e.endsWith(n))}catch{return!1}}function oe(t,e){try{let i=new URL(t,window.location.origin).pathname.split("/").pop()||"unknown",c=i.includes(".")?i.split(".").pop():"unknown";a("File download tracked:",{url:t,fileName:i,fileExtension:c});let l=x({event_name:"custom",metadata:{event_type:"file_download",file_url:t,file_name:i,file_extension:c,link_text:e?.textContent?.trim().substring(0,100)||""}});I(l)}catch(n){C("Failed to track file download:",n)}}let re="https://balance-pixel-proxy.hifilabs.workers.dev",St="https://us-central1-artist-os-distro.cloudfunctions.net/ingestEvents",E=bt||(K?"http://localhost:5001/artist-os-distro/us-central1/ingestEvents":re),O=null,g=null,b=null,u=null,T={},Z={},y=[],tt=null,v="session",L=null,et=0,nt=0,A=0,M=!0,at=0,it=!1,se=2*60*1e3,Pt=Date.now(),U=!1,ce=!pt,a=(...t)=>{pt&&console.log("[artistPixel]",...t)},C=(...t)=>{ce||console.error("[artistPixel]",...t)},ot={base:`
2
2
  :host {
3
3
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
4
4
  position: fixed;
@@ -83,11 +83,11 @@ var ArtistPixel=(()=>{var It=Object.defineProperty;var Ct=(p,w,m)=>w in p?It(p,w
83
83
  }
84
84
  .btn.accept { background: #fff; color: #000; border-color: #fff; }
85
85
  .btn:hover { opacity: 0.8; }
86
- `};class at{constructor(t){$(this,"container",null);$(this,"shadow",null);$(this,"config");if(this.config=t,this.hasStoredConsent()){a("ConsentManager: Consent already exists, not showing banner");return}this.container=document.createElement("div"),this.container.id="artistPixel-consent-manager",this.shadow=this.container.attachShadow({mode:"closed"}),this.render(),document.body.appendChild(this.container),a("ConsentManager: Banner rendered")}hasStoredConsent(){try{return window._balanceConsentNeedsRefresh?!1:localStorage.getItem(H)!==null}catch{return!1}}render(){if(!this.shadow)return;let t=this.config.style||"brutalist",n=oe.base,o=oe[t]||oe.brutalist,c=this.config.position==="top"?"top: 0;":"bottom: 0;",l=this.config.primaryColor?`.btn.accept { background: ${this.config.primaryColor} !important; border-color: ${this.config.primaryColor} !important; color: #fff !important; }`:"";this.shadow.innerHTML=`
86
+ `};class le{constructor(e){V(this,"container",null);V(this,"shadow",null);V(this,"config");if(this.config=e,this.hasStoredConsent()){a("ConsentManager: Consent already exists, not showing banner");return}this.container=document.createElement("div"),this.container.id="artistPixel-consent-manager",this.shadow=this.container.attachShadow({mode:"closed"}),this.render(),document.body.appendChild(this.container),a("ConsentManager: Banner rendered")}hasStoredConsent(){try{return window._balanceConsentNeedsRefresh?!1:localStorage.getItem(z)!==null}catch{return!1}}render(){if(!this.shadow)return;let e=this.config.style||"brutalist",n=ot.base,i=ot[e]||ot.brutalist,c=this.config.position==="top"?"top: 0;":"bottom: 0;",l=this.config.primaryColor?`.btn.accept { background: ${this.config.primaryColor} !important; border-color: ${this.config.primaryColor} !important; color: #fff !important; }`:"";this.shadow.innerHTML=`
87
87
  <style>
88
88
  ${n}
89
89
  :host { ${c} }
90
- ${o}
90
+ ${i}
91
91
  ${l}
92
92
  </style>
93
93
  <div class="banner" role="dialog" aria-label="Cookie consent" aria-modal="false">
@@ -99,4 +99,4 @@ var ArtistPixel=(()=>{var It=Object.defineProperty;var Ct=(p,w,m)=>w in p?It(p,w
99
99
  <button id="accept" class="btn accept">Accept</button>
100
100
  </div>
101
101
  </div>
102
- `,this.shadow.getElementById("accept")?.addEventListener("click",()=>this.handleConsent(!0)),this.shadow.getElementById("decline")?.addEventListener("click",()=>this.handleConsent(!1))}handleConsent(t){window.balance?.setConsent&&window.balance.setConsent({analytics:t,marketing:t,personalization:t,timestamp:new Date().toISOString()}),t&&!window._balanceInitialPageviewFired&&(window._balanceInitialPageviewFired=!0,window.balance?.page&&window.balance.page(),le(),a("Initial pageview fired after consent granted")),this.remove()}remove(){this.container&&(this.container.remove(),this.container=null,this.shadow=null,a("ConsentManager: Banner removed"))}}let Se=!1,ie=!1;function ot(){if(!L)return;if(window.fbq){a("[Platform:Meta] Already loaded, skipping");return}a("[Platform:Meta] Injecting pixel:",L);let e=function(...n){e.callMethod?e.callMethod.apply(e,n):e.queue.push(n)};window._fbq||(window._fbq=e),e.push=e,e.loaded=!0,e.version="2.0",e.queue=[],window.fbq=e;let t=document.createElement("script");t.async=!0,t.src="https://connect.facebook.net/en_US/fbevents.js",t.onload=()=>{window.fbq("init",L),_.pageview&&window.fbq("track","PageView"),a("[Platform:Meta] Initialized and PageView tracked")},document.head.appendChild(t)}function it(){if(!C)return;if(window.ttq?._i?.[C]){a("[Platform:TikTok] Already loaded, skipping");return}a("[Platform:TikTok] Injecting pixel:",C);let e=window,t="ttq";e.TiktokAnalyticsObject=t;let n=e[t]=e[t]||[];n.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie","holdConsent","revokeConsent","grantConsent"],n.setAndDefer=function(o,c){o[c]=function(...l){o.push([c].concat(l))}};for(let o=0;o<n.methods.length;o++)n.setAndDefer(n,n.methods[o]);n.instance=function(o){let c=n._i[o]||[];for(let l=0;l<n.methods.length;l++)n.setAndDefer(c,n.methods[l]);return c},n.load=function(o){let c="https://analytics.tiktok.com/i18n/pixel/events.js";n._i=n._i||{},n._i[o]=[],n._i[o]._u=c,n._t=n._t||{},n._t[o]=+new Date,n._o=n._o||{};let l=document.createElement("script");l.type="text/javascript",l.async=!0,l.src=c+"?sdkid="+o+"&lib="+t,document.head.appendChild(l)},n.load(C),_.pageview&&n.page(),a("[Platform:TikTok] Initialized and page() tracked")}function rt(){if(!f)return;if(window.dataLayer=window.dataLayer||[],typeof window.gtag!="function"&&(window.gtag=function(...t){window.dataLayer.push(t)}),document.querySelector('script[src*="googletagmanager.com/gtag/js"]')){a("[Platform:GoogleAds] gtag.js already loaded, configuring"),window.gtag("config",f);return}a("[Platform:GoogleAds] Injecting gtag:",f),window.gtag("consent","default",{ad_storage:"granted",ad_user_data:"granted",ad_personalization:"granted",analytics_storage:"granted"});let e=document.createElement("script");e.async=!0,e.src=`https://www.googletagmanager.com/gtag/js?id=${f}`,e.onload=()=>{window.gtag("js",new Date),window.gtag("config",f),a("[Platform:GoogleAds] Initialized")},document.head.appendChild(e)}function st(){if(R){if(Se){a("[Platform] Already loaded, skipping");return}if(!ie){a("[Platform] Marketing consent not granted, deferring");return}a("[Platform] Injecting platform pixels (consent granted)"),Se=!0,ot(),it(),rt()}}function Pe(e){if(ie=e,a("[Platform] Marketing consent:",e?"granted":"denied"),e&&st(),window.ttq&&(e?window.ttq.grantConsent?.():window.ttq.revokeConsent?.()),typeof window.gtag=="function"){let t=e?"granted":"denied";window.gtag("consent","update",{ad_storage:t,ad_user_data:t,ad_personalization:t})}}function re(e){if(!R||!ie)return!1;let t=e.toLowerCase();return t==="pageview"||t==="page_view"?_.pageview:t==="purchase"?_.purchase:t==="addtocart"||t==="add_to_cart"?_.addToCart:t==="lead"||t==="form_submit"?_.lead:_.custom.length>0?_.custom.some(n=>n.toLowerCase()===t):!1}function ct(){re("pageview")&&(a("[Platform] Forwarding PageView"),window.fbq&&window.fbq("track","PageView"),window.ttq&&window.ttq.page())}function lt(e,t,n){if(re("purchase")&&(a("[Platform] Forwarding Purchase:",e,t),window.fbq&&window.fbq("track","Purchase",{value:e,currency:t,content_ids:n?.contentIds,content_type:n?.contentType||"product",order_id:n?.transactionId}),window.ttq&&window.ttq.track("CompletePayment",{value:e,currency:t,order_id:n?.transactionId}),typeof window.gtag=="function"&&f)){let o=he?`${f}/${he}`:f;window.gtag("event","conversion",{send_to:o,value:e,currency:t,transaction_id:n?.transactionId}),window.gtag("event","purchase",{send_to:f,value:e,currency:t,transaction_id:n?.transactionId})}}function dt(e,t){if(!re(e))return;let n=e.toLowerCase();a("[Platform] Forwarding custom event:",e);let o={addtocart:"AddToCart",add_to_cart:"AddToCart",lead:"Lead",form_submit:"Lead",viewcontent:"ViewContent",view_content:"ViewContent",search:"Search",subscribe:"Subscribe",contact:"Contact",completeregistration:"CompleteRegistration",complete_registration:"CompleteRegistration",initiatecheckout:"InitiateCheckout",initiate_checkout:"InitiateCheckout"},c={addtocart:"AddToCart",add_to_cart:"AddToCart",lead:"SubmitForm",form_submit:"SubmitForm",viewcontent:"ViewContent",view_content:"ViewContent",search:"Search",subscribe:"Subscribe",contact:"Contact",completeregistration:"CompleteRegistration",complete_registration:"CompleteRegistration",initiatecheckout:"InitiateCheckout",initiate_checkout:"InitiateCheckout"},l={addtocart:"add_to_cart",add_to_cart:"add_to_cart",lead:"generate_lead",form_submit:"generate_lead",viewcontent:"view_item",view_content:"view_item",search:"search",subscribe:"subscribe",contact:"contact",completeregistration:"sign_up",complete_registration:"sign_up",initiatecheckout:"begin_checkout",initiate_checkout:"begin_checkout"};if(window.fbq){let r=o[n];r?window.fbq("track",r,t):window.fbq("trackCustom",e,t)}if(window.ttq){let r=c[n]||e;window.ttq.track(r,t)}if(typeof window.gtag=="function"&&f){let r=l[n]||e;window.gtag("event",r,{send_to:f,...t})}}function Ee(){try{return v==="local"?localStorage:sessionStorage}catch{return null}}function z(e){let t=Ee();if(!t)return null;try{let n=S+e,o=t.getItem(n);if(!o&&v==="session")try{o=localStorage.getItem(n)}catch{}return o}catch{return null}}function U(e,t){let n=Ee();if(n)try{n.setItem(S+e,t)}catch{}}function Te(){if(v!=="local"){a("Upgrading storage tier: session -> local");try{let e=[];for(let t=0;t<sessionStorage.length;t++){let n=sessionStorage.key(t);n?.startsWith(S)&&e.push(n)}for(let t of e){let n=sessionStorage.getItem(t);n&&localStorage.setItem(t,n)}for(let t of e)sessionStorage.removeItem(t);v="local",a(`Storage tier upgraded, migrated ${e.length} items`)}catch(e){I(" Storage migration failed:",e)}}}function V(){return crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}function ut(){try{let e=z(ve),t=z(X);if(e&&t&&Date.now()-parseInt(t,10)<Ye)return U(X,Date.now().toString()),e;let n=V();return U(ve,n),U(X,Date.now().toString()),n}catch{return V()}}function ft(){let e=new URLSearchParams(window.location.search),t={};return["source","medium","campaign","content","term"].forEach(n=>{let o=e.get(`utm_${n}`);o&&(t[`utm_${n}`]=o)}),t}function gt(){try{let e=z(_e);if(e){E=JSON.parse(e),a("Loaded attribution:",E);return}let t=ft();Object.keys(t).length>0&&(E=t,U(_e,JSON.stringify(t)),a("Captured attribution:",E))}catch{}}function mt(){try{b=z(ke)}catch{}}function se(){try{let e=localStorage.getItem(S+Q);if(e)return e;let t=V();return localStorage.setItem(S+Q,t),a("Created persistent visitor ID:",t.substring(0,8)+"..."),t}catch{return a("localStorage unavailable, using session ID as fallback"),D||V()}}function pt(){try{g=localStorage.getItem(S+Q),g&&a("Loaded visitor ID:",g.substring(0,8)+"...")}catch{}}function wt(){try{let e=localStorage.getItem(H);if(e){let t=JSON.parse(e);if(t.expiresAt&&Date.now()>t.expiresAt){a("Consent expired - clearing stored consent"),localStorage.removeItem(H),u=null;return}if(t.expiresAt){let n=t.expiresAt-Date.now();n>0&&n<Ke&&(a("Consent nearing expiration - will prompt for refresh"),window._balanceConsentNeedsRefresh=!0)}u=t.preferences||null,a("Loaded consent:",u)}}catch{}}function Ae(e){let t=u;u=e;try{let o={preferences:e,method:"explicit",version:1,expiresAt:Date.now()+Ge};localStorage.setItem(H,JSON.stringify(o)),a("Consent saved with TTL:",e),window._balanceConsentNeedsRefresh=!1}catch(o){I(" Could not save consent:",o)}e.analytics===!0&&(Te(),g||(g=se()));let n=k({event_name:"consent_updated",metadata:{consent_preferences:e,consent_method:"explicit",previous_consent:t||void 0}});x(n);try{window.dispatchEvent(new CustomEvent("artistPixel:consent:updated",{detail:e})),a("DOM event artistPixel:consent:updated dispatched")}catch{}R&&Pe(e.marketing===!0)}function ht(){return u}function bt(e){return u?.[e]===!0}async function yt(e){let t=e.toLowerCase().trim(),o=new TextEncoder().encode(t),c=await crypto.subtle.digest("SHA-256",o);return Array.from(new Uint8Array(c)).map(r=>r.toString(16).padStart(2,"0")).join("")}function k(e){let t=Ne(),n={artist_id:B,fan_session_id:D,visitor_id:g||se(),fan_id_hash:b||void 0,timestamp:new Date().toISOString(),source_url:window.location.href,referrer_url:document.referrer||void 0,user_agent:navigator.userAgent,device_type:t.device_type,browser:t.browser,os:t.os,tracking_source:N,...e,...E};return G&&!e.projectId&&(n.projectId=G),n}function x(e){y.push(e),a("Event queued:",e.event_name,"(queue:",y.length,")"),y.length>=10&&q()}async function q(){if(y.length===0)return;let e=[...y];y=[],a("Flushing",e.length,"events to",P);try{let t=await fetch(P,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({events:e}),keepalive:!0});if(!t.ok)throw new Error(`HTTP ${t.status}`);a("Events sent successfully")}catch(t){if(I(" Failed to send events, trying fallback:",t),P!==Ie&&!K)try{if((await fetch(Ie,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({events:e}),keepalive:!0})).ok){a("Events sent via fallback (no geo)");return}}catch(n){I(" Fallback also failed:",n)}y.length<50&&y.push(...e)}}function vt(){Z&&clearInterval(Z),Z=window.setInterval(()=>{y.length>0&&q()},5e3)}function ce(){A||(ee=Date.now()),A=Date.now(),O=!0,a("Active time tracking started/resumed")}function Le(){A&&O&&(te+=Date.now()-A),O=!1,a("Active time tracking paused, accumulated:",te,"ms")}function Re(){let e=te;return O&&A&&(e+=Date.now()-A),e}function _t(){Ce=Date.now(),M&&(M=!1,ce(),a("User returned from idle"))}function kt(){if(document.visibilityState==="hidden"){a("Skipping heartbeat - tab hidden");return}if(Date.now()-Ce>tt){M||(M=!0,Le(),a("User idle - pausing heartbeat"));return}let e=Re(),t=Math.round(e/1e3),n=k({event_name:"engagement_heartbeat",metadata:{time_on_page_seconds:t,time_on_page_ms:e,heartbeat_interval_ms:Y,is_active:O&&!M}});x(n),ne++,a("Heartbeat sent:",t,"seconds active")}function le(){if(!me){a('Heartbeat disabled via data-heartbeat="false"');return}T&&clearInterval(T),ce(),T=window.setInterval(()=>{kt()},Y),a("Heartbeat started with interval:",Y,"ms")}function de(){if(!ae){if(ae=!0,T&&(clearInterval(T),T=null),me){let e=ee?Date.now()-ee:0,t=Re(),n=k({event_name:"engagement_summary",metadata:{total_time_ms:e,active_time_ms:t,heartbeat_samples:ne,page_path:window.location.pathname}});if(navigator.sendBeacon&&P){let o=JSON.stringify({events:[n]});navigator.sendBeacon(P,o),a("Engagement summary sent via sendBeacon:",Math.round(t/1e3),"seconds active")}else x(n),a("Engagement summary enqueued:",Math.round(t/1e3),"seconds active")}ne=0}}function F(e={}){let t=e.url||window.location.href;if(Xe(t)){a("Page excluded from tracking:",t);return}let n=k({event_name:"pageview",page_title:e.title||document.title,source_url:t});x(n),ct()}function ue(e,t={}){let n=k({event_name:"custom",metadata:{event_type:e,...t}});x(n),dt(e,t)}async function De(e,t={}){try{if(u&&u.analytics===!1){a("Identify skipped - user declined analytics consent");return}b=await yt(e),u?.analytics===!0&&Te(),U(ke,b);let n=e.split("@"),o=n[0].charAt(0)+"***@"+(n[1]||"");a("Fan identified:",{name:t.name||"(no name)",email:o,hash:b.substring(0,16)+"...",traits:t,storageTier:v});let c=k({event_name:"identify",fan_id_hash:b,metadata:{email_sha256:b,email_display:o,traits:t,consent_preferences:u||void 0,storage_tier:v}});x(c)}catch(n){I(" Failed to identify:",n)}}function Oe(e,t="USD",n={}){let o=k({event_name:"purchase",metadata:{revenue:e,currency:t,...n}});x(o),lt(e,t,n)}function Me(){N=We(),a("Tracking source detected:",N),wt(),u?.analytics===!0?(v="local",a("Storage tier: local (analytics consent granted)")):(v="session",a("Storage tier: session (privacy by default)")),D=ut(),mt(),pt(),g||(g=se()),u||a(J?"Consent UI enabled, waiting for explicit user consent (Tier 0 mode)":"No consent - operating in privacy-first mode (session storage only, limited tracking)"),R&&u?.marketing===!0?(a("[Platform] Marketing consent already granted, initializing platform pixels"),Pe(!0)):R&&a("[Platform] Platform pixels configured:",{meta:L||"(none)",tiktok:C||"(none)",googleAds:f||"(none)"}),gt(),vt(),a("Initialized",{artistId:B,projectId:G||"(none - will track to all projects)",rawProjectId:W||"(none)",sessionId:D,visitorId:g?g.substring(0,8)+"...":null,fanIdHash:b,consent:u,storageTier:v,trackingSource:N,useEmulator:K,endpoint:P}),u?.analytics===!0?(window._balanceInitialPageviewFired=!0,F(),le(),a("Full tracking enabled (user consented)")):J?a("Tracking dormant - waiting for explicit consent via ConsentManager"):(window._balanceInitialPageviewFired=!0,F(),le(),a("Privacy-first tracking enabled (session-scoped, visitor_id for deduplication)")),["mousemove","keydown","scroll","touchstart"].forEach(r=>{document.addEventListener(r,_t,{passive:!0})});let e=window.location.hostname;function t(r){try{let i=new URL(r).hostname.toLowerCase();return i.includes("spotify")?"spotify":i.includes("apple")||i.includes("music.apple")?"apple_music":i.includes("youtube")||i.includes("youtu.be")?"youtube":i.includes("soundcloud")?"soundcloud":i.includes("tidal")?"tidal":i.includes("deezer")?"deezer":i.includes("amazon")||i.includes("music.amazon")?"amazon_music":i.includes("bandcamp")?"bandcamp":i.includes("lnk.to")||i.includes("linkfire")?"linkfire":i.includes("linktr.ee")?"linktree":i.includes("shop")||i.includes("store")||i.includes("merch")?"shop":i.includes("ticketmaster")||i.includes("eventbrite")||i.includes("dice.fm")?"tickets":i.includes("instagram")?"instagram":i.includes("twitter")||i.includes("x.com")?"twitter":i.includes("tiktok")?"tiktok":i.includes("facebook")?"facebook":"external"}catch{return"external"}}function n(r){try{return new URL(r,window.location.origin).hostname!==e}catch{return!1}}function o(r,i){let d=t(r),j=i?.textContent?.trim().substring(0,100)||"",xt=i?.id||i?.getAttribute("data-link-id")||void 0;a("External link clicked:",{url:r,platform:d,linkText:j}),ue("page_link_click",{link_url:r,link_text:j,link_id:xt,platform:d,link_type:"external"})}let c=window.open;if(window.open=function(r,i,d){if(r){let j=r.toString();n(j)&&o(j)}return c.call(window,r,i,d)},a("window.open interception enabled (always on)"),s?.dataset.autoTrackLinks==="true"&&(document.addEventListener("click",r=>{let d=r.target.closest("a");if(d&&d.href&&n(d.href)){if(ye&&(xe(d.href)||d.hasAttribute("download")))return;o(d.href,d)}},{capture:!0,passive:!0}),a("External link click listener enabled (opt-in)")),ye&&(document.addEventListener("click",r=>{let d=r.target.closest("a");d?.href&&(xe(d.href)||d.hasAttribute("download"))&&Ze(d.href,d)},{capture:!0,passive:!0}),a("File download tracking enabled")),Be){let r=window.location.href;window.addEventListener("hashchange",()=>{let i=window.location.href;i!==r&&(r=i,setTimeout(()=>{F({title:document.title,url:i})},0))}),a("Hash routing tracking enabled")}document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"?(Le(),de(),q()):(ce(),ae=!1)}),window.addEventListener("pagehide",()=>{de(),q()}),window.addEventListener("beforeunload",()=>{de(),q()})}if(window.balance?._version&&window.balance._version!==p){console.warn(`[artistPixel] Version conflict: ${window.balance._version} already loaded, skipping ${p}`);return}let fe=window.balance?.q||[];function Ue(){if(fe.length>0){a("Processing",fe.length,"queued commands");for(let e of fe){let[t,...n]=e;switch(t){case"track":ue(n[0],n[1]);break;case"identify":De(n[0],n[1]);break;case"page":F(n[0]);break;case"purchase":Oe(n[0],n[1],n[2]);break;case"setConsent":Ae(n[0]);break;default:a("Unknown queued command:",t)}}}}let qe={track:ue,identify:De,page:F,purchase:Oe,getSessionId:()=>D,getVisitorId:()=>g,getFanIdHash:()=>b,getAttribution:()=>E,setConsent:Ae,getConsent:ht,hasConsent:bt,_version:p};window.artistPixel=qe,window.balance=qe;function Fe(){J&&!u&&new at({style:ze,primaryColor:Ve,position:$e})}let je=window.requestIdleCallback||(e=>setTimeout(e,1));document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{Me(),Ue(),je(()=>Fe())}):(Me(),Ue(),je(()=>Fe())),a("Pixel script loaded")})();})();
102
+ `,this.shadow.getElementById("accept")?.addEventListener("click",()=>this.handleConsent(!0)),this.shadow.getElementById("decline")?.addEventListener("click",()=>this.handleConsent(!1))}handleConsent(e){window.balance?.setConsent&&window.balance.setConsent({analytics:e,marketing:e,personalization:e,timestamp:new Date().toISOString()}),e&&!window._balanceInitialPageviewFired&&(window._balanceInitialPageviewFired=!0,window.balance?.page&&window.balance.page(),dt(),a("Initial pageview fired after consent granted")),this.remove()}remove(){this.container&&(this.container.remove(),this.container=null,this.shadow=null,a("ConsentManager: Banner removed"))}}let Et=!1,rt=!1;function de(){if(!R)return;if(window.fbq){a("[Platform:Meta] Already loaded, skipping");return}a("[Platform:Meta] Injecting pixel:",R);let t=function(...n){t.callMethod?t.callMethod.apply(t,n):t.queue.push(n)};window._fbq||(window._fbq=t),t.push=t,t.loaded=!0,t.version="2.0",t.queue=[],window.fbq=t;let e=document.createElement("script");e.async=!0,e.src="https://connect.facebook.net/en_US/fbevents.js",e.onload=()=>{window.fbq("init",R),_.pageview&&window.fbq("track","PageView"),a("[Platform:Meta] Initialized and PageView tracked")},document.head.appendChild(e)}function ue(){if(!S)return;if(window.ttq?._i?.[S]){a("[Platform:TikTok] Already loaded, skipping");return}a("[Platform:TikTok] Injecting pixel:",S);let t=window,e="ttq";t.TiktokAnalyticsObject=e;let n=t[e]=t[e]||[];n.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie","holdConsent","revokeConsent","grantConsent"],n.setAndDefer=function(i,c){i[c]=function(...l){i.push([c].concat(l))}};for(let i=0;i<n.methods.length;i++)n.setAndDefer(n,n.methods[i]);n.instance=function(i){let c=n._i[i]||[];for(let l=0;l<n.methods.length;l++)n.setAndDefer(c,n.methods[l]);return c},n.load=function(i){let c="https://analytics.tiktok.com/i18n/pixel/events.js";n._i=n._i||{},n._i[i]=[],n._i[i]._u=c,n._t=n._t||{},n._t[i]=+new Date,n._o=n._o||{};let l=document.createElement("script");l.type="text/javascript",l.async=!0,l.src=c+"?sdkid="+i+"&lib="+e,document.head.appendChild(l)},n.load(S),_.pageview&&n.page(),a("[Platform:TikTok] Initialized and page() tracked")}function fe(){if(!f)return;if(window.dataLayer=window.dataLayer||[],typeof window.gtag!="function"&&(window.gtag=function(...e){window.dataLayer.push(e)}),document.querySelector('script[src*="googletagmanager.com/gtag/js"]')){a("[Platform:GoogleAds] gtag.js already loaded, configuring"),window.gtag("config",f);return}a("[Platform:GoogleAds] Injecting gtag:",f),window.gtag("consent","default",{ad_storage:"granted",ad_user_data:"granted",ad_personalization:"granted",analytics_storage:"granted"});let t=document.createElement("script");t.async=!0,t.src=`https://www.googletagmanager.com/gtag/js?id=${f}`,t.onload=()=>{window.gtag("js",new Date),window.gtag("config",f),a("[Platform:GoogleAds] Initialized")},document.head.appendChild(t)}function ge(){if(D){if(Et){a("[Platform] Already loaded, skipping");return}if(!rt){a("[Platform] Marketing consent not granted, deferring");return}a("[Platform] Injecting platform pixels (consent granted)"),Et=!0,de(),ue(),fe()}}function Tt(t){if(rt=t,a("[Platform] Marketing consent:",t?"granted":"denied"),t&&ge(),window.ttq&&(t?window.ttq.grantConsent?.():window.ttq.revokeConsent?.()),typeof window.gtag=="function"){let e=t?"granted":"denied";window.gtag("consent","update",{ad_storage:e,ad_user_data:e,ad_personalization:e})}}function st(t){if(!D||!rt)return!1;let e=t.toLowerCase();return e==="pageview"||e==="page_view"?_.pageview:e==="purchase"?_.purchase:e==="addtocart"||e==="add_to_cart"?_.addToCart:e==="lead"||e==="form_submit"?_.lead:_.custom.length>0?_.custom.some(n=>n.toLowerCase()===e):!1}function me(){st("pageview")&&(a("[Platform] Forwarding PageView"),window.fbq&&window.fbq("track","PageView"),window.ttq&&window.ttq.page())}function pe(t,e,n){if(st("purchase")&&(a("[Platform] Forwarding Purchase:",t,e),window.fbq&&window.fbq("track","Purchase",{value:t,currency:e,content_ids:n?.contentIds,content_type:n?.contentType||"product",order_id:n?.transactionId}),window.ttq&&window.ttq.track("CompletePayment",{value:t,currency:e,order_id:n?.transactionId}),typeof window.gtag=="function"&&f)){let i=yt?`${f}/${yt}`:f;window.gtag("event","conversion",{send_to:i,value:t,currency:e,transaction_id:n?.transactionId}),window.gtag("event","purchase",{send_to:f,value:t,currency:e,transaction_id:n?.transactionId})}}function we(t,e){if(!st(t))return;let n=t.toLowerCase();a("[Platform] Forwarding custom event:",t);let i={addtocart:"AddToCart",add_to_cart:"AddToCart",lead:"Lead",form_submit:"Lead",viewcontent:"ViewContent",view_content:"ViewContent",search:"Search",subscribe:"Subscribe",contact:"Contact",completeregistration:"CompleteRegistration",complete_registration:"CompleteRegistration",initiatecheckout:"InitiateCheckout",initiate_checkout:"InitiateCheckout"},c={addtocart:"AddToCart",add_to_cart:"AddToCart",lead:"SubmitForm",form_submit:"SubmitForm",viewcontent:"ViewContent",view_content:"ViewContent",search:"Search",subscribe:"Subscribe",contact:"Contact",completeregistration:"CompleteRegistration",complete_registration:"CompleteRegistration",initiatecheckout:"InitiateCheckout",initiate_checkout:"InitiateCheckout"},l={addtocart:"add_to_cart",add_to_cart:"add_to_cart",lead:"generate_lead",form_submit:"generate_lead",viewcontent:"view_item",view_content:"view_item",search:"search",subscribe:"subscribe",contact:"contact",completeregistration:"sign_up",complete_registration:"sign_up",initiatecheckout:"begin_checkout",initiate_checkout:"begin_checkout"};if(window.fbq){let r=i[n];r?window.fbq("track",r,e):window.fbq("trackCustom",t,e)}if(window.ttq){let r=c[n]||t;window.ttq.track(r,e)}if(typeof window.gtag=="function"&&f){let r=l[n]||t;window.gtag("event",r,{send_to:f,...e})}}function Lt(){try{return v==="local"?localStorage:sessionStorage}catch{return null}}function H(t){let e=Lt();if(!e)return null;try{let n=P+t,i=e.getItem(n);if(!i&&v==="session")try{i=localStorage.getItem(n)}catch{}return i}catch{return null}}function q(t,e){let n=Lt();if(n)try{n.setItem(P+t,e)}catch{}}function At(){if(v!=="local"){a("Upgrading storage tier: session -> local");try{let t=[];for(let e=0;e<sessionStorage.length;e++){let n=sessionStorage.key(e);n?.startsWith(P)&&t.push(n)}for(let e of t){let n=sessionStorage.getItem(e);n&&localStorage.setItem(e,n)}for(let e of t)sessionStorage.removeItem(e);v="local",a(`Storage tier upgraded, migrated ${t.length} items`)}catch(t){C(" Storage migration failed:",t)}}}function $(){return crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{let e=Math.random()*16|0;return(t==="x"?e:e&3|8).toString(16)})}function he(){try{let t=H(_t),e=H(X);if(t&&e&&Date.now()-parseInt(e,10)<ee)return q(X,Date.now().toString()),t;let n=$();return q(_t,n),q(X,Date.now().toString()),n}catch{return $()}}function be(){let t=new URLSearchParams(window.location.search),e={};return["source","medium","campaign","content","term"].forEach(n=>{let i=t.get(`utm_${n}`);i&&(e[`utm_${n}`]=i)}),e}function ye(){try{let t=H(xt);if(t){T=JSON.parse(t),a("Loaded attribution:",T);return}let e=be();Object.keys(e).length>0&&(T=e,q(xt,JSON.stringify(e)),a("Captured attribution:",T))}catch{}}function ve(){try{b=H(It)}catch{}}function ct(){try{let t=localStorage.getItem(P+Q);if(t)return t;let e=$();return localStorage.setItem(P+Q,e),a("Created persistent visitor ID:",e.substring(0,8)+"..."),e}catch{return a("localStorage unavailable, using session ID as fallback"),O||$()}}function ke(){try{g=localStorage.getItem(P+Q),g&&a("Loaded visitor ID:",g.substring(0,8)+"...")}catch{}}function _e(){try{let t=localStorage.getItem(z);if(t){let e=JSON.parse(t);if(e.expiresAt&&Date.now()>e.expiresAt){a("Consent expired - clearing stored consent"),localStorage.removeItem(z),u=null;return}if(e.expiresAt){let n=e.expiresAt-Date.now();n>0&&n<te&&(a("Consent nearing expiration - will prompt for refresh"),window._balanceConsentNeedsRefresh=!0)}u=e.preferences||null,a("Loaded consent:",u)}}catch{}}function Rt(t){let e=u;u=t;try{let i={preferences:t,method:"explicit",version:1,expiresAt:Date.now()+Zt};localStorage.setItem(z,JSON.stringify(i)),a("Consent saved with TTL:",t),window._balanceConsentNeedsRefresh=!1}catch(i){C(" Could not save consent:",i)}t.analytics===!0&&(At(),g||(g=ct()));let n=x({event_name:"consent_updated",metadata:{consent_preferences:t,consent_method:"explicit",previous_consent:e||void 0}});I(n);try{window.dispatchEvent(new CustomEvent("artistPixel:consent:updated",{detail:t})),a("DOM event artistPixel:consent:updated dispatched")}catch{}D&&Tt(t.marketing===!0)}function xe(){return u}function Ie(t){return u?.[t]===!0}function Ce(t){for(let[e,n]of Object.entries(t))try{let i=Dt(e);Z[i]=n}catch{Z[e]=n}a("Registered",Object.keys(t).length,"links for tracking enrichment")}function Dt(t){try{let e=new URL(t);return`${e.protocol}//${e.host}${e.pathname}${e.search}`}catch{return t}}function Se(t){let e=Dt(t);return Z[e]||null}async function Pe(t){let e=t.toLowerCase().trim(),i=new TextEncoder().encode(e),c=await crypto.subtle.digest("SHA-256",i);return Array.from(new Uint8Array(c)).map(r=>r.toString(16).padStart(2,"0")).join("")}function x(t){let e=Wt(),n={artist_id:B,fan_session_id:O,visitor_id:g||ct(),fan_id_hash:b||void 0,timestamp:new Date().toISOString(),source_url:window.location.href,referrer_url:document.referrer||void 0,user_agent:navigator.userAgent,device_type:e.device_type,browser:e.browser,os:e.os,tracking_source:N,...t,...T};return G&&!t.projectId&&(n.projectId=G),n}function I(t){y.push(t),a("Event queued:",t.event_name,"(queue:",y.length,")"),y.length>=10&&j()}async function j(){if(y.length===0)return;let t=[...y];y=[],a("Flushing",t.length,"events to",E);try{let e=await fetch(E,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({events:t}),keepalive:!0});if(!e.ok)throw new Error(`HTTP ${e.status}`);a("Events sent successfully")}catch(e){if(C(" Failed to send events, trying fallback:",e),E!==St&&!K)try{if((await fetch(St,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({events:t}),keepalive:!0})).ok){a("Events sent via fallback (no geo)");return}}catch(n){C(" Fallback also failed:",n)}y.length<50&&y.push(...t)}}function Ee(){tt&&clearInterval(tt),tt=window.setInterval(()=>{y.length>0&&j()},5e3)}function lt(){A||(et=Date.now()),A=Date.now(),M=!0,a("Active time tracking started/resumed")}function Ot(){A&&M&&(nt+=Date.now()-A),M=!1,a("Active time tracking paused, accumulated:",nt,"ms")}function Mt(){let t=nt;return M&&A&&(t+=Date.now()-A),t}function Te(){Pt=Date.now(),U&&(U=!1,lt(),a("User returned from idle"))}function Le(){if(document.visibilityState==="hidden"){a("Skipping heartbeat - tab hidden");return}if(Date.now()-Pt>se){U||(U=!0,Ot(),a("User idle - pausing heartbeat"));return}let t=Mt(),e=Math.round(t/1e3),n=x({event_name:"engagement_heartbeat",metadata:{time_on_page_seconds:e,time_on_page_ms:t,heartbeat_interval_ms:Y,is_active:M&&!U}});I(n),at++,a("Heartbeat sent:",e,"seconds active")}function dt(){if(!wt){a('Heartbeat disabled via data-heartbeat="false"');return}L&&clearInterval(L),lt(),L=window.setInterval(()=>{Le()},Y),a("Heartbeat started with interval:",Y,"ms")}function ut(){if(!it){if(it=!0,L&&(clearInterval(L),L=null),wt){let t=et?Date.now()-et:0,e=Mt(),n=x({event_name:"engagement_summary",metadata:{total_time_ms:t,active_time_ms:e,heartbeat_samples:at,page_path:window.location.pathname}});if(navigator.sendBeacon&&E){let i=JSON.stringify({events:[n]});navigator.sendBeacon(E,i),a("Engagement summary sent via sendBeacon:",Math.round(e/1e3),"seconds active")}else I(n),a("Engagement summary enqueued:",Math.round(e/1e3),"seconds active")}at=0}}function F(t={}){let e=t.url||window.location.href;if(ae(e)){a("Page excluded from tracking:",e);return}let n=x({event_name:"pageview",page_title:t.title||document.title,source_url:e});I(n),me()}function ft(t,e={}){let n=x({event_name:"custom",metadata:{event_type:t,...e}});I(n),we(t,e)}async function Ut(t,e={}){try{if(u&&u.analytics===!1){a("Identify skipped - user declined analytics consent");return}b=await Pe(t),u?.analytics===!0&&At(),q(It,b);let n=t.split("@"),i=n[0].charAt(0)+"***@"+(n[1]||"");a("Fan identified:",{name:e.name||"(no name)",email:i,hash:b.substring(0,16)+"...",traits:e,storageTier:v});let c=x({event_name:"identify",fan_id_hash:b,metadata:{email_sha256:b,email_display:i,traits:e,consent_preferences:u||void 0,storage_tier:v}});I(c)}catch(n){C(" Failed to identify:",n)}}function qt(t,e="USD",n={}){let i=x({event_name:"purchase",metadata:{revenue:t,currency:e,...n}});I(i),pe(t,e,n)}function jt(){N=Qt(),a("Tracking source detected:",N),_e(),u?.analytics===!0?(v="local",a("Storage tier: local (analytics consent granted)")):(v="session",a("Storage tier: session (privacy by default)")),O=he(),ve(),ke(),g||(g=ct()),u||a(J?"Consent UI enabled, waiting for explicit user consent (Tier 0 mode)":"No consent - operating in privacy-first mode (session storage only, limited tracking)"),D&&u?.marketing===!0?(a("[Platform] Marketing consent already granted, initializing platform pixels"),Tt(!0)):D&&a("[Platform] Platform pixels configured:",{meta:R||"(none)",tiktok:S||"(none)",googleAds:f||"(none)"}),ye(),Ee(),a("Initialized",{artistId:B,projectId:G||"(none - will track to all projects)",rawProjectId:W||"(none)",sessionId:O,visitorId:g?g.substring(0,8)+"...":null,fanIdHash:b,consent:u,storageTier:v,trackingSource:N,useEmulator:K,endpoint:E}),u?.analytics===!0?(window._balanceInitialPageviewFired=!0,F(),dt(),a("Full tracking enabled (user consented)")):J?a("Tracking dormant - waiting for explicit consent via ConsentManager"):(window._balanceInitialPageviewFired=!0,F(),dt(),a("Privacy-first tracking enabled (session-scoped, visitor_id for deduplication)")),["mousemove","keydown","scroll","touchstart"].forEach(r=>{document.addEventListener(r,Te,{passive:!0})});let t=window.location.hostname;function e(r){try{let o=new URL(r).hostname.toLowerCase();return o.includes("spotify")?"spotify":o.includes("apple")||o.includes("music.apple")?"apple_music":o.includes("youtube")||o.includes("youtu.be")?"youtube":o.includes("soundcloud")?"soundcloud":o.includes("tidal")?"tidal":o.includes("deezer")?"deezer":o.includes("amazon")||o.includes("music.amazon")?"amazon_music":o.includes("bandcamp")?"bandcamp":o.includes("lnk.to")||o.includes("linkfire")?"linkfire":o.includes("linktr.ee")?"linktree":o.includes("shop")||o.includes("store")||o.includes("merch")?"shop":o.includes("ticketmaster")||o.includes("eventbrite")||o.includes("dice.fm")?"tickets":o.includes("instagram")?"instagram":o.includes("twitter")||o.includes("x.com")?"twitter":o.includes("tiktok")?"tiktok":o.includes("facebook")?"facebook":"external"}catch{return"external"}}function n(r){try{return new URL(r,window.location.origin).hostname!==t}catch{return!1}}function i(r,o){let d=e(r),k=Se(r),$t=k?.title||o?.textContent?.trim().substring(0,100)||"",Vt=k?.id||o?.id||o?.getAttribute("data-link-id")||void 0,Bt=k?.category;a("External link clicked:",{url:r,platform:d,linkText:$t,linkId:Vt,fromRegistry:!!k}),ft("page_link_click",{link_url:r,link_text:$t,link_id:Vt,platform:d,link_type:"external",...Bt&&{link_category:Bt},...k&&Object.fromEntries(Object.entries(k).filter(([mt])=>!["title","id","category"].includes(mt)).map(([mt,Ae])=>[`link_${mt}`,Ae]))})}let c=window.open;if(window.open=function(r,o,d){if(r){let k=r.toString();n(k)&&i(k)}return c.call(window,r,o,d)},a("window.open interception enabled (always on)"),s?.dataset.autoTrackLinks==="true"&&(document.addEventListener("click",r=>{let d=r.target.closest("a");if(d&&d.href&&n(d.href)){if(kt&&(Ct(d.href)||d.hasAttribute("download")))return;i(d.href,d)}},{capture:!0,passive:!0}),a("External link click listener enabled (opt-in)")),kt&&(document.addEventListener("click",r=>{let d=r.target.closest("a");d?.href&&(Ct(d.href)||d.hasAttribute("download"))&&oe(d.href,d)},{capture:!0,passive:!0}),a("File download tracking enabled")),Xt){let r=window.location.href;window.addEventListener("hashchange",()=>{let o=window.location.href;o!==r&&(r=o,setTimeout(()=>{F({title:document.title,url:o})},0))}),a("Hash routing tracking enabled")}document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"?(Ot(),ut(),j()):(lt(),it=!1)}),window.addEventListener("pagehide",()=>{ut(),j()}),window.addEventListener("beforeunload",()=>{ut(),j()})}if(window.balance?._version&&window.balance._version!==p){console.warn(`[artistPixel] Version conflict: ${window.balance._version} already loaded, skipping ${p}`);return}let gt=window.balance?.q||[];function Ft(){if(gt.length>0){a("Processing",gt.length,"queued commands");for(let t of gt){let[e,...n]=t;switch(e){case"track":ft(n[0],n[1]);break;case"identify":Ut(n[0],n[1]);break;case"page":F(n[0]);break;case"purchase":qt(n[0],n[1],n[2]);break;case"setConsent":Rt(n[0]);break;default:a("Unknown queued command:",e)}}}}let Nt={track:ft,identify:Ut,page:F,purchase:qt,getSessionId:()=>O,getVisitorId:()=>g,getFanIdHash:()=>b,getAttribution:()=>T,setConsent:Rt,getConsent:xe,hasConsent:Ie,registerLinks:Ce,_version:p};window.artistPixel=Nt,window.balance=Nt;function zt(){J&&!u&&new le({style:Kt,primaryColor:Yt,position:Jt})}let Ht=window.requestIdleCallback||(t=>setTimeout(t,1));document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{jt(),Ft(),Ht(()=>zt())}):(jt(),Ft(),Ht(()=>zt())),a("Pixel script loaded")})();})();
@@ -82,6 +82,12 @@ export interface BalanceProviderProps {
82
82
  export declare const BalanceContext: React.Context<BalanceContextValue>;
83
83
  export declare function BalanceProvider(props: BalanceProviderProps): JSX.Element;
84
84
 
85
+ // ArtistPixel aliases (preferred names)
86
+ export type ArtistPixelContextValue = BalanceContextValue;
87
+ export type ArtistPixelProviderProps = BalanceProviderProps;
88
+ export declare const ArtistPixelContext: React.Context<ArtistPixelContextValue>;
89
+ export declare function ArtistPixelProvider(props: ArtistPixelProviderProps): JSX.Element;
90
+
85
91
  // ============================================
86
92
  // Primary Hooks
87
93
  // ============================================
@@ -90,6 +96,11 @@ export declare function useBalance(): BalanceContextValue;
90
96
  export declare function useBalanceOptional(): BalanceContextValue | null;
91
97
  export declare function useBalanceReady(): boolean;
92
98
 
99
+ // ArtistPixel hook aliases (preferred names)
100
+ export declare function useArtistPixel(): ArtistPixelContextValue;
101
+ export declare function useArtistPixelOptional(): ArtistPixelContextValue | null;
102
+ export declare function useArtistPixelReady(): boolean;
103
+
93
104
  export interface UseBalanceConsentReturn {
94
105
  consent: ConsentPreferences | null;
95
106
  setConsent: (preferences: ConsentPreferences) => void;
@@ -100,11 +111,16 @@ export interface UseBalanceConsentReturn {
100
111
 
101
112
  export declare function useBalanceConsent(): UseBalanceConsentReturn;
102
113
 
114
+ // ArtistPixel consent alias
115
+ export type UseArtistPixelConsentReturn = UseBalanceConsentReturn;
116
+ export declare function useArtistPixelConsent(): UseArtistPixelConsentReturn;
117
+
103
118
  // ============================================
104
119
  // Components
105
120
  // ============================================
106
121
 
107
122
  export declare function BalanceAnalytics(): null;
123
+ export declare function ArtistPixelAnalytics(): null;
108
124
 
109
125
  // ============================================
110
126
  // SSR-safe Wrapper Functions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hifilabs/pixel",
3
- "version": "0.10.0",
3
+ "version": "0.11.1",
4
4
  "description": "artistPixel - Lightweight browser tracking script for artist fan analytics",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",