@hifilabs/pixel 0.1.3 → 0.1.5
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/index.js +13 -170
- package/dist/index.min.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,90 +1,5 @@
|
|
|
1
1
|
var BalancePixel = (() => {
|
|
2
|
-
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
9
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
10
|
-
}) : x)(function(x) {
|
|
11
|
-
if (typeof require !== "undefined")
|
|
12
|
-
return require.apply(this, arguments);
|
|
13
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
14
|
-
});
|
|
15
|
-
var __export = (target, all) => {
|
|
16
|
-
for (var name in all)
|
|
17
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
18
|
-
};
|
|
19
|
-
var __copyProps = (to, from, except, desc) => {
|
|
20
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
21
|
-
for (let key of __getOwnPropNames(from))
|
|
22
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
23
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
24
|
-
}
|
|
25
|
-
return to;
|
|
26
|
-
};
|
|
27
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
28
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
29
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
30
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
31
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
32
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
33
|
-
mod
|
|
34
|
-
));
|
|
35
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
36
|
-
|
|
37
|
-
// src/index.ts
|
|
38
|
-
var src_exports = {};
|
|
39
|
-
__export(src_exports, {
|
|
40
|
-
BalanceAnalytics: () => BalanceAnalytics,
|
|
41
|
-
getAttribution: () => getAttribution,
|
|
42
|
-
getConsent: () => getConsent,
|
|
43
|
-
getFanIdHash: () => getFanIdHash,
|
|
44
|
-
getSessionId: () => getSessionId,
|
|
45
|
-
hasConsent: () => hasConsent,
|
|
46
|
-
identify: () => identify,
|
|
47
|
-
page: () => page,
|
|
48
|
-
purchase: () => purchase,
|
|
49
|
-
setConsent: () => setConsent,
|
|
50
|
-
track: () => track
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// src/react/BalanceAnalytics.tsx
|
|
54
|
-
var import_react = __toESM(__require("react"));
|
|
55
|
-
var import_navigation = __require("next/navigation");
|
|
56
|
-
function BalanceAnalyticsInner() {
|
|
57
|
-
const pathname = (0, import_navigation.usePathname)();
|
|
58
|
-
const searchParams = (0, import_navigation.useSearchParams)();
|
|
59
|
-
const isFirstRender = (0, import_react.useRef)(true);
|
|
60
|
-
const lastTrackedPath = (0, import_react.useRef)(null);
|
|
61
|
-
(0, import_react.useEffect)(() => {
|
|
62
|
-
if (typeof window === "undefined" || !window.balance)
|
|
63
|
-
return;
|
|
64
|
-
const currentPath = pathname + (searchParams?.toString() || "");
|
|
65
|
-
if (lastTrackedPath.current === currentPath) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
if (isFirstRender.current) {
|
|
69
|
-
isFirstRender.current = false;
|
|
70
|
-
if (window._balanceInitialPageviewFired) {
|
|
71
|
-
lastTrackedPath.current = currentPath;
|
|
72
|
-
console.log("[BalanceAnalytics] Skipping initial pageview (script already fired)");
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
const url = window.location.href;
|
|
77
|
-
const title = document.title;
|
|
78
|
-
lastTrackedPath.current = currentPath;
|
|
79
|
-
window.balance.page({ url, title });
|
|
80
|
-
}, [pathname, searchParams]);
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
function BalanceAnalytics() {
|
|
84
|
-
return /* @__PURE__ */ import_react.default.createElement(import_react.Suspense, { fallback: null }, /* @__PURE__ */ import_react.default.createElement(BalanceAnalyticsInner, null));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// src/index.ts
|
|
2
|
+
// src/browser.ts
|
|
88
3
|
(function() {
|
|
89
4
|
function parseUserAgent(ua) {
|
|
90
5
|
let device_type = "desktop";
|
|
@@ -313,7 +228,7 @@ var BalancePixel = (() => {
|
|
|
313
228
|
} catch (e) {
|
|
314
229
|
}
|
|
315
230
|
}
|
|
316
|
-
function
|
|
231
|
+
function setConsent(preferences) {
|
|
317
232
|
const previousConsent = consent;
|
|
318
233
|
consent = preferences;
|
|
319
234
|
try {
|
|
@@ -340,10 +255,10 @@ var BalancePixel = (() => {
|
|
|
340
255
|
});
|
|
341
256
|
enqueueEvent(event);
|
|
342
257
|
}
|
|
343
|
-
function
|
|
258
|
+
function getConsent() {
|
|
344
259
|
return consent;
|
|
345
260
|
}
|
|
346
|
-
function
|
|
261
|
+
function hasConsent(type) {
|
|
347
262
|
return consent?.[type] === true;
|
|
348
263
|
}
|
|
349
264
|
async function hashEmail(email) {
|
|
@@ -506,7 +421,7 @@ var BalancePixel = (() => {
|
|
|
506
421
|
});
|
|
507
422
|
enqueueEvent(event);
|
|
508
423
|
}
|
|
509
|
-
function
|
|
424
|
+
function track(eventName, properties = {}) {
|
|
510
425
|
const event = buildEvent({
|
|
511
426
|
event_name: "custom",
|
|
512
427
|
metadata: {
|
|
@@ -516,7 +431,7 @@ var BalancePixel = (() => {
|
|
|
516
431
|
});
|
|
517
432
|
enqueueEvent(event);
|
|
518
433
|
}
|
|
519
|
-
async function
|
|
434
|
+
async function identify(email, traits = {}) {
|
|
520
435
|
try {
|
|
521
436
|
if (consent && consent.analytics === false) {
|
|
522
437
|
log("Identify skipped - user declined analytics consent");
|
|
@@ -551,7 +466,7 @@ var BalancePixel = (() => {
|
|
|
551
466
|
console.error("[BALANCE Pixel] Failed to identify:", error);
|
|
552
467
|
}
|
|
553
468
|
}
|
|
554
|
-
function
|
|
469
|
+
function purchase(revenue, currency = "USD", properties = {}) {
|
|
555
470
|
const event = buildEvent({
|
|
556
471
|
event_name: "purchase",
|
|
557
472
|
metadata: {
|
|
@@ -618,16 +533,16 @@ var BalancePixel = (() => {
|
|
|
618
533
|
});
|
|
619
534
|
}
|
|
620
535
|
window.balance = {
|
|
621
|
-
track
|
|
622
|
-
identify
|
|
536
|
+
track,
|
|
537
|
+
identify,
|
|
623
538
|
page: trackPageView,
|
|
624
|
-
purchase
|
|
539
|
+
purchase,
|
|
625
540
|
getSessionId: () => sessionId,
|
|
626
541
|
getFanIdHash: () => fanIdHash,
|
|
627
542
|
getAttribution: () => attribution,
|
|
628
|
-
setConsent
|
|
629
|
-
getConsent
|
|
630
|
-
hasConsent
|
|
543
|
+
setConsent,
|
|
544
|
+
getConsent,
|
|
545
|
+
hasConsent
|
|
631
546
|
};
|
|
632
547
|
if (document.readyState === "loading") {
|
|
633
548
|
document.addEventListener("DOMContentLoaded", init);
|
|
@@ -636,76 +551,4 @@ var BalancePixel = (() => {
|
|
|
636
551
|
}
|
|
637
552
|
log("Pixel script loaded");
|
|
638
553
|
})();
|
|
639
|
-
var track = (eventName, properties) => {
|
|
640
|
-
if (typeof window === "undefined")
|
|
641
|
-
return;
|
|
642
|
-
if (window.balance) {
|
|
643
|
-
window.balance.track(eventName, properties);
|
|
644
|
-
} else {
|
|
645
|
-
console.warn("[Balance Pixel] track() called before pixel initialized:", eventName);
|
|
646
|
-
}
|
|
647
|
-
};
|
|
648
|
-
var identify = (email, traits) => {
|
|
649
|
-
if (typeof window === "undefined")
|
|
650
|
-
return Promise.resolve();
|
|
651
|
-
if (window.balance) {
|
|
652
|
-
return window.balance.identify(email, traits);
|
|
653
|
-
} else {
|
|
654
|
-
console.warn("[Balance Pixel] identify() called before pixel initialized");
|
|
655
|
-
return Promise.resolve();
|
|
656
|
-
}
|
|
657
|
-
};
|
|
658
|
-
var page = (options) => {
|
|
659
|
-
if (typeof window === "undefined")
|
|
660
|
-
return;
|
|
661
|
-
if (window.balance) {
|
|
662
|
-
window.balance.page(options);
|
|
663
|
-
} else {
|
|
664
|
-
console.warn("[Balance Pixel] page() called before pixel initialized");
|
|
665
|
-
}
|
|
666
|
-
};
|
|
667
|
-
var purchase = (revenue, currency, properties) => {
|
|
668
|
-
if (typeof window === "undefined")
|
|
669
|
-
return;
|
|
670
|
-
if (window.balance) {
|
|
671
|
-
window.balance.purchase(revenue, currency, properties);
|
|
672
|
-
} else {
|
|
673
|
-
console.warn("[Balance Pixel] purchase() called before pixel initialized");
|
|
674
|
-
}
|
|
675
|
-
};
|
|
676
|
-
var getSessionId = () => {
|
|
677
|
-
if (typeof window === "undefined")
|
|
678
|
-
return null;
|
|
679
|
-
return window.balance?.getSessionId() ?? null;
|
|
680
|
-
};
|
|
681
|
-
var getFanIdHash = () => {
|
|
682
|
-
if (typeof window === "undefined")
|
|
683
|
-
return null;
|
|
684
|
-
return window.balance?.getFanIdHash() ?? null;
|
|
685
|
-
};
|
|
686
|
-
var getAttribution = () => {
|
|
687
|
-
if (typeof window === "undefined")
|
|
688
|
-
return {};
|
|
689
|
-
return window.balance?.getAttribution() ?? {};
|
|
690
|
-
};
|
|
691
|
-
var setConsent = (preferences) => {
|
|
692
|
-
if (typeof window === "undefined")
|
|
693
|
-
return;
|
|
694
|
-
if (window.balance) {
|
|
695
|
-
window.balance.setConsent(preferences);
|
|
696
|
-
} else {
|
|
697
|
-
console.warn("[Balance Pixel] setConsent() called before pixel initialized");
|
|
698
|
-
}
|
|
699
|
-
};
|
|
700
|
-
var getConsent = () => {
|
|
701
|
-
if (typeof window === "undefined")
|
|
702
|
-
return null;
|
|
703
|
-
return window.balance?.getConsent() ?? null;
|
|
704
|
-
};
|
|
705
|
-
var hasConsent = (type) => {
|
|
706
|
-
if (typeof window === "undefined")
|
|
707
|
-
return false;
|
|
708
|
-
return window.balance?.hasConsent(type) ?? false;
|
|
709
|
-
};
|
|
710
|
-
return __toCommonJS(src_exports);
|
|
711
554
|
})();
|
package/dist/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var BalancePixel=(()=>{var Ae=Object.create;var T=Object.defineProperty;var ke=Object.getOwnPropertyDescriptor;var Pe=Object.getOwnPropertyNames;var Ee=Object.getPrototypeOf,Te=Object.prototype.hasOwnProperty;var Z=(i=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(i,{get:(r,s)=>(typeof require<"u"?require:r)[s]}):i)(function(i){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+i+'" is not supported')});var Ce=(i,r)=>{for(var s in r)T(i,s,{get:r[s],enumerable:!0})},ee=(i,r,s,l)=>{if(r&&typeof r=="object"||typeof r=="function")for(let d of Pe(r))!Te.call(i,d)&&d!==s&&T(i,d,{get:()=>r[d],enumerable:!(l=ke(r,d))||l.enumerable});return i};var De=(i,r,s)=>(s=i!=null?Ae(Ee(i)):{},ee(r||!i||!i.__esModule?T(s,"default",{value:i,enumerable:!0}):s,i)),Oe=i=>ee(T({},"__esModule",{value:!0}),i);var Je={};Ce(Je,{BalanceAnalytics:()=>te,getAttribution:()=>ze,getConsent:()=>Me,getFanIdHash:()=>He,getSessionId:()=>Fe,hasConsent:()=>Ke,identify:()=>Re,page:()=>Ue,purchase:()=>Be,setConsent:()=>je,track:()=>Ne});var u=De(Z("react")),C=Z("next/navigation");function Le(){let i=(0,C.usePathname)(),r=(0,C.useSearchParams)(),s=(0,u.useRef)(!0),l=(0,u.useRef)(null);return(0,u.useEffect)(()=>{if(typeof window>"u"||!window.balance)return;let d=i+(r?.toString()||"");if(l.current===d)return;if(s.current&&(s.current=!1,window._balanceInitialPageviewFired)){l.current=d,console.log("[BalanceAnalytics] Skipping initial pageview (script already fired)");return}let v=window.location.href,_=document.title;l.current=d,window.balance.page({url:v,title:_})},[i,r]),null}function te(){return u.default.createElement(u.Suspense,{fallback:null},u.default.createElement(Le,null))}(function(){function i(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 r=null;function s(){if(!r)try{r=i(navigator.userAgent)}catch{r={device_type:"desktop",browser:"Unknown",os:"Unknown"}}return r}let l=document.currentScript,d=l?.dataset.artistId,v=l?.dataset.projectId,_=l?.dataset.emulator==="true",ne=l?.dataset.debug==="true",D=parseInt(l?.dataset.heartbeatInterval||"30000",10),z=l?.dataset.heartbeat!=="false",j=l?.dataset.source;function ie(){if(j)return j;let e=typeof window.dataLayer<"u"&&Array.isArray(window.dataLayer),t=typeof window.gtag=="function";return e&&t?"gtm":"pixel"}let A="pixel";if(!d){console.error("[BALANCE Pixel] Error: data-artist-id attribute is required");return}let M="session_id",O="session_timestamp",K="attribution",J="fan_id_hash",Y="balance_consent",re=60*60*1e3,L="balance_",N=_?"http://localhost:5001/artist-os-distro/us-central1/pixelEndpoint":"https://us-central1-artist-os-distro.cloudfunctions.net/pixelEndpoint",k=null,f=null,c=null,m={},g=[],R=null,p="session",w=null,ae=0,U=0,y=0,x=!0,oe=2*60*1e3,q=Date.now(),S=!1,a=(...e)=>{ne&&console.log("[BALANCE Pixel]",...e)};function G(){try{return p==="local"?localStorage:sessionStorage}catch{return null}}function P(e){let t=G();if(!t)return null;try{let n=L+e,o=t.getItem(n);if(!o&&p==="session")try{o=localStorage.getItem(n)}catch{}return o}catch{return null}}function I(e,t){let n=G();if(n)try{n.setItem(L+e,t)}catch{}}function B(){if(p!=="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(L)&&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);p="local",a(`Storage tier upgraded, migrated ${e.length} items`)}catch(e){console.error("[BALANCE Pixel] Storage migration failed:",e)}}}function $(){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 se(){try{let e=P(M),t=P(O);if(e&&t&&Date.now()-parseInt(t,10)<re)return I(O,Date.now().toString()),e;let n=$();return I(M,n),I(O,Date.now().toString()),n}catch{return $()}}function ce(){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 le(){try{let e=P(K);if(e){m=JSON.parse(e),a("Loaded attribution:",m);return}let t=ce();Object.keys(t).length>0&&(m=t,I(K,JSON.stringify(t)),a("Captured attribution:",m))}catch{}}function de(){try{f=P(J)}catch{}}function ue(){try{let e=localStorage.getItem(Y);e&&(c=JSON.parse(e).preferences||null,a("Loaded consent:",c))}catch{}}function fe(e){let t=c;c=e;try{let o={preferences:e,method:"explicit",version:1};localStorage.setItem(Y,JSON.stringify(o)),a("Consent saved:",e)}catch(o){console.error("[BALANCE Pixel] Could not save consent:",o)}e.analytics===!0&&B();let n=b({event_name:"consent_updated",metadata:{consent_preferences:e,consent_method:"explicit",previous_consent:t||void 0}});h(n)}function ge(){return c}function pe(e){return c?.[e]===!0}async function me(e){let t=e.toLowerCase().trim(),o=new TextEncoder().encode(t),H=await crypto.subtle.digest("SHA-256",o);return Array.from(new Uint8Array(H)).map(_e=>_e.toString(16).padStart(2,"0")).join("")}function b(e){let t=s(),n={artist_id:d,fan_session_id:k,fan_id_hash:f||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:A,...e,...m};return v&&!e.projectId&&(n.projectId=v),n}function h(e){g.push(e),a("Event queued:",e.event_name,"(queue:",g.length,")"),g.length>=10&&E()}async function E(){if(g.length===0)return;let e=[...g];g=[],a("Flushing",e.length,"events to",N);try{let t=await fetch(N,{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){console.error("[BALANCE Pixel] Failed to send events:",t),g.length<50&&g.push(...e)}}function we(){R&&clearInterval(R),R=window.setInterval(()=>{g.length>0&&E()},5e3)}function F(){y||(ae=Date.now()),y=Date.now(),x=!0,a("Active time tracking started/resumed")}function W(){y&&x&&(U+=Date.now()-y),x=!1,a("Active time tracking paused, accumulated:",U,"ms")}function ye(){let e=U;return x&&y&&(e+=Date.now()-y),e}function be(){q=Date.now(),S&&(S=!1,F(),a("User returned from idle"))}function V(){if(document.visibilityState==="hidden"){a("Skipping heartbeat - tab hidden");return}if(Date.now()-q>oe){S||(S=!0,W(),a("User idle - pausing heartbeat"));return}let e=ye(),t=Math.round(e/1e3),n=b({event_name:"engagement_heartbeat",metadata:{time_on_page_seconds:t,time_on_page_ms:e,heartbeat_interval_ms:D,is_active:x&&!S}});h(n),a("Heartbeat sent:",t,"seconds active")}function he(){if(!z){a('Heartbeat disabled via data-heartbeat="false"');return}w&&clearInterval(w),F(),w=window.setInterval(()=>{V()},D),a("Heartbeat started with interval:",D,"ms")}function ve(){w&&(clearInterval(w),w=null),z&&(V(),a("Heartbeat stopped, final time sent"))}function Q(e={}){let t=b({event_name:"pageview",page_title:e.title||document.title,source_url:e.url||window.location.href});h(t)}function xe(e,t={}){let n=b({event_name:"custom",metadata:{event_type:e,...t}});h(n)}async function Se(e,t={}){try{if(c&&c.analytics===!1){a("Identify skipped - user declined analytics consent");return}f=await me(e),c?.analytics===!0&&B(),I(J,f);let n=e.split("@"),o=n[0].charAt(0)+"***@"+(n[1]||"");a("Fan identified:",{name:t.name||"(no name)",email:o,hash:f.substring(0,16)+"...",traits:t,storageTier:p});let H=b({event_name:"identify",fan_id_hash:f,metadata:{email_sha256:f,traits:t,consent_preferences:c||void 0,storage_tier:p}});h(H)}catch(n){console.error("[BALANCE Pixel] Failed to identify:",n)}}function Ie(e,t="USD",n={}){let o=b({event_name:"purchase",metadata:{revenue:e,currency:t,...n}});h(o)}function X(){A=ie(),a("Tracking source detected:",A),ue(),c?.analytics===!0?(p="local",a("Storage tier: local (analytics consent granted)")):(p="session",a("Storage tier: session (privacy by default)")),k=se(),de(),c||(c={analytics:!0,marketing:!0,personalization:!0,timestamp:new Date().toISOString()},a("Default consent enabled (all tracking):",c),B()),le(),we(),a("Initialized",{artistId:d,projectId:v||"(none - will track to all projects)",sessionId:k,fanIdHash:f,consent:c,storageTier:p,trackingSource:A,useEmulator:_,endpoint:N}),window._balanceInitialPageviewFired=!0,Q(),he(),["mousemove","keydown","scroll","touchstart"].forEach(e=>{document.addEventListener(e,be,{passive:!0})}),window.addEventListener("beforeunload",()=>{ve(),E()}),document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"?(W(),E()):F()})}window.balance={track:xe,identify:Se,page:Q,purchase:Ie,getSessionId:()=>k,getFanIdHash:()=>f,getAttribution:()=>m,setConsent:fe,getConsent:ge,hasConsent:pe},document.readyState==="loading"?document.addEventListener("DOMContentLoaded",X):X(),a("Pixel script loaded")})();var Ne=(i,r)=>{typeof window>"u"||(window.balance?window.balance.track(i,r):console.warn("[Balance Pixel] track() called before pixel initialized:",i))},Re=(i,r)=>typeof window>"u"?Promise.resolve():window.balance?window.balance.identify(i,r):(console.warn("[Balance Pixel] identify() called before pixel initialized"),Promise.resolve()),Ue=i=>{typeof window>"u"||(window.balance?window.balance.page(i):console.warn("[Balance Pixel] page() called before pixel initialized"))},Be=(i,r,s)=>{typeof window>"u"||(window.balance?window.balance.purchase(i,r,s):console.warn("[Balance Pixel] purchase() called before pixel initialized"))},Fe=()=>typeof window>"u"?null:window.balance?.getSessionId()??null,He=()=>typeof window>"u"?null:window.balance?.getFanIdHash()??null,ze=()=>typeof window>"u"?{}:window.balance?.getAttribution()??{},je=i=>{typeof window>"u"||(window.balance?window.balance.setConsent(i):console.warn("[Balance Pixel] setConsent() called before pixel initialized"))},Me=()=>typeof window>"u"?null:window.balance?.getConsent()??null,Ke=i=>typeof window>"u"?!1:window.balance?.hasConsent(i)??!1;return Oe(Je);})();
|
|
1
|
+
var BalancePixel=(()=>{(function(){function $(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 i="Unknown";return/iphone|ipad/i.test(e)?i="iOS":/android/i.test(e)?i="Android":/windows/i.test(e)?i="Windows":/mac os/i.test(e)?i="macOS":/linux/i.test(e)?i="Linux":/cros/i.test(e)&&(i="ChromeOS"),{device_type:t,browser:n,os:i}}let v=null;function W(){if(!v)try{v=$(navigator.userAgent)}catch{v={device_type:"desktop",browser:"Unknown",os:"Unknown"}}return v}let l=document.currentScript,w=l?.dataset.artistId,x=l?.dataset.projectId,L=l?.dataset.emulator==="true",V=l?.dataset.debug==="true",A=parseInt(l?.dataset.heartbeatInterval||"30000",10),U=l?.dataset.heartbeat!=="false",R=l?.dataset.source;function Q(){if(R)return R;let e=typeof window.dataLayer<"u"&&Array.isArray(window.dataLayer),t=typeof window.gtag=="function";return e&&t?"gtm":"pixel"}let b="pixel";if(!w){console.error("[BALANCE Pixel] Error: data-artist-id attribute is required");return}let H="session_id",E="session_timestamp",F="attribution",B="fan_id_hash",j="balance_consent",X=60*60*1e3,T="balance_",k=L?"http://localhost:5001/artist-os-distro/us-central1/pixelEndpoint":"https://us-central1-artist-os-distro.cloudfunctions.net/pixelEndpoint",S=null,s=null,a=null,d={},o=[],P=null,c="session",u=null,Z=0,C=0,g=0,p=!0,ee=2*60*1e3,M=Date.now(),h=!1,r=(...e)=>{V&&console.log("[BALANCE Pixel]",...e)};function z(){try{return c==="local"?localStorage:sessionStorage}catch{return null}}function _(e){let t=z();if(!t)return null;try{let n=T+e,i=t.getItem(n);if(!i&&c==="session")try{i=localStorage.getItem(n)}catch{}return i}catch{return null}}function y(e,t){let n=z();if(n)try{n.setItem(T+e,t)}catch{}}function D(){if(c!=="local"){r("Upgrading storage tier: session -> local");try{let e=[];for(let t=0;t<sessionStorage.length;t++){let n=sessionStorage.key(t);n?.startsWith(T)&&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);c="local",r(`Storage tier upgraded, migrated ${e.length} items`)}catch(e){console.error("[BALANCE Pixel] Storage migration failed:",e)}}}function K(){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 te(){try{let e=_(H),t=_(E);if(e&&t&&Date.now()-parseInt(t,10)<X)return y(E,Date.now().toString()),e;let n=K();return y(H,n),y(E,Date.now().toString()),n}catch{return K()}}function ne(){let e=new URLSearchParams(window.location.search),t={};return["source","medium","campaign","content","term"].forEach(n=>{let i=e.get(`utm_${n}`);i&&(t[`utm_${n}`]=i)}),t}function re(){try{let e=_(F);if(e){d=JSON.parse(e),r("Loaded attribution:",d);return}let t=ne();Object.keys(t).length>0&&(d=t,y(F,JSON.stringify(t)),r("Captured attribution:",d))}catch{}}function ie(){try{s=_(B)}catch{}}function ae(){try{let e=localStorage.getItem(j);e&&(a=JSON.parse(e).preferences||null,r("Loaded consent:",a))}catch{}}function se(e){let t=a;a=e;try{let i={preferences:e,method:"explicit",version:1};localStorage.setItem(j,JSON.stringify(i)),r("Consent saved:",e)}catch(i){console.error("[BALANCE Pixel] Could not save consent:",i)}e.analytics===!0&&D();let n=f({event_name:"consent_updated",metadata:{consent_preferences:e,consent_method:"explicit",previous_consent:t||void 0}});m(n)}function oe(){return a}function ce(e){return a?.[e]===!0}async function le(e){let t=e.toLowerCase().trim(),i=new TextEncoder().encode(t),N=await crypto.subtle.digest("SHA-256",i);return Array.from(new Uint8Array(N)).map(ve=>ve.toString(16).padStart(2,"0")).join("")}function f(e){let t=W(),n={artist_id:w,fan_session_id:S,fan_id_hash:s||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:b,...e,...d};return x&&!e.projectId&&(n.projectId=x),n}function m(e){o.push(e),r("Event queued:",e.event_name,"(queue:",o.length,")"),o.length>=10&&I()}async function I(){if(o.length===0)return;let e=[...o];o=[],r("Flushing",e.length,"events to",k);try{let t=await fetch(k,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({events:e}),keepalive:!0});if(!t.ok)throw new Error(`HTTP ${t.status}`);r("Events sent successfully")}catch(t){console.error("[BALANCE Pixel] Failed to send events:",t),o.length<50&&o.push(...e)}}function de(){P&&clearInterval(P),P=window.setInterval(()=>{o.length>0&&I()},5e3)}function O(){g||(Z=Date.now()),g=Date.now(),p=!0,r("Active time tracking started/resumed")}function J(){g&&p&&(C+=Date.now()-g),p=!1,r("Active time tracking paused, accumulated:",C,"ms")}function ue(){let e=C;return p&&g&&(e+=Date.now()-g),e}function ge(){M=Date.now(),h&&(h=!1,O(),r("User returned from idle"))}function Y(){if(document.visibilityState==="hidden"){r("Skipping heartbeat - tab hidden");return}if(Date.now()-M>ee){h||(h=!0,J(),r("User idle - pausing heartbeat"));return}let e=ue(),t=Math.round(e/1e3),n=f({event_name:"engagement_heartbeat",metadata:{time_on_page_seconds:t,time_on_page_ms:e,heartbeat_interval_ms:A,is_active:p&&!h}});m(n),r("Heartbeat sent:",t,"seconds active")}function fe(){if(!U){r('Heartbeat disabled via data-heartbeat="false"');return}u&&clearInterval(u),O(),u=window.setInterval(()=>{Y()},A),r("Heartbeat started with interval:",A,"ms")}function me(){u&&(clearInterval(u),u=null),U&&(Y(),r("Heartbeat stopped, final time sent"))}function q(e={}){let t=f({event_name:"pageview",page_title:e.title||document.title,source_url:e.url||window.location.href});m(t)}function pe(e,t={}){let n=f({event_name:"custom",metadata:{event_type:e,...t}});m(n)}async function he(e,t={}){try{if(a&&a.analytics===!1){r("Identify skipped - user declined analytics consent");return}s=await le(e),a?.analytics===!0&&D(),y(B,s);let n=e.split("@"),i=n[0].charAt(0)+"***@"+(n[1]||"");r("Fan identified:",{name:t.name||"(no name)",email:i,hash:s.substring(0,16)+"...",traits:t,storageTier:c});let N=f({event_name:"identify",fan_id_hash:s,metadata:{email_sha256:s,traits:t,consent_preferences:a||void 0,storage_tier:c}});m(N)}catch(n){console.error("[BALANCE Pixel] Failed to identify:",n)}}function ye(e,t="USD",n={}){let i=f({event_name:"purchase",metadata:{revenue:e,currency:t,...n}});m(i)}function G(){b=Q(),r("Tracking source detected:",b),ae(),a?.analytics===!0?(c="local",r("Storage tier: local (analytics consent granted)")):(c="session",r("Storage tier: session (privacy by default)")),S=te(),ie(),a||(a={analytics:!0,marketing:!0,personalization:!0,timestamp:new Date().toISOString()},r("Default consent enabled (all tracking):",a),D()),re(),de(),r("Initialized",{artistId:w,projectId:x||"(none - will track to all projects)",sessionId:S,fanIdHash:s,consent:a,storageTier:c,trackingSource:b,useEmulator:L,endpoint:k}),window._balanceInitialPageviewFired=!0,q(),fe(),["mousemove","keydown","scroll","touchstart"].forEach(e=>{document.addEventListener(e,ge,{passive:!0})}),window.addEventListener("beforeunload",()=>{me(),I()}),document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"?(J(),I()):O()})}window.balance={track:pe,identify:he,page:q,purchase:ye,getSessionId:()=>S,getFanIdHash:()=>s,getAttribution:()=>d,setConsent:se,getConsent:oe,hasConsent:ce},document.readyState==="loading"?document.addEventListener("DOMContentLoaded",G):G(),r("Pixel script loaded")})();})();
|