@hifilabs/pixel 0.0.7 → 0.0.9
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.esm.d.ts +59 -0
- package/dist/index.esm.js +445 -6
- package/dist/index.js +120 -20
- package/dist/index.min.js +1 -1
- package/package.json +2 -2
package/dist/index.esm.d.ts
CHANGED
|
@@ -1 +1,60 @@
|
|
|
1
1
|
export declare function BalanceAnalytics(): null;
|
|
2
|
+
|
|
3
|
+
// SSR-safe wrapper function type declarations
|
|
4
|
+
export declare const track: (eventName: string, properties?: Record<string, any>) => void;
|
|
5
|
+
export declare const identify: (email: string, traits?: Record<string, any>) => Promise<void>;
|
|
6
|
+
export declare const page: (options?: { title?: string; url?: string }) => void;
|
|
7
|
+
export declare const purchase: (revenue: number, currency?: string, properties?: Record<string, any>) => void;
|
|
8
|
+
export declare const getSessionId: () => string | null;
|
|
9
|
+
export declare const getFanIdHash: () => string | null;
|
|
10
|
+
export declare const getAttribution: () => Record<string, string>;
|
|
11
|
+
export declare const setConsent: (preferences: {
|
|
12
|
+
analytics: boolean;
|
|
13
|
+
marketing: boolean;
|
|
14
|
+
personalization: boolean;
|
|
15
|
+
timestamp: string;
|
|
16
|
+
ip_address?: string;
|
|
17
|
+
user_agent?: string;
|
|
18
|
+
}) => void;
|
|
19
|
+
export declare const getConsent: () => any;
|
|
20
|
+
export declare const hasConsent: (type: 'analytics' | 'marketing' | 'personalization') => boolean;
|
|
21
|
+
|
|
22
|
+
// useBalanceIdentify hook - consent-aware identify wrapper
|
|
23
|
+
export declare function useBalanceIdentify(): {
|
|
24
|
+
/**
|
|
25
|
+
* Identify a user with BALANCE pixel.
|
|
26
|
+
* Handles consent checks, queuing, and storage tier automatically.
|
|
27
|
+
* @param email - User's email address
|
|
28
|
+
* @param traits - Optional additional user traits
|
|
29
|
+
* @returns true if identify was called immediately, false if queued or blocked
|
|
30
|
+
*/
|
|
31
|
+
identify: (email: string, traits?: Record<string, unknown>) => boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Check if analytics consent is currently granted
|
|
34
|
+
*/
|
|
35
|
+
hasAnalyticsConsent: () => boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Storage types
|
|
39
|
+
export type StorageTier = 'session' | 'local';
|
|
40
|
+
|
|
41
|
+
export interface StorageConfig {
|
|
42
|
+
prefix: string;
|
|
43
|
+
tier: StorageTier;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// StorageManager class for tiered storage
|
|
47
|
+
export declare class StorageManager {
|
|
48
|
+
constructor(config?: Partial<StorageConfig>);
|
|
49
|
+
getTier(): StorageTier;
|
|
50
|
+
upgradeTier(newTier: StorageTier): void;
|
|
51
|
+
downgradeTier(newTier: StorageTier): void;
|
|
52
|
+
getItem(key: string): string | null;
|
|
53
|
+
setItem(key: string, value: string): void;
|
|
54
|
+
removeItem(key: string): void;
|
|
55
|
+
getJSON<T>(key: string): T | null;
|
|
56
|
+
setJSON<T>(key: string, value: T): void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export declare function getStorageManager(): StorageManager;
|
|
60
|
+
export declare function initStorageWithConsent(hasAnalyticsConsent: boolean): StorageManager;
|
package/dist/index.esm.js
CHANGED
|
@@ -1,22 +1,461 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
+
var __publicField = (obj, key, value) => {
|
|
5
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
|
+
return value;
|
|
7
|
+
};
|
|
8
|
+
|
|
2
9
|
// src/react/BalanceAnalytics.tsx
|
|
3
|
-
import React, { useEffect, Suspense } from "react";
|
|
10
|
+
import React, { useEffect, useRef, Suspense } from "react";
|
|
4
11
|
import { usePathname, useSearchParams } from "next/navigation";
|
|
5
12
|
function BalanceAnalyticsInner() {
|
|
6
13
|
const pathname = usePathname();
|
|
7
14
|
const searchParams = useSearchParams();
|
|
15
|
+
const isFirstRender = useRef(true);
|
|
16
|
+
const lastTrackedPath = useRef(null);
|
|
8
17
|
useEffect(() => {
|
|
9
|
-
if (typeof window
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
if (typeof window === "undefined" || !window.balance)
|
|
19
|
+
return;
|
|
20
|
+
const currentPath = pathname + (searchParams?.toString() || "");
|
|
21
|
+
if (lastTrackedPath.current === currentPath) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (isFirstRender.current) {
|
|
25
|
+
isFirstRender.current = false;
|
|
26
|
+
if (window._balanceInitialPageviewFired) {
|
|
27
|
+
lastTrackedPath.current = currentPath;
|
|
28
|
+
console.log("[BalanceAnalytics] Skipping initial pageview (script already fired)");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
13
31
|
}
|
|
32
|
+
const url = window.location.href;
|
|
33
|
+
const title = document.title;
|
|
34
|
+
lastTrackedPath.current = currentPath;
|
|
35
|
+
window.balance.page({ url, title });
|
|
14
36
|
}, [pathname, searchParams]);
|
|
15
37
|
return null;
|
|
16
38
|
}
|
|
17
39
|
function BalanceAnalytics() {
|
|
18
40
|
return /* @__PURE__ */ React.createElement(Suspense, { fallback: null }, /* @__PURE__ */ React.createElement(BalanceAnalyticsInner, null));
|
|
19
41
|
}
|
|
42
|
+
|
|
43
|
+
// src/react/useBalanceIdentify.ts
|
|
44
|
+
import { useCallback, useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
45
|
+
|
|
46
|
+
// src/storage/StorageManager.ts
|
|
47
|
+
var DEFAULT_PREFIX = "balance_";
|
|
48
|
+
var StorageManager = class {
|
|
49
|
+
constructor(config) {
|
|
50
|
+
__publicField(this, "prefix");
|
|
51
|
+
__publicField(this, "currentTier");
|
|
52
|
+
this.prefix = config?.prefix ?? DEFAULT_PREFIX;
|
|
53
|
+
this.currentTier = config?.tier ?? "session";
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the appropriate storage based on current tier
|
|
57
|
+
*/
|
|
58
|
+
getStorage() {
|
|
59
|
+
if (typeof window === "undefined")
|
|
60
|
+
return null;
|
|
61
|
+
try {
|
|
62
|
+
return this.currentTier === "local" ? localStorage : sessionStorage;
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get current storage tier
|
|
69
|
+
*/
|
|
70
|
+
getTier() {
|
|
71
|
+
return this.currentTier;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Upgrade storage tier (e.g., when user gives consent)
|
|
75
|
+
* Automatically migrates data from sessionStorage to localStorage
|
|
76
|
+
*/
|
|
77
|
+
upgradeTier(newTier) {
|
|
78
|
+
if (typeof window === "undefined")
|
|
79
|
+
return;
|
|
80
|
+
if (this.currentTier === newTier)
|
|
81
|
+
return;
|
|
82
|
+
const oldTier = this.currentTier;
|
|
83
|
+
if (oldTier === "session" && newTier === "local") {
|
|
84
|
+
this.migrateToLocal();
|
|
85
|
+
}
|
|
86
|
+
this.currentTier = newTier;
|
|
87
|
+
console.log(`[StorageManager] Upgraded tier: ${oldTier} -> ${newTier}`);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Downgrade storage tier (e.g., when user revokes consent)
|
|
91
|
+
* Clears localStorage data and falls back to sessionStorage
|
|
92
|
+
*/
|
|
93
|
+
downgradeTier(newTier) {
|
|
94
|
+
if (typeof window === "undefined")
|
|
95
|
+
return;
|
|
96
|
+
if (this.currentTier === newTier)
|
|
97
|
+
return;
|
|
98
|
+
const oldTier = this.currentTier;
|
|
99
|
+
if (oldTier === "local" && newTier === "session") {
|
|
100
|
+
this.clearLocalStorage();
|
|
101
|
+
}
|
|
102
|
+
this.currentTier = newTier;
|
|
103
|
+
console.log(`[StorageManager] Downgraded tier: ${oldTier} -> ${newTier}`);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Migrate all prefixed data from sessionStorage to localStorage
|
|
107
|
+
*/
|
|
108
|
+
migrateToLocal() {
|
|
109
|
+
if (typeof window === "undefined")
|
|
110
|
+
return;
|
|
111
|
+
try {
|
|
112
|
+
const keysToMigrate = [];
|
|
113
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
114
|
+
const key = sessionStorage.key(i);
|
|
115
|
+
if (key?.startsWith(this.prefix)) {
|
|
116
|
+
keysToMigrate.push(key);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const key of keysToMigrate) {
|
|
120
|
+
const value = sessionStorage.getItem(key);
|
|
121
|
+
if (value) {
|
|
122
|
+
localStorage.setItem(key, value);
|
|
123
|
+
console.log(`[StorageManager] Migrated: ${key}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
for (const key of keysToMigrate) {
|
|
127
|
+
sessionStorage.removeItem(key);
|
|
128
|
+
}
|
|
129
|
+
console.log(`[StorageManager] Migration complete: ${keysToMigrate.length} items`);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error("[StorageManager] Migration failed:", error);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Clear all prefixed data from localStorage
|
|
136
|
+
*/
|
|
137
|
+
clearLocalStorage() {
|
|
138
|
+
if (typeof window === "undefined")
|
|
139
|
+
return;
|
|
140
|
+
try {
|
|
141
|
+
const keysToRemove = [];
|
|
142
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
143
|
+
const key = localStorage.key(i);
|
|
144
|
+
if (key?.startsWith(this.prefix)) {
|
|
145
|
+
keysToRemove.push(key);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
for (const key of keysToRemove) {
|
|
149
|
+
localStorage.removeItem(key);
|
|
150
|
+
}
|
|
151
|
+
console.log(`[StorageManager] Cleared ${keysToRemove.length} items from localStorage`);
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error("[StorageManager] Clear failed:", error);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get item from current storage tier
|
|
158
|
+
*/
|
|
159
|
+
getItem(key) {
|
|
160
|
+
const storage = this.getStorage();
|
|
161
|
+
if (!storage)
|
|
162
|
+
return null;
|
|
163
|
+
try {
|
|
164
|
+
const fullKey = this.prefix + key;
|
|
165
|
+
let value = storage.getItem(fullKey);
|
|
166
|
+
if (!value && this.currentTier === "session") {
|
|
167
|
+
try {
|
|
168
|
+
value = localStorage.getItem(fullKey);
|
|
169
|
+
} catch {
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return value;
|
|
173
|
+
} catch {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Set item in current storage tier
|
|
179
|
+
*/
|
|
180
|
+
setItem(key, value) {
|
|
181
|
+
const storage = this.getStorage();
|
|
182
|
+
if (!storage)
|
|
183
|
+
return;
|
|
184
|
+
try {
|
|
185
|
+
const fullKey = this.prefix + key;
|
|
186
|
+
storage.setItem(fullKey, value);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
console.error("[StorageManager] setItem failed:", error);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Remove item from all storage tiers
|
|
193
|
+
*/
|
|
194
|
+
removeItem(key) {
|
|
195
|
+
if (typeof window === "undefined")
|
|
196
|
+
return;
|
|
197
|
+
const fullKey = this.prefix + key;
|
|
198
|
+
try {
|
|
199
|
+
sessionStorage.removeItem(fullKey);
|
|
200
|
+
} catch {
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
localStorage.removeItem(fullKey);
|
|
204
|
+
} catch {
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Get JSON-parsed item
|
|
209
|
+
*/
|
|
210
|
+
getJSON(key) {
|
|
211
|
+
const value = this.getItem(key);
|
|
212
|
+
if (!value)
|
|
213
|
+
return null;
|
|
214
|
+
try {
|
|
215
|
+
return JSON.parse(value);
|
|
216
|
+
} catch {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Set JSON-stringified item
|
|
222
|
+
*/
|
|
223
|
+
setJSON(key, value) {
|
|
224
|
+
try {
|
|
225
|
+
this.setItem(key, JSON.stringify(value));
|
|
226
|
+
} catch {
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
var storageManagerInstance = null;
|
|
231
|
+
function getStorageManager() {
|
|
232
|
+
if (!storageManagerInstance) {
|
|
233
|
+
storageManagerInstance = new StorageManager();
|
|
234
|
+
}
|
|
235
|
+
return storageManagerInstance;
|
|
236
|
+
}
|
|
237
|
+
function initStorageWithConsent(hasAnalyticsConsent) {
|
|
238
|
+
const manager = getStorageManager();
|
|
239
|
+
if (hasAnalyticsConsent) {
|
|
240
|
+
manager.upgradeTier("local");
|
|
241
|
+
} else {
|
|
242
|
+
manager.downgradeTier("session");
|
|
243
|
+
}
|
|
244
|
+
return manager;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/react/useBalanceIdentify.ts
|
|
248
|
+
var PENDING_IDENTIFY_KEY = "pending_identify";
|
|
249
|
+
var MAX_PENDING_AGE_MS = 30 * 60 * 1e3;
|
|
250
|
+
function checkAnalyticsConsent() {
|
|
251
|
+
if (typeof window === "undefined")
|
|
252
|
+
return false;
|
|
253
|
+
try {
|
|
254
|
+
if (window.balance?.hasConsent) {
|
|
255
|
+
return window.balance.hasConsent("analytics");
|
|
256
|
+
}
|
|
257
|
+
const stored = localStorage.getItem("balance_consent");
|
|
258
|
+
if (stored) {
|
|
259
|
+
const consent = JSON.parse(stored);
|
|
260
|
+
return consent?.preferences?.analytics !== false;
|
|
261
|
+
}
|
|
262
|
+
return true;
|
|
263
|
+
} catch {
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function useBalanceIdentify() {
|
|
268
|
+
const pollIntervalRef = useRef2(null);
|
|
269
|
+
const hasProcessedPending = useRef2(false);
|
|
270
|
+
const storageManager = typeof window !== "undefined" ? getStorageManager() : null;
|
|
271
|
+
const getPendingIdentify = useCallback(() => {
|
|
272
|
+
if (!storageManager)
|
|
273
|
+
return null;
|
|
274
|
+
const pending = storageManager.getJSON(PENDING_IDENTIFY_KEY);
|
|
275
|
+
if (!pending)
|
|
276
|
+
return null;
|
|
277
|
+
if (Date.now() - pending.timestamp > MAX_PENDING_AGE_MS) {
|
|
278
|
+
storageManager.removeItem(PENDING_IDENTIFY_KEY);
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
return pending;
|
|
282
|
+
}, [storageManager]);
|
|
283
|
+
const setPendingIdentify = useCallback((email, traits) => {
|
|
284
|
+
if (!storageManager)
|
|
285
|
+
return;
|
|
286
|
+
storageManager.setJSON(PENDING_IDENTIFY_KEY, {
|
|
287
|
+
email,
|
|
288
|
+
traits,
|
|
289
|
+
timestamp: Date.now()
|
|
290
|
+
});
|
|
291
|
+
}, [storageManager]);
|
|
292
|
+
const clearPendingIdentify = useCallback(() => {
|
|
293
|
+
if (!storageManager)
|
|
294
|
+
return;
|
|
295
|
+
storageManager.removeItem(PENDING_IDENTIFY_KEY);
|
|
296
|
+
}, [storageManager]);
|
|
297
|
+
const identify2 = useCallback((email, traits) => {
|
|
298
|
+
const hasConsent2 = checkAnalyticsConsent();
|
|
299
|
+
if (!hasConsent2) {
|
|
300
|
+
console.log("[useBalanceIdentify] Skipping identify - user declined analytics consent");
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
if (storageManager) {
|
|
304
|
+
initStorageWithConsent(hasConsent2);
|
|
305
|
+
}
|
|
306
|
+
if (typeof window !== "undefined" && window.balance?.identify) {
|
|
307
|
+
window.balance.identify(email, traits);
|
|
308
|
+
console.log("[useBalanceIdentify] User identified:", email.split("@")[0] + "***");
|
|
309
|
+
clearPendingIdentify();
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
console.log("[useBalanceIdentify] Pixel not ready, queueing identify");
|
|
313
|
+
setPendingIdentify(email, traits);
|
|
314
|
+
return false;
|
|
315
|
+
}, [storageManager, clearPendingIdentify, setPendingIdentify]);
|
|
316
|
+
const processPendingIdentify = useCallback(() => {
|
|
317
|
+
if (hasProcessedPending.current)
|
|
318
|
+
return;
|
|
319
|
+
const pending = getPendingIdentify();
|
|
320
|
+
if (!pending)
|
|
321
|
+
return;
|
|
322
|
+
if (typeof window !== "undefined" && window.balance?.identify) {
|
|
323
|
+
const hasConsent2 = checkAnalyticsConsent();
|
|
324
|
+
if (!hasConsent2) {
|
|
325
|
+
console.log("[useBalanceIdentify] Clearing pending identify - user declined analytics consent");
|
|
326
|
+
clearPendingIdentify();
|
|
327
|
+
hasProcessedPending.current = true;
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (storageManager) {
|
|
331
|
+
initStorageWithConsent(hasConsent2);
|
|
332
|
+
}
|
|
333
|
+
console.log("[useBalanceIdentify] Processing pending identify");
|
|
334
|
+
window.balance.identify(pending.email, pending.traits);
|
|
335
|
+
clearPendingIdentify();
|
|
336
|
+
hasProcessedPending.current = true;
|
|
337
|
+
}
|
|
338
|
+
}, [getPendingIdentify, clearPendingIdentify, storageManager]);
|
|
339
|
+
useEffect2(() => {
|
|
340
|
+
processPendingIdentify();
|
|
341
|
+
const pending = getPendingIdentify();
|
|
342
|
+
if (pending && !hasProcessedPending.current) {
|
|
343
|
+
pollIntervalRef.current = setInterval(() => {
|
|
344
|
+
processPendingIdentify();
|
|
345
|
+
if (hasProcessedPending.current || !getPendingIdentify()) {
|
|
346
|
+
if (pollIntervalRef.current) {
|
|
347
|
+
clearInterval(pollIntervalRef.current);
|
|
348
|
+
pollIntervalRef.current = null;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}, 500);
|
|
352
|
+
}
|
|
353
|
+
return () => {
|
|
354
|
+
if (pollIntervalRef.current) {
|
|
355
|
+
clearInterval(pollIntervalRef.current);
|
|
356
|
+
pollIntervalRef.current = null;
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
}, [processPendingIdentify, getPendingIdentify]);
|
|
360
|
+
return {
|
|
361
|
+
/**
|
|
362
|
+
* Identify a user with BALANCE pixel.
|
|
363
|
+
* Handles consent checks, queuing, and storage tier automatically.
|
|
364
|
+
*/
|
|
365
|
+
identify: identify2,
|
|
366
|
+
/**
|
|
367
|
+
* Check if analytics consent is currently granted
|
|
368
|
+
*/
|
|
369
|
+
hasAnalyticsConsent: checkAnalyticsConsent
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/index.esm.ts
|
|
374
|
+
var track = (eventName, properties) => {
|
|
375
|
+
if (typeof window === "undefined")
|
|
376
|
+
return;
|
|
377
|
+
if (window.balance) {
|
|
378
|
+
window.balance.track(eventName, properties);
|
|
379
|
+
} else {
|
|
380
|
+
console.warn("[Balance Pixel] track() called before pixel initialized:", eventName);
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
var identify = (email, traits) => {
|
|
384
|
+
if (typeof window === "undefined")
|
|
385
|
+
return Promise.resolve();
|
|
386
|
+
if (window.balance) {
|
|
387
|
+
return window.balance.identify(email, traits);
|
|
388
|
+
} else {
|
|
389
|
+
console.warn("[Balance Pixel] identify() called before pixel initialized");
|
|
390
|
+
return Promise.resolve();
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
var page = (options) => {
|
|
394
|
+
if (typeof window === "undefined")
|
|
395
|
+
return;
|
|
396
|
+
if (window.balance) {
|
|
397
|
+
window.balance.page(options);
|
|
398
|
+
} else {
|
|
399
|
+
console.warn("[Balance Pixel] page() called before pixel initialized");
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
var purchase = (revenue, currency, properties) => {
|
|
403
|
+
if (typeof window === "undefined")
|
|
404
|
+
return;
|
|
405
|
+
if (window.balance) {
|
|
406
|
+
window.balance.purchase(revenue, currency, properties);
|
|
407
|
+
} else {
|
|
408
|
+
console.warn("[Balance Pixel] purchase() called before pixel initialized");
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
var getSessionId = () => {
|
|
412
|
+
if (typeof window === "undefined")
|
|
413
|
+
return null;
|
|
414
|
+
return window.balance?.getSessionId() ?? null;
|
|
415
|
+
};
|
|
416
|
+
var getFanIdHash = () => {
|
|
417
|
+
if (typeof window === "undefined")
|
|
418
|
+
return null;
|
|
419
|
+
return window.balance?.getFanIdHash() ?? null;
|
|
420
|
+
};
|
|
421
|
+
var getAttribution = () => {
|
|
422
|
+
if (typeof window === "undefined")
|
|
423
|
+
return {};
|
|
424
|
+
return window.balance?.getAttribution() ?? {};
|
|
425
|
+
};
|
|
426
|
+
var setConsent = (preferences) => {
|
|
427
|
+
if (typeof window === "undefined")
|
|
428
|
+
return;
|
|
429
|
+
if (window.balance) {
|
|
430
|
+
window.balance.setConsent(preferences);
|
|
431
|
+
} else {
|
|
432
|
+
console.warn("[Balance Pixel] setConsent() called before pixel initialized");
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
var getConsent = () => {
|
|
436
|
+
if (typeof window === "undefined")
|
|
437
|
+
return null;
|
|
438
|
+
return window.balance?.getConsent() ?? null;
|
|
439
|
+
};
|
|
440
|
+
var hasConsent = (type) => {
|
|
441
|
+
if (typeof window === "undefined")
|
|
442
|
+
return false;
|
|
443
|
+
return window.balance?.hasConsent(type) ?? false;
|
|
444
|
+
};
|
|
20
445
|
export {
|
|
21
|
-
BalanceAnalytics
|
|
446
|
+
BalanceAnalytics,
|
|
447
|
+
StorageManager,
|
|
448
|
+
getAttribution,
|
|
449
|
+
getConsent,
|
|
450
|
+
getFanIdHash,
|
|
451
|
+
getSessionId,
|
|
452
|
+
getStorageManager,
|
|
453
|
+
hasConsent,
|
|
454
|
+
identify,
|
|
455
|
+
initStorageWithConsent,
|
|
456
|
+
page,
|
|
457
|
+
purchase,
|
|
458
|
+
setConsent,
|
|
459
|
+
track,
|
|
460
|
+
useBalanceIdentify
|
|
22
461
|
};
|
package/dist/index.js
CHANGED
|
@@ -56,12 +56,27 @@ var BalancePixel = (() => {
|
|
|
56
56
|
function BalanceAnalyticsInner() {
|
|
57
57
|
const pathname = (0, import_navigation.usePathname)();
|
|
58
58
|
const searchParams = (0, import_navigation.useSearchParams)();
|
|
59
|
+
const isFirstRender = (0, import_react.useRef)(true);
|
|
60
|
+
const lastTrackedPath = (0, import_react.useRef)(null);
|
|
59
61
|
(0, import_react.useEffect)(() => {
|
|
60
|
-
if (typeof window
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
+
}
|
|
64
75
|
}
|
|
76
|
+
const url = window.location.href;
|
|
77
|
+
const title = document.title;
|
|
78
|
+
lastTrackedPath.current = currentPath;
|
|
79
|
+
window.balance.page({ url, title });
|
|
65
80
|
}, [pathname, searchParams]);
|
|
66
81
|
return null;
|
|
67
82
|
}
|
|
@@ -80,12 +95,13 @@ var BalancePixel = (() => {
|
|
|
80
95
|
console.error("[BALANCE Pixel] Error: data-artist-id attribute is required");
|
|
81
96
|
return;
|
|
82
97
|
}
|
|
83
|
-
const SESSION_KEY = "
|
|
84
|
-
const SESSION_TIMESTAMP_KEY = "
|
|
85
|
-
const ATTRIBUTION_KEY = "
|
|
86
|
-
const FAN_ID_KEY = "
|
|
98
|
+
const SESSION_KEY = "session_id";
|
|
99
|
+
const SESSION_TIMESTAMP_KEY = "session_timestamp";
|
|
100
|
+
const ATTRIBUTION_KEY = "attribution";
|
|
101
|
+
const FAN_ID_KEY = "fan_id_hash";
|
|
87
102
|
const CONSENT_STORAGE_KEY = "balance_consent";
|
|
88
103
|
const SESSION_DURATION = 60 * 60 * 1e3;
|
|
104
|
+
const STORAGE_PREFIX = "balance_";
|
|
89
105
|
const API_ENDPOINT = useEmulator ? `http://localhost:5001/artist-os-distro/us-central1/pixelEndpoint` : `https://us-central1-artist-os-distro.cloudfunctions.net/pixelEndpoint`;
|
|
90
106
|
let sessionId = null;
|
|
91
107
|
let fanIdHash = null;
|
|
@@ -93,10 +109,72 @@ var BalancePixel = (() => {
|
|
|
93
109
|
let attribution = {};
|
|
94
110
|
let eventQueue = [];
|
|
95
111
|
let flushTimer = null;
|
|
112
|
+
let currentStorageTier = "session";
|
|
96
113
|
const log = (...args) => {
|
|
97
114
|
if (debug)
|
|
98
115
|
console.log("[BALANCE Pixel]", ...args);
|
|
99
116
|
};
|
|
117
|
+
function getStorage() {
|
|
118
|
+
try {
|
|
119
|
+
return currentStorageTier === "local" ? localStorage : sessionStorage;
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function storageGet(key) {
|
|
125
|
+
const storage = getStorage();
|
|
126
|
+
if (!storage)
|
|
127
|
+
return null;
|
|
128
|
+
try {
|
|
129
|
+
const fullKey = STORAGE_PREFIX + key;
|
|
130
|
+
let value = storage.getItem(fullKey);
|
|
131
|
+
if (!value && currentStorageTier === "session") {
|
|
132
|
+
try {
|
|
133
|
+
value = localStorage.getItem(fullKey);
|
|
134
|
+
} catch {
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return value;
|
|
138
|
+
} catch {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function storageSet(key, value) {
|
|
143
|
+
const storage = getStorage();
|
|
144
|
+
if (!storage)
|
|
145
|
+
return;
|
|
146
|
+
try {
|
|
147
|
+
storage.setItem(STORAGE_PREFIX + key, value);
|
|
148
|
+
} catch {
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function upgradeStorageTier() {
|
|
152
|
+
if (currentStorageTier === "local")
|
|
153
|
+
return;
|
|
154
|
+
log("Upgrading storage tier: session -> local");
|
|
155
|
+
try {
|
|
156
|
+
const keysToMigrate = [];
|
|
157
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
158
|
+
const key = sessionStorage.key(i);
|
|
159
|
+
if (key?.startsWith(STORAGE_PREFIX)) {
|
|
160
|
+
keysToMigrate.push(key);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
for (const key of keysToMigrate) {
|
|
164
|
+
const value = sessionStorage.getItem(key);
|
|
165
|
+
if (value) {
|
|
166
|
+
localStorage.setItem(key, value);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
for (const key of keysToMigrate) {
|
|
170
|
+
sessionStorage.removeItem(key);
|
|
171
|
+
}
|
|
172
|
+
currentStorageTier = "local";
|
|
173
|
+
log(`Storage tier upgraded, migrated ${keysToMigrate.length} items`);
|
|
174
|
+
} catch (error) {
|
|
175
|
+
console.error("[BALANCE Pixel] Storage migration failed:", error);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
100
178
|
function generateUUID() {
|
|
101
179
|
if (crypto && crypto.randomUUID) {
|
|
102
180
|
return crypto.randomUUID();
|
|
@@ -109,18 +187,18 @@ var BalancePixel = (() => {
|
|
|
109
187
|
}
|
|
110
188
|
function getOrCreateSession() {
|
|
111
189
|
try {
|
|
112
|
-
const stored =
|
|
113
|
-
const timestamp =
|
|
190
|
+
const stored = storageGet(SESSION_KEY);
|
|
191
|
+
const timestamp = storageGet(SESSION_TIMESTAMP_KEY);
|
|
114
192
|
if (stored && timestamp) {
|
|
115
193
|
const age = Date.now() - parseInt(timestamp, 10);
|
|
116
194
|
if (age < SESSION_DURATION) {
|
|
117
|
-
|
|
195
|
+
storageSet(SESSION_TIMESTAMP_KEY, Date.now().toString());
|
|
118
196
|
return stored;
|
|
119
197
|
}
|
|
120
198
|
}
|
|
121
199
|
const newId = generateUUID();
|
|
122
|
-
|
|
123
|
-
|
|
200
|
+
storageSet(SESSION_KEY, newId);
|
|
201
|
+
storageSet(SESSION_TIMESTAMP_KEY, Date.now().toString());
|
|
124
202
|
return newId;
|
|
125
203
|
} catch (e) {
|
|
126
204
|
return generateUUID();
|
|
@@ -138,7 +216,7 @@ var BalancePixel = (() => {
|
|
|
138
216
|
}
|
|
139
217
|
function captureAttribution() {
|
|
140
218
|
try {
|
|
141
|
-
const stored =
|
|
219
|
+
const stored = storageGet(ATTRIBUTION_KEY);
|
|
142
220
|
if (stored) {
|
|
143
221
|
attribution = JSON.parse(stored);
|
|
144
222
|
log("Loaded attribution:", attribution);
|
|
@@ -147,7 +225,7 @@ var BalancePixel = (() => {
|
|
|
147
225
|
const utm = extractUTM();
|
|
148
226
|
if (Object.keys(utm).length > 0) {
|
|
149
227
|
attribution = utm;
|
|
150
|
-
|
|
228
|
+
storageSet(ATTRIBUTION_KEY, JSON.stringify(utm));
|
|
151
229
|
log("Captured attribution:", attribution);
|
|
152
230
|
}
|
|
153
231
|
} catch (e) {
|
|
@@ -155,7 +233,7 @@ var BalancePixel = (() => {
|
|
|
155
233
|
}
|
|
156
234
|
function loadFanId() {
|
|
157
235
|
try {
|
|
158
|
-
fanIdHash =
|
|
236
|
+
fanIdHash = storageGet(FAN_ID_KEY);
|
|
159
237
|
} catch (e) {
|
|
160
238
|
}
|
|
161
239
|
}
|
|
@@ -184,6 +262,9 @@ var BalancePixel = (() => {
|
|
|
184
262
|
} catch (e) {
|
|
185
263
|
console.error("[BALANCE Pixel] Could not save consent:", e);
|
|
186
264
|
}
|
|
265
|
+
if (preferences.analytics === true) {
|
|
266
|
+
upgradeStorageTier();
|
|
267
|
+
}
|
|
187
268
|
const event = buildEvent({
|
|
188
269
|
event_name: "consent_updated",
|
|
189
270
|
metadata: {
|
|
@@ -285,15 +366,23 @@ var BalancePixel = (() => {
|
|
|
285
366
|
}
|
|
286
367
|
async function identify2(email, traits = {}) {
|
|
287
368
|
try {
|
|
369
|
+
if (consent && consent.analytics === false) {
|
|
370
|
+
log("Identify skipped - user declined analytics consent");
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
288
373
|
fanIdHash = await hashEmail(email);
|
|
289
|
-
|
|
374
|
+
if (consent?.analytics === true) {
|
|
375
|
+
upgradeStorageTier();
|
|
376
|
+
}
|
|
377
|
+
storageSet(FAN_ID_KEY, fanIdHash);
|
|
290
378
|
const emailParts = email.split("@");
|
|
291
379
|
const maskedEmail = emailParts[0].charAt(0) + "***@" + (emailParts[1] || "");
|
|
292
380
|
log("Fan identified:", {
|
|
293
381
|
name: traits.name || "(no name)",
|
|
294
382
|
email: maskedEmail,
|
|
295
383
|
hash: fanIdHash.substring(0, 16) + "...",
|
|
296
|
-
traits
|
|
384
|
+
traits,
|
|
385
|
+
storageTier: currentStorageTier
|
|
297
386
|
});
|
|
298
387
|
const event = buildEvent({
|
|
299
388
|
event_name: "identify",
|
|
@@ -301,7 +390,8 @@ var BalancePixel = (() => {
|
|
|
301
390
|
metadata: {
|
|
302
391
|
email_sha256: fanIdHash,
|
|
303
392
|
traits,
|
|
304
|
-
consent_preferences: consent || void 0
|
|
393
|
+
consent_preferences: consent || void 0,
|
|
394
|
+
storage_tier: currentStorageTier
|
|
305
395
|
}
|
|
306
396
|
});
|
|
307
397
|
enqueueEvent(event);
|
|
@@ -321,9 +411,16 @@ var BalancePixel = (() => {
|
|
|
321
411
|
enqueueEvent(event);
|
|
322
412
|
}
|
|
323
413
|
function init() {
|
|
414
|
+
loadConsent();
|
|
415
|
+
if (consent?.analytics === true) {
|
|
416
|
+
currentStorageTier = "local";
|
|
417
|
+
log("Storage tier: local (analytics consent granted)");
|
|
418
|
+
} else {
|
|
419
|
+
currentStorageTier = "session";
|
|
420
|
+
log("Storage tier: session (privacy by default)");
|
|
421
|
+
}
|
|
324
422
|
sessionId = getOrCreateSession();
|
|
325
423
|
loadFanId();
|
|
326
|
-
loadConsent();
|
|
327
424
|
if (!consent) {
|
|
328
425
|
consent = {
|
|
329
426
|
analytics: true,
|
|
@@ -332,6 +429,7 @@ var BalancePixel = (() => {
|
|
|
332
429
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
333
430
|
};
|
|
334
431
|
log("Default consent enabled (all tracking):", consent);
|
|
432
|
+
upgradeStorageTier();
|
|
335
433
|
}
|
|
336
434
|
captureAttribution();
|
|
337
435
|
startFlushTimer();
|
|
@@ -341,9 +439,11 @@ var BalancePixel = (() => {
|
|
|
341
439
|
sessionId,
|
|
342
440
|
fanIdHash,
|
|
343
441
|
consent,
|
|
442
|
+
storageTier: currentStorageTier,
|
|
344
443
|
useEmulator,
|
|
345
444
|
endpoint: API_ENDPOINT
|
|
346
445
|
});
|
|
446
|
+
window._balanceInitialPageviewFired = true;
|
|
347
447
|
trackPageView();
|
|
348
448
|
window.addEventListener("beforeunload", () => {
|
|
349
449
|
flush();
|
package/dist/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var BalancePixel=(()=>{var
|
|
1
|
+
var BalancePixel=(()=>{var te=Object.create;var _=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var ie=Object.getOwnPropertyNames;var oe=Object.getPrototypeOf,ae=Object.prototype.hasOwnProperty;var z=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(i,o)=>(typeof require<"u"?require:i)[o]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var se=(t,i)=>{for(var o in i)_(t,o,{get:i[o],enumerable:!0})},U=(t,i,o,d)=>{if(i&&typeof i=="object"||typeof i=="function")for(let l of ie(i))!ae.call(t,l)&&l!==o&&_(t,l,{get:()=>i[l],enumerable:!(d=re(i,l))||d.enumerable});return t};var ce=(t,i,o)=>(o=t!=null?te(oe(t)):{},U(i||!t||!t.__esModule?_(o,"default",{value:t,enumerable:!0}):o,t)),le=t=>U(_({},"__esModule",{value:!0}),t);var Se={};se(Se,{BalanceAnalytics:()=>j,getAttribution:()=>ye,getConsent:()=>xe,getFanIdHash:()=>me,getSessionId:()=>we,hasConsent:()=>be,identify:()=>ge,page:()=>fe,purchase:()=>pe,setConsent:()=>he,track:()=>de});var u=ce(z("react")),P=z("next/navigation");function ue(){let t=(0,P.usePathname)(),i=(0,P.useSearchParams)(),o=(0,u.useRef)(!0),d=(0,u.useRef)(null);return(0,u.useEffect)(()=>{if(typeof window>"u"||!window.balance)return;let l=t+(i?.toString()||"");if(d.current===l)return;if(o.current&&(o.current=!1,window._balanceInitialPageviewFired)){d.current=l,console.log("[BalanceAnalytics] Skipping initial pageview (script already fired)");return}let b=window.location.href,m=document.title;d.current=l,window.balance.page({url:b,title:m})},[t,i]),null}function j(){return u.default.createElement(u.Suspense,{fallback:null},u.default.createElement(ue,null))}(function(){let t=document.currentScript,i=t?.dataset.artistId,o=t?.dataset.projectId,d=t?.dataset.emulator==="true",l=t?.dataset.debug==="true";if(!i){console.error("[BALANCE Pixel] Error: data-artist-id attribute is required");return}let b="session_id",m="session_timestamp",N="attribution",R="fan_id_hash",O="balance_consent",H=60*60*1e3,E="balance_",A=d?"http://localhost:5001/artist-os-distro/us-central1/pixelEndpoint":"https://us-central1-artist-os-distro.cloudfunctions.net/pixelEndpoint",S=null,g=null,c=null,w={},f=[],C=null,p="session",s=(...e)=>{l&&console.log("[BALANCE Pixel]",...e)};function B(){try{return p==="local"?localStorage:sessionStorage}catch{return null}}function v(e){let n=B();if(!n)return null;try{let r=E+e,a=n.getItem(r);if(!a&&p==="session")try{a=localStorage.getItem(r)}catch{}return a}catch{return null}}function y(e,n){let r=B();if(r)try{r.setItem(E+e,n)}catch{}}function k(){if(p!=="local"){s("Upgrading storage tier: session -> local");try{let e=[];for(let n=0;n<sessionStorage.length;n++){let r=sessionStorage.key(n);r?.startsWith(E)&&e.push(r)}for(let n of e){let r=sessionStorage.getItem(n);r&&localStorage.setItem(n,r)}for(let n of e)sessionStorage.removeItem(n);p="local",s(`Storage tier upgraded, migrated ${e.length} items`)}catch(e){console.error("[BALANCE Pixel] Storage migration failed:",e)}}}function F(){return crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let n=Math.random()*16|0;return(e==="x"?n:n&3|8).toString(16)})}function M(){try{let e=v(b),n=v(m);if(e&&n&&Date.now()-parseInt(n,10)<H)return y(m,Date.now().toString()),e;let r=F();return y(b,r),y(m,Date.now().toString()),r}catch{return F()}}function K(){let e=new URLSearchParams(window.location.search),n={};return["source","medium","campaign","content","term"].forEach(r=>{let a=e.get(`utm_${r}`);a&&(n[`utm_${r}`]=a)}),n}function J(){try{let e=v(N);if(e){w=JSON.parse(e),s("Loaded attribution:",w);return}let n=K();Object.keys(n).length>0&&(w=n,y(N,JSON.stringify(n)),s("Captured attribution:",w))}catch{}}function Y(){try{g=v(R)}catch{}}function q(){try{let e=localStorage.getItem(O);e&&(c=JSON.parse(e).preferences||null,s("Loaded consent:",c))}catch{}}function $(e){let n=c;c=e;try{let a={preferences:e,method:"explicit",version:1};localStorage.setItem(O,JSON.stringify(a)),s("Consent saved:",e)}catch(a){console.error("[BALANCE Pixel] Could not save consent:",a)}e.analytics===!0&&k();let r=h({event_name:"consent_updated",metadata:{consent_preferences:e,consent_method:"explicit",previous_consent:n||void 0}});x(r)}function G(){return c}function W(e){return c?.[e]===!0}async function Q(e){let n=e.toLowerCase().trim(),a=new TextEncoder().encode(n),T=await crypto.subtle.digest("SHA-256",a);return Array.from(new Uint8Array(T)).map(ne=>ne.toString(16).padStart(2,"0")).join("")}function h(e){let n={artist_id:i,fan_session_id:S,fan_id_hash:g||void 0,timestamp:new Date().toISOString(),source_url:window.location.href,referrer_url:document.referrer||void 0,user_agent:navigator.userAgent,...e,...w};return o&&!e.projectId&&(n.projectId=o),n}function x(e){f.push(e),s("Event queued:",e.event_name,"(queue:",f.length,")"),f.length>=10&&I()}async function I(){if(f.length===0)return;let e=[...f];f=[],s("Flushing",e.length,"events to",A);try{let n=await fetch(A,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({events:e}),keepalive:!0});if(!n.ok)throw new Error(`HTTP ${n.status}`);s("Events sent successfully")}catch(n){console.error("[BALANCE Pixel] Failed to send events:",n),f.length<50&&f.push(...e)}}function V(){C&&clearInterval(C),C=window.setInterval(()=>{f.length>0&&I()},5e3)}function L(e={}){let n=h({event_name:"pageview",page_title:e.title||document.title,source_url:e.url||window.location.href});x(n)}function X(e,n={}){let r=h({event_name:"custom",metadata:{event_type:e,...n}});x(r)}async function Z(e,n={}){try{if(c&&c.analytics===!1){s("Identify skipped - user declined analytics consent");return}g=await Q(e),c?.analytics===!0&&k(),y(R,g);let r=e.split("@"),a=r[0].charAt(0)+"***@"+(r[1]||"");s("Fan identified:",{name:n.name||"(no name)",email:a,hash:g.substring(0,16)+"...",traits:n,storageTier:p});let T=h({event_name:"identify",fan_id_hash:g,metadata:{email_sha256:g,traits:n,consent_preferences:c||void 0,storage_tier:p}});x(T)}catch(r){console.error("[BALANCE Pixel] Failed to identify:",r)}}function ee(e,n="USD",r={}){let a=h({event_name:"purchase",metadata:{revenue:e,currency:n,...r}});x(a)}function D(){q(),c?.analytics===!0?(p="local",s("Storage tier: local (analytics consent granted)")):(p="session",s("Storage tier: session (privacy by default)")),S=M(),Y(),c||(c={analytics:!0,marketing:!0,personalization:!0,timestamp:new Date().toISOString()},s("Default consent enabled (all tracking):",c),k()),J(),V(),s("Initialized",{artistId:i,projectId:o||"(none - will track to all projects)",sessionId:S,fanIdHash:g,consent:c,storageTier:p,useEmulator:d,endpoint:A}),window._balanceInitialPageviewFired=!0,L(),window.addEventListener("beforeunload",()=>{I()}),document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&I()})}window.balance={track:X,identify:Z,page:L,purchase:ee,getSessionId:()=>S,getFanIdHash:()=>g,getAttribution:()=>w,setConsent:$,getConsent:G,hasConsent:W},document.readyState==="loading"?document.addEventListener("DOMContentLoaded",D):D(),s("Pixel script loaded")})();var de=(t,i)=>{typeof window>"u"||(window.balance?window.balance.track(t,i):console.warn("[Balance Pixel] track() called before pixel initialized:",t))},ge=(t,i)=>typeof window>"u"?Promise.resolve():window.balance?window.balance.identify(t,i):(console.warn("[Balance Pixel] identify() called before pixel initialized"),Promise.resolve()),fe=t=>{typeof window>"u"||(window.balance?window.balance.page(t):console.warn("[Balance Pixel] page() called before pixel initialized"))},pe=(t,i,o)=>{typeof window>"u"||(window.balance?window.balance.purchase(t,i,o):console.warn("[Balance Pixel] purchase() called before pixel initialized"))},we=()=>typeof window>"u"?null:window.balance?.getSessionId()??null,me=()=>typeof window>"u"?null:window.balance?.getFanIdHash()??null,ye=()=>typeof window>"u"?{}:window.balance?.getAttribution()??{},he=t=>{typeof window>"u"||(window.balance?window.balance.setConsent(t):console.warn("[Balance Pixel] setConsent() called before pixel initialized"))},xe=()=>typeof window>"u"?null:window.balance?.getConsent()??null,be=t=>typeof window>"u"?!1:window.balance?.hasConsent(t)??!1;return le(Se);})();
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hifilabs/pixel",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "BALANCE Pixel - Lightweight browser tracking script for artist fan analytics",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.esm.js",
|
|
7
7
|
"types": "./dist/index.esm.d.ts",
|
|
8
8
|
"publishConfig": {
|
|
9
|
-
"access": "
|
|
9
|
+
"access": "restricted"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist"
|