@aranova/tracking-next 0.9.0 → 0.9.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/README.md +57 -1
- package/dist/index.d.mts +117 -6
- package/dist/index.d.ts +117 -6
- package/dist/index.js +231 -58
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +231 -60
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -44,8 +44,10 @@ __export(src_exports, {
|
|
|
44
44
|
formatMoney: () => formatMoney,
|
|
45
45
|
fromMinor: () => fromMinor,
|
|
46
46
|
getConsentState: () => getConsentState,
|
|
47
|
+
resetConsent: () => resetConsent,
|
|
47
48
|
setConsentState: () => setConsentState,
|
|
48
49
|
toMinor: () => toMinor,
|
|
50
|
+
useConsent: () => useConsent,
|
|
49
51
|
useConsentState: () => useConsentState,
|
|
50
52
|
useGclid: () => useGclid,
|
|
51
53
|
useTrackingParams: () => useTrackingParams
|
|
@@ -79,6 +81,12 @@ function setConsentState(state) {
|
|
|
79
81
|
if (typeof window.gtag === "function")
|
|
80
82
|
window.gtag("consent", "update", buildConsentPayload(state));
|
|
81
83
|
}
|
|
84
|
+
function resetConsent() {
|
|
85
|
+
if (typeof window === "undefined")
|
|
86
|
+
return;
|
|
87
|
+
window.localStorage.removeItem(CONSENT_STATE_KEY);
|
|
88
|
+
window.localStorage.removeItem(CONSENT_TIMESTAMP_KEY);
|
|
89
|
+
}
|
|
82
90
|
|
|
83
91
|
// ../tracking-core/src/payloads.ts
|
|
84
92
|
function createTrackingClientContext(surface, input = {}) {
|
|
@@ -1220,81 +1228,244 @@ function formatMoney(cents, currency, locale) {
|
|
|
1220
1228
|
}
|
|
1221
1229
|
|
|
1222
1230
|
// src/ConsentBanner.tsx
|
|
1223
|
-
var
|
|
1224
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1225
|
-
function ConsentBanner() {
|
|
1226
|
-
const [consentState, setBannerConsentState] = (0, import_react.useState)("pending");
|
|
1227
|
-
const [isReady, setIsReady] = (0, import_react.useState)(false);
|
|
1228
|
-
(0, import_react.useEffect)(() => {
|
|
1229
|
-
setBannerConsentState(getConsentState());
|
|
1230
|
-
setIsReady(true);
|
|
1231
|
-
}, []);
|
|
1232
|
-
if (!isReady || consentState !== "pending")
|
|
1233
|
-
return null;
|
|
1234
|
-
const handleAccept = () => {
|
|
1235
|
-
setConsentState("granted");
|
|
1236
|
-
setBannerConsentState("granted");
|
|
1237
|
-
};
|
|
1238
|
-
const handleDecline = () => {
|
|
1239
|
-
setConsentState("denied");
|
|
1240
|
-
setBannerConsentState("denied");
|
|
1241
|
-
};
|
|
1242
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "fixed bottom-0 left-0 right-0 z-50 border-t border-gray-200 bg-white p-4 shadow-lg", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mx-auto flex max-w-5xl flex-col gap-4 md:flex-row md:items-center md:justify-between", children: [
|
|
1243
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-gray-700", children: "We use cookies to understand ad performance and improve how our marketing works across visits. You can accept or decline this tracking." }),
|
|
1244
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-2 sm:flex-row", children: [
|
|
1245
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1246
|
-
"button",
|
|
1247
|
-
{
|
|
1248
|
-
type: "button",
|
|
1249
|
-
onClick: handleDecline,
|
|
1250
|
-
className: "rounded-md border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 transition hover:bg-gray-100",
|
|
1251
|
-
children: "Decline"
|
|
1252
|
-
}
|
|
1253
|
-
),
|
|
1254
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1255
|
-
"button",
|
|
1256
|
-
{
|
|
1257
|
-
type: "button",
|
|
1258
|
-
onClick: handleAccept,
|
|
1259
|
-
className: "rounded-md bg-gray-900 px-4 py-2 text-sm font-medium text-white transition hover:bg-gray-800",
|
|
1260
|
-
children: "Accept"
|
|
1261
|
-
}
|
|
1262
|
-
)
|
|
1263
|
-
] })
|
|
1264
|
-
] }) });
|
|
1265
|
-
}
|
|
1231
|
+
var import_react2 = require("react");
|
|
1266
1232
|
|
|
1267
1233
|
// src/hooks.ts
|
|
1268
|
-
var
|
|
1234
|
+
var import_react = require("react");
|
|
1269
1235
|
function useGclid() {
|
|
1270
|
-
const [gclid, setGclid] = (0,
|
|
1271
|
-
(0,
|
|
1236
|
+
const [gclid, setGclid] = (0, import_react.useState)(null);
|
|
1237
|
+
(0, import_react.useEffect)(() => {
|
|
1272
1238
|
setGclid(getCookieValueFromDocument("gclid"));
|
|
1273
1239
|
}, []);
|
|
1274
1240
|
return gclid;
|
|
1275
1241
|
}
|
|
1276
1242
|
function useTrackingParams() {
|
|
1277
|
-
const [trackingParams, setTrackingParams] = (0,
|
|
1278
|
-
(0,
|
|
1243
|
+
const [trackingParams, setTrackingParams] = (0, import_react.useState)(createEmptyTrackingParams());
|
|
1244
|
+
(0, import_react.useEffect)(() => {
|
|
1279
1245
|
setTrackingParams(getTrackingParamsFromCookieReader(getCookieValueFromDocument));
|
|
1280
1246
|
}, []);
|
|
1281
1247
|
return trackingParams;
|
|
1282
1248
|
}
|
|
1283
1249
|
function useConsentState() {
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1250
|
+
return useConsent().state;
|
|
1251
|
+
}
|
|
1252
|
+
function useConsent() {
|
|
1253
|
+
const [state, setState] = (0, import_react.useState)("pending");
|
|
1254
|
+
(0, import_react.useEffect)(() => {
|
|
1255
|
+
setState(getConsentState());
|
|
1287
1256
|
const handleStorage = (event) => {
|
|
1288
|
-
if (event.key ===
|
|
1289
|
-
setConsentStateValue(getConsentState());
|
|
1257
|
+
if (event.key === CONSENT_STATE_KEY) setState(getConsentState());
|
|
1290
1258
|
};
|
|
1291
1259
|
window.addEventListener("storage", handleStorage);
|
|
1292
|
-
return () =>
|
|
1293
|
-
|
|
1294
|
-
|
|
1260
|
+
return () => window.removeEventListener("storage", handleStorage);
|
|
1261
|
+
}, []);
|
|
1262
|
+
const accept = (0, import_react.useCallback)(() => {
|
|
1263
|
+
setConsentState("granted");
|
|
1264
|
+
setState("granted");
|
|
1295
1265
|
}, []);
|
|
1296
|
-
|
|
1266
|
+
const decline = (0, import_react.useCallback)(() => {
|
|
1267
|
+
setConsentState("denied");
|
|
1268
|
+
setState("denied");
|
|
1269
|
+
}, []);
|
|
1270
|
+
const reset = (0, import_react.useCallback)(() => {
|
|
1271
|
+
resetConsent();
|
|
1272
|
+
setState("pending");
|
|
1273
|
+
}, []);
|
|
1274
|
+
return {
|
|
1275
|
+
state,
|
|
1276
|
+
isPending: state === "pending",
|
|
1277
|
+
isGranted: state === "granted",
|
|
1278
|
+
isDenied: state === "denied",
|
|
1279
|
+
accept,
|
|
1280
|
+
decline,
|
|
1281
|
+
reset
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
// src/ConsentBanner.tsx
|
|
1286
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1287
|
+
var LIGHT_THEME = {
|
|
1288
|
+
background: "#ffffff",
|
|
1289
|
+
border: "#e5e7eb",
|
|
1290
|
+
text: "#111827",
|
|
1291
|
+
mutedText: "#4b5563",
|
|
1292
|
+
acceptBg: "#111827",
|
|
1293
|
+
acceptText: "#ffffff",
|
|
1294
|
+
declineBg: "transparent",
|
|
1295
|
+
declineText: "#111827",
|
|
1296
|
+
declineBorder: "#d1d5db",
|
|
1297
|
+
shadow: "0 -4px 16px -2px rgba(15, 23, 42, 0.08), 0 -2px 6px -1px rgba(15, 23, 42, 0.04)",
|
|
1298
|
+
linkColor: "#1f2937"
|
|
1299
|
+
};
|
|
1300
|
+
var DARK_THEME = {
|
|
1301
|
+
background: "#0f172a",
|
|
1302
|
+
border: "#1e293b",
|
|
1303
|
+
text: "#f1f5f9",
|
|
1304
|
+
mutedText: "#cbd5e1",
|
|
1305
|
+
acceptBg: "#f1f5f9",
|
|
1306
|
+
acceptText: "#0f172a",
|
|
1307
|
+
declineBg: "transparent",
|
|
1308
|
+
declineText: "#f1f5f9",
|
|
1309
|
+
declineBorder: "#334155",
|
|
1310
|
+
shadow: "0 -4px 16px -2px rgba(0, 0, 0, 0.5), 0 -2px 6px -1px rgba(0, 0, 0, 0.3)",
|
|
1311
|
+
linkColor: "#e2e8f0"
|
|
1312
|
+
};
|
|
1313
|
+
function useResolvedTheme(theme) {
|
|
1314
|
+
const [prefersDark, setPrefersDark] = (0, import_react2.useState)(false);
|
|
1315
|
+
(0, import_react2.useEffect)(() => {
|
|
1316
|
+
if (theme !== "auto" || typeof window === "undefined" || !window.matchMedia) return;
|
|
1317
|
+
const mql = window.matchMedia("(prefers-color-scheme: dark)");
|
|
1318
|
+
setPrefersDark(mql.matches);
|
|
1319
|
+
const onChange = (e) => setPrefersDark(e.matches);
|
|
1320
|
+
mql.addEventListener("change", onChange);
|
|
1321
|
+
return () => mql.removeEventListener("change", onChange);
|
|
1322
|
+
}, [theme]);
|
|
1323
|
+
if (theme === "dark") return DARK_THEME;
|
|
1324
|
+
if (theme === "auto" && prefersDark) return DARK_THEME;
|
|
1325
|
+
return LIGHT_THEME;
|
|
1326
|
+
}
|
|
1327
|
+
var DEFAULT_MESSAGE = "We use cookies to understand ad performance and improve how our marketing works across visits. You can accept or decline this tracking.";
|
|
1328
|
+
function ConsentBanner({
|
|
1329
|
+
message,
|
|
1330
|
+
title,
|
|
1331
|
+
acceptLabel = "Accept",
|
|
1332
|
+
declineLabel = "Decline",
|
|
1333
|
+
policyHref,
|
|
1334
|
+
policyLabel = "Learn more",
|
|
1335
|
+
onAccept,
|
|
1336
|
+
onDecline,
|
|
1337
|
+
position = "bottom",
|
|
1338
|
+
theme = "light",
|
|
1339
|
+
className,
|
|
1340
|
+
style
|
|
1341
|
+
} = {}) {
|
|
1342
|
+
const { isPending, accept, decline } = useConsent();
|
|
1343
|
+
const tokens = useResolvedTheme(theme);
|
|
1344
|
+
const [hasMounted, setHasMounted] = (0, import_react2.useState)(false);
|
|
1345
|
+
(0, import_react2.useEffect)(() => {
|
|
1346
|
+
setHasMounted(true);
|
|
1347
|
+
}, []);
|
|
1348
|
+
if (!hasMounted || !isPending) return null;
|
|
1349
|
+
const wrapperStyle = {
|
|
1350
|
+
position: "fixed",
|
|
1351
|
+
left: 0,
|
|
1352
|
+
right: 0,
|
|
1353
|
+
[position]: 0,
|
|
1354
|
+
zIndex: 2147483640,
|
|
1355
|
+
background: tokens.background,
|
|
1356
|
+
color: tokens.text,
|
|
1357
|
+
borderTop: position === "bottom" ? `1px solid ${tokens.border}` : "none",
|
|
1358
|
+
borderBottom: position === "top" ? `1px solid ${tokens.border}` : "none",
|
|
1359
|
+
boxShadow: tokens.shadow,
|
|
1360
|
+
padding: "16px 20px",
|
|
1361
|
+
boxSizing: "border-box",
|
|
1362
|
+
animation: `${ANIMATION_NAME}-${position} 200ms ease-out`,
|
|
1363
|
+
fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
1364
|
+
...style
|
|
1365
|
+
};
|
|
1366
|
+
const innerStyle = {
|
|
1367
|
+
maxWidth: 1100,
|
|
1368
|
+
margin: "0 auto",
|
|
1369
|
+
display: "flex",
|
|
1370
|
+
flexWrap: "wrap",
|
|
1371
|
+
gap: 16,
|
|
1372
|
+
alignItems: "center",
|
|
1373
|
+
justifyContent: "space-between"
|
|
1374
|
+
};
|
|
1375
|
+
const messageStyle = {
|
|
1376
|
+
flex: "1 1 320px",
|
|
1377
|
+
margin: 0,
|
|
1378
|
+
fontSize: 14,
|
|
1379
|
+
lineHeight: 1.5,
|
|
1380
|
+
color: tokens.mutedText
|
|
1381
|
+
};
|
|
1382
|
+
const titleStyle = {
|
|
1383
|
+
margin: "0 0 4px 0",
|
|
1384
|
+
fontSize: 14,
|
|
1385
|
+
fontWeight: 600,
|
|
1386
|
+
color: tokens.text
|
|
1387
|
+
};
|
|
1388
|
+
const actionsStyle = {
|
|
1389
|
+
display: "flex",
|
|
1390
|
+
gap: 8,
|
|
1391
|
+
flexShrink: 0
|
|
1392
|
+
};
|
|
1393
|
+
const buttonBase = {
|
|
1394
|
+
appearance: "none",
|
|
1395
|
+
fontFamily: "inherit",
|
|
1396
|
+
fontSize: 14,
|
|
1397
|
+
fontWeight: 500,
|
|
1398
|
+
padding: "8px 16px",
|
|
1399
|
+
borderRadius: 6,
|
|
1400
|
+
cursor: "pointer",
|
|
1401
|
+
border: "1px solid transparent",
|
|
1402
|
+
transition: "opacity 120ms ease"
|
|
1403
|
+
};
|
|
1404
|
+
const declineStyle = {
|
|
1405
|
+
...buttonBase,
|
|
1406
|
+
background: tokens.declineBg,
|
|
1407
|
+
color: tokens.declineText,
|
|
1408
|
+
borderColor: tokens.declineBorder
|
|
1409
|
+
};
|
|
1410
|
+
const acceptStyle = {
|
|
1411
|
+
...buttonBase,
|
|
1412
|
+
background: tokens.acceptBg,
|
|
1413
|
+
color: tokens.acceptText
|
|
1414
|
+
};
|
|
1415
|
+
const linkStyle = {
|
|
1416
|
+
color: tokens.linkColor,
|
|
1417
|
+
textDecoration: "underline",
|
|
1418
|
+
textUnderlineOffset: 2
|
|
1419
|
+
};
|
|
1420
|
+
const handleAccept = () => {
|
|
1421
|
+
accept();
|
|
1422
|
+
onAccept?.();
|
|
1423
|
+
};
|
|
1424
|
+
const handleDecline = () => {
|
|
1425
|
+
decline();
|
|
1426
|
+
onDecline?.();
|
|
1427
|
+
};
|
|
1428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1429
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: ANIMATION_KEYFRAMES }),
|
|
1430
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1431
|
+
"div",
|
|
1432
|
+
{
|
|
1433
|
+
role: "dialog",
|
|
1434
|
+
"aria-live": "polite",
|
|
1435
|
+
"aria-label": "Cookie consent",
|
|
1436
|
+
className,
|
|
1437
|
+
style: wrapperStyle,
|
|
1438
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: innerStyle, children: [
|
|
1439
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { flex: "1 1 320px" }, children: [
|
|
1440
|
+
title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: titleStyle, children: title }) : null,
|
|
1441
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: messageStyle, children: [
|
|
1442
|
+
message ?? DEFAULT_MESSAGE,
|
|
1443
|
+
policyHref ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1444
|
+
" ",
|
|
1445
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: policyHref, style: linkStyle, children: policyLabel })
|
|
1446
|
+
] }) : null
|
|
1447
|
+
] })
|
|
1448
|
+
] }),
|
|
1449
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: actionsStyle, children: [
|
|
1450
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: handleDecline, style: declineStyle, children: declineLabel }),
|
|
1451
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: handleAccept, style: acceptStyle, children: acceptLabel })
|
|
1452
|
+
] })
|
|
1453
|
+
] })
|
|
1454
|
+
}
|
|
1455
|
+
)
|
|
1456
|
+
] });
|
|
1457
|
+
}
|
|
1458
|
+
var ANIMATION_NAME = "aranova-consent-banner";
|
|
1459
|
+
var ANIMATION_KEYFRAMES = `
|
|
1460
|
+
@keyframes ${ANIMATION_NAME}-bottom {
|
|
1461
|
+
from { transform: translateY(100%); opacity: 0; }
|
|
1462
|
+
to { transform: translateY(0); opacity: 1; }
|
|
1463
|
+
}
|
|
1464
|
+
@keyframes ${ANIMATION_NAME}-top {
|
|
1465
|
+
from { transform: translateY(-100%); opacity: 0; }
|
|
1466
|
+
to { transform: translateY(0); opacity: 1; }
|
|
1297
1467
|
}
|
|
1468
|
+
`;
|
|
1298
1469
|
|
|
1299
1470
|
// src/GoogleAdsTracking.tsx
|
|
1300
1471
|
var import_script = __toESM(require("next/script"));
|
|
@@ -1323,7 +1494,7 @@ function GoogleAdsTracking(props) {
|
|
|
1323
1494
|
var import_navigation = require("next/navigation");
|
|
1324
1495
|
|
|
1325
1496
|
// package.json
|
|
1326
|
-
var version = "0.9.
|
|
1497
|
+
var version = "0.9.1";
|
|
1327
1498
|
|
|
1328
1499
|
// src/factory.tsx
|
|
1329
1500
|
var import_react3 = require("react");
|
|
@@ -1543,8 +1714,10 @@ function createTracking(options) {
|
|
|
1543
1714
|
formatMoney,
|
|
1544
1715
|
fromMinor,
|
|
1545
1716
|
getConsentState,
|
|
1717
|
+
resetConsent,
|
|
1546
1718
|
setConsentState,
|
|
1547
1719
|
toMinor,
|
|
1720
|
+
useConsent,
|
|
1548
1721
|
useConsentState,
|
|
1549
1722
|
useGclid,
|
|
1550
1723
|
useTrackingParams
|