@hifilabs/pixel 0.0.10 → 0.1.0
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 +32 -0
- package/dist/index.esm.js +154 -3
- package/package.json +1 -1
package/dist/index.esm.d.ts
CHANGED
|
@@ -19,6 +19,38 @@ export declare const setConsent: (preferences: {
|
|
|
19
19
|
export declare const getConsent: () => any;
|
|
20
20
|
export declare const hasConsent: (type: 'analytics' | 'marketing' | 'personalization') => boolean;
|
|
21
21
|
|
|
22
|
+
// GTM Integration Types
|
|
23
|
+
export type GTMConsentState = 'granted' | 'denied';
|
|
24
|
+
|
|
25
|
+
export interface GTMConsentConfig {
|
|
26
|
+
ad_storage: GTMConsentState;
|
|
27
|
+
ad_user_data: GTMConsentState;
|
|
28
|
+
ad_personalization: GTMConsentState;
|
|
29
|
+
analytics_storage: GTMConsentState;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export declare const DEFAULT_GTM_CONSENT: GTMConsentConfig;
|
|
33
|
+
|
|
34
|
+
// GTMProvider Component
|
|
35
|
+
export interface GTMProviderProps {
|
|
36
|
+
gtmId?: string;
|
|
37
|
+
children: React.ReactNode;
|
|
38
|
+
debug?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export declare function GTMProvider(props: GTMProviderProps): JSX.Element;
|
|
42
|
+
|
|
43
|
+
// useGTMConsent Hook
|
|
44
|
+
export interface UseGTMConsentOptions {
|
|
45
|
+
pollInterval?: number;
|
|
46
|
+
debug?: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export declare function useGTMConsent(options?: UseGTMConsentOptions): {
|
|
50
|
+
syncConsent: () => void;
|
|
51
|
+
getConsentConfig: () => GTMConsentConfig;
|
|
52
|
+
};
|
|
53
|
+
|
|
22
54
|
// useBalanceIdentify hook - consent-aware identify wrapper
|
|
23
55
|
export declare function useBalanceIdentify(): {
|
|
24
56
|
/**
|
package/dist/index.esm.js
CHANGED
|
@@ -7,7 +7,7 @@ var __publicField = (obj, key, value) => {
|
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
// src/react/BalanceAnalytics.tsx
|
|
10
|
-
import
|
|
10
|
+
import React2, { useEffect, useRef, Suspense } from "react";
|
|
11
11
|
import { usePathname, useSearchParams } from "next/navigation";
|
|
12
12
|
function BalanceAnalyticsInner() {
|
|
13
13
|
const pathname = usePathname();
|
|
@@ -37,7 +37,7 @@ function BalanceAnalyticsInner() {
|
|
|
37
37
|
return null;
|
|
38
38
|
}
|
|
39
39
|
function BalanceAnalytics() {
|
|
40
|
-
return /* @__PURE__ */
|
|
40
|
+
return /* @__PURE__ */ React2.createElement(Suspense, { fallback: null }, /* @__PURE__ */ React2.createElement(BalanceAnalyticsInner, null));
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// src/react/useBalanceIdentify.ts
|
|
@@ -370,6 +370,154 @@ function useBalanceIdentify() {
|
|
|
370
370
|
};
|
|
371
371
|
}
|
|
372
372
|
|
|
373
|
+
// src/react/GTMProvider.tsx
|
|
374
|
+
import { useEffect as useEffect4 } from "react";
|
|
375
|
+
import Script from "next/script";
|
|
376
|
+
|
|
377
|
+
// src/react/useGTMConsent.ts
|
|
378
|
+
import { useEffect as useEffect3, useRef as useRef3, useCallback as useCallback2 } from "react";
|
|
379
|
+
function useGTMConsent(options = {}) {
|
|
380
|
+
const { pollInterval = 1e3, debug = false } = options;
|
|
381
|
+
const lastConsentRef = useRef3("");
|
|
382
|
+
const log = useCallback2(
|
|
383
|
+
(...args) => {
|
|
384
|
+
if (debug) {
|
|
385
|
+
console.log("[useGTMConsent]", ...args);
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
[debug]
|
|
389
|
+
);
|
|
390
|
+
const mapPixelConsentToGTM = useCallback2(() => {
|
|
391
|
+
if (typeof window === "undefined" || !window.balance) {
|
|
392
|
+
return {
|
|
393
|
+
ad_storage: "denied",
|
|
394
|
+
ad_user_data: "denied",
|
|
395
|
+
ad_personalization: "denied",
|
|
396
|
+
analytics_storage: "denied"
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
const hasAnalytics = window.balance.hasConsent("analytics");
|
|
400
|
+
const hasMarketing = window.balance.hasConsent("marketing");
|
|
401
|
+
const analyticsState = hasAnalytics ? "granted" : "denied";
|
|
402
|
+
const marketingState = hasMarketing ? "granted" : "denied";
|
|
403
|
+
return {
|
|
404
|
+
analytics_storage: analyticsState,
|
|
405
|
+
ad_storage: marketingState,
|
|
406
|
+
ad_user_data: marketingState,
|
|
407
|
+
ad_personalization: marketingState
|
|
408
|
+
};
|
|
409
|
+
}, []);
|
|
410
|
+
const updateGTMConsent = useCallback2(
|
|
411
|
+
(consentConfig) => {
|
|
412
|
+
if (typeof window === "undefined")
|
|
413
|
+
return;
|
|
414
|
+
window.dataLayer = window.dataLayer || [];
|
|
415
|
+
if (typeof window.gtag !== "function") {
|
|
416
|
+
window.gtag = function gtag(...args) {
|
|
417
|
+
window.dataLayer.push(args);
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
window.gtag("consent", "update", consentConfig);
|
|
421
|
+
log("Pushed consent update to GTM:", consentConfig);
|
|
422
|
+
},
|
|
423
|
+
[log]
|
|
424
|
+
);
|
|
425
|
+
const syncConsent = useCallback2(() => {
|
|
426
|
+
const currentConsent = mapPixelConsentToGTM();
|
|
427
|
+
const consentKey = JSON.stringify(currentConsent);
|
|
428
|
+
if (consentKey !== lastConsentRef.current) {
|
|
429
|
+
lastConsentRef.current = consentKey;
|
|
430
|
+
updateGTMConsent(currentConsent);
|
|
431
|
+
}
|
|
432
|
+
}, [mapPixelConsentToGTM, updateGTMConsent]);
|
|
433
|
+
useEffect3(() => {
|
|
434
|
+
if (typeof window === "undefined")
|
|
435
|
+
return;
|
|
436
|
+
syncConsent();
|
|
437
|
+
const intervalId = setInterval(syncConsent, pollInterval);
|
|
438
|
+
const handleStorageChange = (e) => {
|
|
439
|
+
if (e.key === "balance_consent") {
|
|
440
|
+
log("Consent changed in another tab, syncing...");
|
|
441
|
+
syncConsent();
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
window.addEventListener("storage", handleStorageChange);
|
|
445
|
+
return () => {
|
|
446
|
+
clearInterval(intervalId);
|
|
447
|
+
window.removeEventListener("storage", handleStorageChange);
|
|
448
|
+
};
|
|
449
|
+
}, [syncConsent, pollInterval, log]);
|
|
450
|
+
return {
|
|
451
|
+
/**
|
|
452
|
+
* Manually trigger a consent sync
|
|
453
|
+
*/
|
|
454
|
+
syncConsent,
|
|
455
|
+
/**
|
|
456
|
+
* Get current consent config
|
|
457
|
+
*/
|
|
458
|
+
getConsentConfig: mapPixelConsentToGTM
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// src/types/gtm.ts
|
|
463
|
+
var DEFAULT_GTM_CONSENT = {
|
|
464
|
+
ad_storage: "denied",
|
|
465
|
+
ad_user_data: "denied",
|
|
466
|
+
ad_personalization: "denied",
|
|
467
|
+
analytics_storage: "denied"
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
// src/react/GTMProvider.tsx
|
|
471
|
+
function GTMProvider({ gtmId, children, debug = false }) {
|
|
472
|
+
const resolvedGtmId = gtmId || process.env.NEXT_PUBLIC_GTM_ID;
|
|
473
|
+
useGTMConsent({ debug });
|
|
474
|
+
useEffect4(() => {
|
|
475
|
+
if (typeof window === "undefined" || !resolvedGtmId)
|
|
476
|
+
return;
|
|
477
|
+
window.dataLayer = window.dataLayer || [];
|
|
478
|
+
if (typeof window.gtag !== "function") {
|
|
479
|
+
window.gtag = function gtag(...args) {
|
|
480
|
+
window.dataLayer.push(args);
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
window.gtag("consent", "default", DEFAULT_GTM_CONSENT);
|
|
484
|
+
if (debug) {
|
|
485
|
+
console.log("[GTMProvider] Initialized with default consent:", DEFAULT_GTM_CONSENT);
|
|
486
|
+
}
|
|
487
|
+
}, [resolvedGtmId, debug]);
|
|
488
|
+
if (!resolvedGtmId) {
|
|
489
|
+
if (debug) {
|
|
490
|
+
console.log("[GTMProvider] No GTM ID configured, skipping GTM initialization");
|
|
491
|
+
}
|
|
492
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
|
|
493
|
+
}
|
|
494
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
495
|
+
Script,
|
|
496
|
+
{
|
|
497
|
+
id: "gtm-script",
|
|
498
|
+
strategy: "afterInteractive",
|
|
499
|
+
dangerouslySetInnerHTML: {
|
|
500
|
+
__html: `
|
|
501
|
+
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
|
502
|
+
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
|
503
|
+
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
|
504
|
+
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
|
505
|
+
})(window,document,'script','dataLayer','${resolvedGtmId}');
|
|
506
|
+
`
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
), /* @__PURE__ */ React.createElement("noscript", null, /* @__PURE__ */ React.createElement(
|
|
510
|
+
"iframe",
|
|
511
|
+
{
|
|
512
|
+
src: `https://www.googletagmanager.com/ns.html?id=${resolvedGtmId}`,
|
|
513
|
+
height: "0",
|
|
514
|
+
width: "0",
|
|
515
|
+
style: { display: "none", visibility: "hidden" },
|
|
516
|
+
title: "GTM"
|
|
517
|
+
}
|
|
518
|
+
)), children);
|
|
519
|
+
}
|
|
520
|
+
|
|
373
521
|
// src/index.esm.ts
|
|
374
522
|
var track = (eventName, properties) => {
|
|
375
523
|
if (typeof window === "undefined")
|
|
@@ -444,6 +592,8 @@ var hasConsent = (type) => {
|
|
|
444
592
|
};
|
|
445
593
|
export {
|
|
446
594
|
BalanceAnalytics,
|
|
595
|
+
DEFAULT_GTM_CONSENT,
|
|
596
|
+
GTMProvider,
|
|
447
597
|
StorageManager,
|
|
448
598
|
getAttribution,
|
|
449
599
|
getConsent,
|
|
@@ -457,5 +607,6 @@ export {
|
|
|
457
607
|
purchase,
|
|
458
608
|
setConsent,
|
|
459
609
|
track,
|
|
460
|
-
useBalanceIdentify
|
|
610
|
+
useBalanceIdentify,
|
|
611
|
+
useGTMConsent
|
|
461
612
|
};
|