@aranova/tracking-next 0.8.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 +164 -7
- package/dist/index.d.ts +164 -7
- 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.mjs
CHANGED
|
@@ -25,6 +25,12 @@ function setConsentState(state) {
|
|
|
25
25
|
if (typeof window.gtag === "function")
|
|
26
26
|
window.gtag("consent", "update", buildConsentPayload(state));
|
|
27
27
|
}
|
|
28
|
+
function resetConsent() {
|
|
29
|
+
if (typeof window === "undefined")
|
|
30
|
+
return;
|
|
31
|
+
window.localStorage.removeItem(CONSENT_STATE_KEY);
|
|
32
|
+
window.localStorage.removeItem(CONSENT_TIMESTAMP_KEY);
|
|
33
|
+
}
|
|
28
34
|
|
|
29
35
|
// ../tracking-core/src/payloads.ts
|
|
30
36
|
function createTrackingClientContext(surface, input = {}) {
|
|
@@ -1166,92 +1172,255 @@ function formatMoney(cents, currency, locale) {
|
|
|
1166
1172
|
}
|
|
1167
1173
|
|
|
1168
1174
|
// src/ConsentBanner.tsx
|
|
1169
|
-
import { useEffect, useState } from "react";
|
|
1170
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1171
|
-
function ConsentBanner() {
|
|
1172
|
-
const [consentState, setBannerConsentState] = useState("pending");
|
|
1173
|
-
const [isReady, setIsReady] = useState(false);
|
|
1174
|
-
useEffect(() => {
|
|
1175
|
-
setBannerConsentState(getConsentState());
|
|
1176
|
-
setIsReady(true);
|
|
1177
|
-
}, []);
|
|
1178
|
-
if (!isReady || consentState !== "pending")
|
|
1179
|
-
return null;
|
|
1180
|
-
const handleAccept = () => {
|
|
1181
|
-
setConsentState("granted");
|
|
1182
|
-
setBannerConsentState("granted");
|
|
1183
|
-
};
|
|
1184
|
-
const handleDecline = () => {
|
|
1185
|
-
setConsentState("denied");
|
|
1186
|
-
setBannerConsentState("denied");
|
|
1187
|
-
};
|
|
1188
|
-
return /* @__PURE__ */ 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__ */ jsxs("div", { className: "mx-auto flex max-w-5xl flex-col gap-4 md:flex-row md:items-center md:justify-between", children: [
|
|
1189
|
-
/* @__PURE__ */ 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." }),
|
|
1190
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row", children: [
|
|
1191
|
-
/* @__PURE__ */ jsx(
|
|
1192
|
-
"button",
|
|
1193
|
-
{
|
|
1194
|
-
type: "button",
|
|
1195
|
-
onClick: handleDecline,
|
|
1196
|
-
className: "rounded-md border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 transition hover:bg-gray-100",
|
|
1197
|
-
children: "Decline"
|
|
1198
|
-
}
|
|
1199
|
-
),
|
|
1200
|
-
/* @__PURE__ */ jsx(
|
|
1201
|
-
"button",
|
|
1202
|
-
{
|
|
1203
|
-
type: "button",
|
|
1204
|
-
onClick: handleAccept,
|
|
1205
|
-
className: "rounded-md bg-gray-900 px-4 py-2 text-sm font-medium text-white transition hover:bg-gray-800",
|
|
1206
|
-
children: "Accept"
|
|
1207
|
-
}
|
|
1208
|
-
)
|
|
1209
|
-
] })
|
|
1210
|
-
] }) });
|
|
1211
|
-
}
|
|
1175
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
1212
1176
|
|
|
1213
1177
|
// src/hooks.ts
|
|
1214
|
-
import { useEffect
|
|
1178
|
+
import { useCallback, useEffect, useState } from "react";
|
|
1215
1179
|
function useGclid() {
|
|
1216
|
-
const [gclid, setGclid] =
|
|
1217
|
-
|
|
1180
|
+
const [gclid, setGclid] = useState(null);
|
|
1181
|
+
useEffect(() => {
|
|
1218
1182
|
setGclid(getCookieValueFromDocument("gclid"));
|
|
1219
1183
|
}, []);
|
|
1220
1184
|
return gclid;
|
|
1221
1185
|
}
|
|
1222
1186
|
function useTrackingParams() {
|
|
1223
|
-
const [trackingParams, setTrackingParams] =
|
|
1224
|
-
|
|
1187
|
+
const [trackingParams, setTrackingParams] = useState(createEmptyTrackingParams());
|
|
1188
|
+
useEffect(() => {
|
|
1225
1189
|
setTrackingParams(getTrackingParamsFromCookieReader(getCookieValueFromDocument));
|
|
1226
1190
|
}, []);
|
|
1227
1191
|
return trackingParams;
|
|
1228
1192
|
}
|
|
1229
1193
|
function useConsentState() {
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1194
|
+
return useConsent().state;
|
|
1195
|
+
}
|
|
1196
|
+
function useConsent() {
|
|
1197
|
+
const [state, setState] = useState("pending");
|
|
1198
|
+
useEffect(() => {
|
|
1199
|
+
setState(getConsentState());
|
|
1233
1200
|
const handleStorage = (event) => {
|
|
1234
|
-
if (event.key ===
|
|
1235
|
-
setConsentStateValue(getConsentState());
|
|
1201
|
+
if (event.key === CONSENT_STATE_KEY) setState(getConsentState());
|
|
1236
1202
|
};
|
|
1237
1203
|
window.addEventListener("storage", handleStorage);
|
|
1238
|
-
return () =>
|
|
1239
|
-
|
|
1240
|
-
|
|
1204
|
+
return () => window.removeEventListener("storage", handleStorage);
|
|
1205
|
+
}, []);
|
|
1206
|
+
const accept = useCallback(() => {
|
|
1207
|
+
setConsentState("granted");
|
|
1208
|
+
setState("granted");
|
|
1209
|
+
}, []);
|
|
1210
|
+
const decline = useCallback(() => {
|
|
1211
|
+
setConsentState("denied");
|
|
1212
|
+
setState("denied");
|
|
1241
1213
|
}, []);
|
|
1242
|
-
|
|
1214
|
+
const reset = useCallback(() => {
|
|
1215
|
+
resetConsent();
|
|
1216
|
+
setState("pending");
|
|
1217
|
+
}, []);
|
|
1218
|
+
return {
|
|
1219
|
+
state,
|
|
1220
|
+
isPending: state === "pending",
|
|
1221
|
+
isGranted: state === "granted",
|
|
1222
|
+
isDenied: state === "denied",
|
|
1223
|
+
accept,
|
|
1224
|
+
decline,
|
|
1225
|
+
reset
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
// src/ConsentBanner.tsx
|
|
1230
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
1231
|
+
var LIGHT_THEME = {
|
|
1232
|
+
background: "#ffffff",
|
|
1233
|
+
border: "#e5e7eb",
|
|
1234
|
+
text: "#111827",
|
|
1235
|
+
mutedText: "#4b5563",
|
|
1236
|
+
acceptBg: "#111827",
|
|
1237
|
+
acceptText: "#ffffff",
|
|
1238
|
+
declineBg: "transparent",
|
|
1239
|
+
declineText: "#111827",
|
|
1240
|
+
declineBorder: "#d1d5db",
|
|
1241
|
+
shadow: "0 -4px 16px -2px rgba(15, 23, 42, 0.08), 0 -2px 6px -1px rgba(15, 23, 42, 0.04)",
|
|
1242
|
+
linkColor: "#1f2937"
|
|
1243
|
+
};
|
|
1244
|
+
var DARK_THEME = {
|
|
1245
|
+
background: "#0f172a",
|
|
1246
|
+
border: "#1e293b",
|
|
1247
|
+
text: "#f1f5f9",
|
|
1248
|
+
mutedText: "#cbd5e1",
|
|
1249
|
+
acceptBg: "#f1f5f9",
|
|
1250
|
+
acceptText: "#0f172a",
|
|
1251
|
+
declineBg: "transparent",
|
|
1252
|
+
declineText: "#f1f5f9",
|
|
1253
|
+
declineBorder: "#334155",
|
|
1254
|
+
shadow: "0 -4px 16px -2px rgba(0, 0, 0, 0.5), 0 -2px 6px -1px rgba(0, 0, 0, 0.3)",
|
|
1255
|
+
linkColor: "#e2e8f0"
|
|
1256
|
+
};
|
|
1257
|
+
function useResolvedTheme(theme) {
|
|
1258
|
+
const [prefersDark, setPrefersDark] = useState2(false);
|
|
1259
|
+
useEffect2(() => {
|
|
1260
|
+
if (theme !== "auto" || typeof window === "undefined" || !window.matchMedia) return;
|
|
1261
|
+
const mql = window.matchMedia("(prefers-color-scheme: dark)");
|
|
1262
|
+
setPrefersDark(mql.matches);
|
|
1263
|
+
const onChange = (e) => setPrefersDark(e.matches);
|
|
1264
|
+
mql.addEventListener("change", onChange);
|
|
1265
|
+
return () => mql.removeEventListener("change", onChange);
|
|
1266
|
+
}, [theme]);
|
|
1267
|
+
if (theme === "dark") return DARK_THEME;
|
|
1268
|
+
if (theme === "auto" && prefersDark) return DARK_THEME;
|
|
1269
|
+
return LIGHT_THEME;
|
|
1270
|
+
}
|
|
1271
|
+
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.";
|
|
1272
|
+
function ConsentBanner({
|
|
1273
|
+
message,
|
|
1274
|
+
title,
|
|
1275
|
+
acceptLabel = "Accept",
|
|
1276
|
+
declineLabel = "Decline",
|
|
1277
|
+
policyHref,
|
|
1278
|
+
policyLabel = "Learn more",
|
|
1279
|
+
onAccept,
|
|
1280
|
+
onDecline,
|
|
1281
|
+
position = "bottom",
|
|
1282
|
+
theme = "light",
|
|
1283
|
+
className,
|
|
1284
|
+
style
|
|
1285
|
+
} = {}) {
|
|
1286
|
+
const { isPending, accept, decline } = useConsent();
|
|
1287
|
+
const tokens = useResolvedTheme(theme);
|
|
1288
|
+
const [hasMounted, setHasMounted] = useState2(false);
|
|
1289
|
+
useEffect2(() => {
|
|
1290
|
+
setHasMounted(true);
|
|
1291
|
+
}, []);
|
|
1292
|
+
if (!hasMounted || !isPending) return null;
|
|
1293
|
+
const wrapperStyle = {
|
|
1294
|
+
position: "fixed",
|
|
1295
|
+
left: 0,
|
|
1296
|
+
right: 0,
|
|
1297
|
+
[position]: 0,
|
|
1298
|
+
zIndex: 2147483640,
|
|
1299
|
+
background: tokens.background,
|
|
1300
|
+
color: tokens.text,
|
|
1301
|
+
borderTop: position === "bottom" ? `1px solid ${tokens.border}` : "none",
|
|
1302
|
+
borderBottom: position === "top" ? `1px solid ${tokens.border}` : "none",
|
|
1303
|
+
boxShadow: tokens.shadow,
|
|
1304
|
+
padding: "16px 20px",
|
|
1305
|
+
boxSizing: "border-box",
|
|
1306
|
+
animation: `${ANIMATION_NAME}-${position} 200ms ease-out`,
|
|
1307
|
+
fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
1308
|
+
...style
|
|
1309
|
+
};
|
|
1310
|
+
const innerStyle = {
|
|
1311
|
+
maxWidth: 1100,
|
|
1312
|
+
margin: "0 auto",
|
|
1313
|
+
display: "flex",
|
|
1314
|
+
flexWrap: "wrap",
|
|
1315
|
+
gap: 16,
|
|
1316
|
+
alignItems: "center",
|
|
1317
|
+
justifyContent: "space-between"
|
|
1318
|
+
};
|
|
1319
|
+
const messageStyle = {
|
|
1320
|
+
flex: "1 1 320px",
|
|
1321
|
+
margin: 0,
|
|
1322
|
+
fontSize: 14,
|
|
1323
|
+
lineHeight: 1.5,
|
|
1324
|
+
color: tokens.mutedText
|
|
1325
|
+
};
|
|
1326
|
+
const titleStyle = {
|
|
1327
|
+
margin: "0 0 4px 0",
|
|
1328
|
+
fontSize: 14,
|
|
1329
|
+
fontWeight: 600,
|
|
1330
|
+
color: tokens.text
|
|
1331
|
+
};
|
|
1332
|
+
const actionsStyle = {
|
|
1333
|
+
display: "flex",
|
|
1334
|
+
gap: 8,
|
|
1335
|
+
flexShrink: 0
|
|
1336
|
+
};
|
|
1337
|
+
const buttonBase = {
|
|
1338
|
+
appearance: "none",
|
|
1339
|
+
fontFamily: "inherit",
|
|
1340
|
+
fontSize: 14,
|
|
1341
|
+
fontWeight: 500,
|
|
1342
|
+
padding: "8px 16px",
|
|
1343
|
+
borderRadius: 6,
|
|
1344
|
+
cursor: "pointer",
|
|
1345
|
+
border: "1px solid transparent",
|
|
1346
|
+
transition: "opacity 120ms ease"
|
|
1347
|
+
};
|
|
1348
|
+
const declineStyle = {
|
|
1349
|
+
...buttonBase,
|
|
1350
|
+
background: tokens.declineBg,
|
|
1351
|
+
color: tokens.declineText,
|
|
1352
|
+
borderColor: tokens.declineBorder
|
|
1353
|
+
};
|
|
1354
|
+
const acceptStyle = {
|
|
1355
|
+
...buttonBase,
|
|
1356
|
+
background: tokens.acceptBg,
|
|
1357
|
+
color: tokens.acceptText
|
|
1358
|
+
};
|
|
1359
|
+
const linkStyle = {
|
|
1360
|
+
color: tokens.linkColor,
|
|
1361
|
+
textDecoration: "underline",
|
|
1362
|
+
textUnderlineOffset: 2
|
|
1363
|
+
};
|
|
1364
|
+
const handleAccept = () => {
|
|
1365
|
+
accept();
|
|
1366
|
+
onAccept?.();
|
|
1367
|
+
};
|
|
1368
|
+
const handleDecline = () => {
|
|
1369
|
+
decline();
|
|
1370
|
+
onDecline?.();
|
|
1371
|
+
};
|
|
1372
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1373
|
+
/* @__PURE__ */ jsx("style", { children: ANIMATION_KEYFRAMES }),
|
|
1374
|
+
/* @__PURE__ */ jsx(
|
|
1375
|
+
"div",
|
|
1376
|
+
{
|
|
1377
|
+
role: "dialog",
|
|
1378
|
+
"aria-live": "polite",
|
|
1379
|
+
"aria-label": "Cookie consent",
|
|
1380
|
+
className,
|
|
1381
|
+
style: wrapperStyle,
|
|
1382
|
+
children: /* @__PURE__ */ jsxs("div", { style: innerStyle, children: [
|
|
1383
|
+
/* @__PURE__ */ jsxs("div", { style: { flex: "1 1 320px" }, children: [
|
|
1384
|
+
title ? /* @__PURE__ */ jsx("p", { style: titleStyle, children: title }) : null,
|
|
1385
|
+
/* @__PURE__ */ jsxs("p", { style: messageStyle, children: [
|
|
1386
|
+
message ?? DEFAULT_MESSAGE,
|
|
1387
|
+
policyHref ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1388
|
+
" ",
|
|
1389
|
+
/* @__PURE__ */ jsx("a", { href: policyHref, style: linkStyle, children: policyLabel })
|
|
1390
|
+
] }) : null
|
|
1391
|
+
] })
|
|
1392
|
+
] }),
|
|
1393
|
+
/* @__PURE__ */ jsxs("div", { style: actionsStyle, children: [
|
|
1394
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: handleDecline, style: declineStyle, children: declineLabel }),
|
|
1395
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: handleAccept, style: acceptStyle, children: acceptLabel })
|
|
1396
|
+
] })
|
|
1397
|
+
] })
|
|
1398
|
+
}
|
|
1399
|
+
)
|
|
1400
|
+
] });
|
|
1401
|
+
}
|
|
1402
|
+
var ANIMATION_NAME = "aranova-consent-banner";
|
|
1403
|
+
var ANIMATION_KEYFRAMES = `
|
|
1404
|
+
@keyframes ${ANIMATION_NAME}-bottom {
|
|
1405
|
+
from { transform: translateY(100%); opacity: 0; }
|
|
1406
|
+
to { transform: translateY(0); opacity: 1; }
|
|
1407
|
+
}
|
|
1408
|
+
@keyframes ${ANIMATION_NAME}-top {
|
|
1409
|
+
from { transform: translateY(-100%); opacity: 0; }
|
|
1410
|
+
to { transform: translateY(0); opacity: 1; }
|
|
1243
1411
|
}
|
|
1412
|
+
`;
|
|
1244
1413
|
|
|
1245
1414
|
// src/GoogleAdsTracking.tsx
|
|
1246
1415
|
import Script from "next/script";
|
|
1247
|
-
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1416
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1248
1417
|
function GoogleAdsTracking(props) {
|
|
1249
1418
|
const { gtagId, gtagIds } = props;
|
|
1250
1419
|
const allIds = gtagIds ? Object.values(gtagIds) : gtagId ? [gtagId] : [];
|
|
1251
1420
|
if (allIds.length === 0) return null;
|
|
1252
1421
|
const loaderId = allIds[0];
|
|
1253
1422
|
const initScript = allIds.length === 1 ? createGtagInitScript(allIds[0]) : createGtagInitScriptMulti(allIds);
|
|
1254
|
-
return /* @__PURE__ */ jsxs2(
|
|
1423
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1255
1424
|
/* @__PURE__ */ jsx2(Script, { id: "consent-default", strategy: "beforeInteractive", children: createConsentDefaultScript() }),
|
|
1256
1425
|
/* @__PURE__ */ jsx2(
|
|
1257
1426
|
Script,
|
|
@@ -1269,7 +1438,7 @@ function GoogleAdsTracking(props) {
|
|
|
1269
1438
|
import { usePathname, useSearchParams } from "next/navigation";
|
|
1270
1439
|
|
|
1271
1440
|
// package.json
|
|
1272
|
-
var version = "0.
|
|
1441
|
+
var version = "0.9.1";
|
|
1273
1442
|
|
|
1274
1443
|
// src/factory.tsx
|
|
1275
1444
|
import {
|
|
@@ -1494,8 +1663,10 @@ export {
|
|
|
1494
1663
|
formatMoney,
|
|
1495
1664
|
fromMinor,
|
|
1496
1665
|
getConsentState,
|
|
1666
|
+
resetConsent,
|
|
1497
1667
|
setConsentState,
|
|
1498
1668
|
toMinor,
|
|
1669
|
+
useConsent,
|
|
1499
1670
|
useConsentState,
|
|
1500
1671
|
useGclid,
|
|
1501
1672
|
useTrackingParams
|