@jitsu/js 1.9.11 → 1.9.13-canary.1167.20250215132227
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/.turbo/turbo-build.log +67 -67
- package/.turbo/turbo-clean.log +5 -5
- package/.turbo/turbo-test.log +1091 -461
- package/__tests__/node/nodejs.test.ts +27 -0
- package/__tests__/playwright/cases/anonymous-id-bug.html +26 -0
- package/__tests__/playwright/cases/basic.html +5 -0
- package/__tests__/playwright/integration.test.ts +43 -0
- package/dist/jitsu.cjs.js +18 -4
- package/dist/jitsu.es.js +18 -4
- package/dist/web/p.js.txt +18 -4
- package/package.json +6 -6
- package/src/analytics-plugin.ts +31 -9
|
@@ -214,6 +214,33 @@ describe("Test Jitsu NodeJS client", () => {
|
|
|
214
214
|
expect((p.body.anonymousId ?? "").length).toBeGreaterThan(0);
|
|
215
215
|
});
|
|
216
216
|
|
|
217
|
+
test("test defaultPayloadContext", async () => {
|
|
218
|
+
const config = {
|
|
219
|
+
host: server.baseUrl,
|
|
220
|
+
writeKey: "key:secret",
|
|
221
|
+
debug: true,
|
|
222
|
+
defaultPayloadContext: {
|
|
223
|
+
awesomeIdentifier: "awesome-identifier",
|
|
224
|
+
awesome: {
|
|
225
|
+
nestedKey: "awesome-key",
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
const client = jitsuAnalytics(config);
|
|
230
|
+
expect(requestLog.length).toBe(0);
|
|
231
|
+
await client.identify("myUserId", { email: "myUserId@example.com" });
|
|
232
|
+
await client.group("myGroupId", { name: "myGroupId" });
|
|
233
|
+
await client.track("myEvent", { prop1: "value1" });
|
|
234
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
235
|
+
expect(requestLog.length).toBe(3);
|
|
236
|
+
expect(requestLog[0].body.context.awesomeIdentifier).toBe("awesome-identifier");
|
|
237
|
+
expect(requestLog[0].body.context.awesome.nestedKey).toBe("awesome-key");
|
|
238
|
+
expect(requestLog[1].body.context.awesomeIdentifier).toBe("awesome-identifier");
|
|
239
|
+
expect(requestLog[1].body.context.awesome.nestedKey).toBe("awesome-key");
|
|
240
|
+
expect(requestLog[2].body.context.awesomeIdentifier).toBe("awesome-identifier");
|
|
241
|
+
expect(requestLog[2].body.context.awesome.nestedKey).toBe("awesome-key");
|
|
242
|
+
});
|
|
243
|
+
|
|
217
244
|
test("node js", async () => {
|
|
218
245
|
const jitsu: AnalyticsInterface = jitsuAnalytics({
|
|
219
246
|
writeKey: "key:secret",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
|
|
3
|
+
<html lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
|
|
8
|
+
<title>Tracking page</title>
|
|
9
|
+
<script>
|
|
10
|
+
window.testOnload = async j => {
|
|
11
|
+
j.track("pageLoaded");
|
|
12
|
+
};
|
|
13
|
+
</script>
|
|
14
|
+
<script
|
|
15
|
+
type="text/javascript"
|
|
16
|
+
src="<%=trackingBase%>/p.js"
|
|
17
|
+
data-onload="testOnload"
|
|
18
|
+
data-debug="true"
|
|
19
|
+
defer
|
|
20
|
+
></script>
|
|
21
|
+
</head>
|
|
22
|
+
|
|
23
|
+
<body>
|
|
24
|
+
<h1>Test</h1>
|
|
25
|
+
</body>
|
|
26
|
+
</html>
|
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
|
|
8
8
|
<title>Tracking page</title>
|
|
9
9
|
<script>
|
|
10
|
+
window.jitsuConfig = {
|
|
11
|
+
cookieCapture: {
|
|
12
|
+
ttp: "_ttp",
|
|
13
|
+
},
|
|
14
|
+
};
|
|
10
15
|
window.testOnload = async j => {
|
|
11
16
|
j.identify("john-doe-id-1", { email: "john.doe@gmail.com" });
|
|
12
17
|
j.track("pageLoaded", { trackParam: "trackValue" });
|
|
@@ -450,9 +450,46 @@ test("disable-user-ids-then-consent", async ({ browser }) => {
|
|
|
450
450
|
expect((p.body.anonymousId ?? "").length).toBeGreaterThan(0);
|
|
451
451
|
});
|
|
452
452
|
|
|
453
|
+
test("anonymous-id-bug", async ({ browser }) => {
|
|
454
|
+
clearRequestLog();
|
|
455
|
+
const anonymousId = "1724633695283.638279";
|
|
456
|
+
const browserContext = await browser.newContext();
|
|
457
|
+
await browserContext.addCookies([{ name: "__eventn_id", value: anonymousId, url: server.baseUrl }]);
|
|
458
|
+
const { page, uncaughtErrors } = await createLoggingPage(browserContext);
|
|
459
|
+
const [pageResult] = await Promise.all([page.goto(`${server.baseUrl}/anonymous-id-bug.html`)]);
|
|
460
|
+
await page.waitForFunction(() => window["jitsu"] !== undefined, undefined, {
|
|
461
|
+
timeout: 1000,
|
|
462
|
+
polling: 100,
|
|
463
|
+
});
|
|
464
|
+
expect(pageResult.status()).toBe(200);
|
|
465
|
+
const cookies = (await browserContext.cookies()).reduce(
|
|
466
|
+
(res, cookie) => ({
|
|
467
|
+
...res,
|
|
468
|
+
[cookie.name]: cookie.value,
|
|
469
|
+
}),
|
|
470
|
+
{}
|
|
471
|
+
);
|
|
472
|
+
console.log("🍪 Jitsu Cookies", cookies);
|
|
473
|
+
//wait for some time since the server has an artificial latency of 30ms
|
|
474
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
475
|
+
expect(uncaughtErrors.length).toEqual(0);
|
|
476
|
+
console.log(
|
|
477
|
+
`📝 Request log size of ${requestLog.length}`,
|
|
478
|
+
requestLog.map(x => describeEvent(x.type, x.body))
|
|
479
|
+
);
|
|
480
|
+
const p = requestLog[0];
|
|
481
|
+
console.log(chalk.bold("📝 Checking page event"), JSON.stringify(p, null, 3));
|
|
482
|
+
expect(p.body.anonymousId).toEqual(anonymousId);
|
|
483
|
+
});
|
|
484
|
+
|
|
453
485
|
test("basic", async ({ browser }) => {
|
|
454
486
|
clearRequestLog();
|
|
455
487
|
const browserContext = await browser.newContext();
|
|
488
|
+
await browserContext.addCookies([
|
|
489
|
+
{ name: "_fbc", value: "fbc-id", url: server.baseUrl },
|
|
490
|
+
{ name: "_fbp", value: "fbp-id", url: server.baseUrl },
|
|
491
|
+
{ name: "_ttp", value: "ttp-id", url: server.baseUrl },
|
|
492
|
+
]);
|
|
456
493
|
|
|
457
494
|
const { page: firstPage, uncaughtErrors: firstPageErrors } = await createLoggingPage(browserContext);
|
|
458
495
|
const [pageResult] = await Promise.all([
|
|
@@ -498,6 +535,9 @@ test("basic", async ({ browser }) => {
|
|
|
498
535
|
console.log(chalk.bold("📝 Checking track event"), JSON.stringify(track, null, 3));
|
|
499
536
|
expect(track.properties.trackParam).toEqual("trackValue");
|
|
500
537
|
expect(track.type).toEqual("track");
|
|
538
|
+
expect(track.context.clientIds).toHaveProperty("fbc", "fbc-id");
|
|
539
|
+
expect(track.context.clientIds).toHaveProperty("fbp", "fbp-id");
|
|
540
|
+
expect(track.context.clientIds).toHaveProperty("ttp", "ttp-id");
|
|
501
541
|
expect(track.context.traits.email).toEqual("john.doe@gmail.com");
|
|
502
542
|
expect(track.userId).toEqual("john-doe-id-1");
|
|
503
543
|
expect(track.event).toEqual("pageLoaded");
|
|
@@ -509,6 +549,9 @@ test("basic", async ({ browser }) => {
|
|
|
509
549
|
|
|
510
550
|
console.log(chalk.bold("📝 Checking page event"), JSON.stringify(page, null, 3));
|
|
511
551
|
expect(page.anonymousId).toEqual(anonymousId);
|
|
552
|
+
expect(page.context.clientIds).toHaveProperty("fbc", "fbc-id");
|
|
553
|
+
expect(page.context.clientIds).toHaveProperty("fbp", "fbp-id");
|
|
554
|
+
expect(page.context.clientIds).toHaveProperty("ttp", "ttp-id");
|
|
512
555
|
expect(page.context.traits.email).toEqual("john.doe@gmail.com");
|
|
513
556
|
expect(page.userId).toEqual("john-doe-id-1");
|
|
514
557
|
|
package/dist/jitsu.cjs.js
CHANGED
|
@@ -1061,11 +1061,13 @@ const defaultConfig = {
|
|
|
1061
1061
|
fetch: null,
|
|
1062
1062
|
echoEvents: false,
|
|
1063
1063
|
cookieDomain: undefined,
|
|
1064
|
+
cookieCapture: {},
|
|
1064
1065
|
runtime: undefined,
|
|
1065
1066
|
fetchTimeoutMs: undefined,
|
|
1066
1067
|
s2s: undefined,
|
|
1067
1068
|
idEndpoint: undefined,
|
|
1068
1069
|
errorPolicy: "log",
|
|
1070
|
+
defaultPayloadContext: {},
|
|
1069
1071
|
privacy: {
|
|
1070
1072
|
dontSend: false,
|
|
1071
1073
|
disableUserIds: false,
|
|
@@ -1150,6 +1152,14 @@ function getCookie(name) {
|
|
|
1150
1152
|
const parts = value.split(`; ${name}=`);
|
|
1151
1153
|
return parts.length === 2 ? parts.pop().split(";").shift() : undefined;
|
|
1152
1154
|
}
|
|
1155
|
+
function getClientIds(runtime, customCookieCapture) {
|
|
1156
|
+
const cookieCapture = Object.assign({ fbc: "_fbc", fbp: "_fbp" }, customCookieCapture);
|
|
1157
|
+
const clientIds = Object.entries(cookieCapture).reduce((acc, [key, cookieName]) => {
|
|
1158
|
+
acc[key] = runtime.getCookie(cookieName);
|
|
1159
|
+
return acc;
|
|
1160
|
+
}, {});
|
|
1161
|
+
return Object.assign(Object.assign({}, clientIds), getGa4Ids(runtime));
|
|
1162
|
+
}
|
|
1153
1163
|
function getGa4Ids(runtime) {
|
|
1154
1164
|
var _a;
|
|
1155
1165
|
const allCookies = runtime.getCookies();
|
|
@@ -1227,6 +1237,10 @@ const cookieStorage = (cookieDomain, key2cookie) => {
|
|
|
1227
1237
|
getItem(key) {
|
|
1228
1238
|
const cookieName = key2cookie[key] || key;
|
|
1229
1239
|
const result = getCookie(cookieName);
|
|
1240
|
+
if (key === "__anon_id") {
|
|
1241
|
+
//anonymous id must always be a string, so we don't parse it to preserve its exact value
|
|
1242
|
+
return result;
|
|
1243
|
+
}
|
|
1230
1244
|
if (typeof result === "undefined" && key === "__user_id") {
|
|
1231
1245
|
//backward compatibility with old jitsu cookie. get user id if from traits
|
|
1232
1246
|
const traits = parse(getCookie("__eventn_id_usr")) || {};
|
|
@@ -1413,7 +1427,7 @@ function adjustPayload(payload, config, storage, s2s) {
|
|
|
1413
1427
|
properties.url = targetUrl.replace(hashRegex, "");
|
|
1414
1428
|
properties.path = fixPath(urlPath(targetUrl));
|
|
1415
1429
|
}
|
|
1416
|
-
const customContext = ((_a = payload.properties) === null || _a === void 0 ? void 0 : _a.context) || ((_b = payload.options) === null || _b === void 0 ? void 0 : _b.context) || {};
|
|
1430
|
+
const customContext = deepMerge(config.defaultPayloadContext, ((_a = payload.properties) === null || _a === void 0 ? void 0 : _a.context) || ((_b = payload.options) === null || _b === void 0 ? void 0 : _b.context) || {});
|
|
1417
1431
|
(_c = payload.properties) === null || _c === void 0 ? true : delete _c.context;
|
|
1418
1432
|
const referrer = runtime.referrer();
|
|
1419
1433
|
const context = {
|
|
@@ -1441,8 +1455,7 @@ function adjustPayload(payload, config, storage, s2s) {
|
|
|
1441
1455
|
url: properties.url || url,
|
|
1442
1456
|
encoding: properties.encoding || runtime.documentEncoding(),
|
|
1443
1457
|
},
|
|
1444
|
-
clientIds: !((_e = config.privacy) === null || _e === void 0 ? void 0 : _e.disableUserIds)
|
|
1445
|
-
? Object.assign({ fbc: runtime.getCookie("_fbc"), fbp: runtime.getCookie("_fbp") }, getGa4Ids(runtime)) : undefined,
|
|
1458
|
+
clientIds: !((_e = config.privacy) === null || _e === void 0 ? void 0 : _e.disableUserIds) ? getClientIds(runtime, config.cookieCapture) : undefined,
|
|
1446
1459
|
campaign: parseUtms(query),
|
|
1447
1460
|
};
|
|
1448
1461
|
const withContext = Object.assign(Object.assign({}, payload), { timestamp: new Date().toISOString(), sentAt: new Date().toISOString(), messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)), writeKey: maskWriteKey(config.writeKey), groupId: storage.getItem("__group_id"), context: deepMerge(context, customContext) });
|
|
@@ -1630,7 +1643,8 @@ function send(method, payload, jitsuConfig, instance, store) {
|
|
|
1630
1643
|
console.log(`[JITSU DEBUG] ${url} replied ${fetchResult.status}: ${responseText}. Original payload:\n${JSON.stringify(adjustedPayload, null, 2)}`);
|
|
1631
1644
|
}
|
|
1632
1645
|
if (!fetchResult.ok) {
|
|
1633
|
-
|
|
1646
|
+
getErrorHandler(jitsuConfig)(`Call to ${url} failed with error: ${fetchResult.status} - ${fetchResult.statusText}: ${responseText}`);
|
|
1647
|
+
return Promise.resolve();
|
|
1634
1648
|
}
|
|
1635
1649
|
let responseJson;
|
|
1636
1650
|
try {
|
package/dist/jitsu.es.js
CHANGED
|
@@ -1059,11 +1059,13 @@ const defaultConfig = {
|
|
|
1059
1059
|
fetch: null,
|
|
1060
1060
|
echoEvents: false,
|
|
1061
1061
|
cookieDomain: undefined,
|
|
1062
|
+
cookieCapture: {},
|
|
1062
1063
|
runtime: undefined,
|
|
1063
1064
|
fetchTimeoutMs: undefined,
|
|
1064
1065
|
s2s: undefined,
|
|
1065
1066
|
idEndpoint: undefined,
|
|
1066
1067
|
errorPolicy: "log",
|
|
1068
|
+
defaultPayloadContext: {},
|
|
1067
1069
|
privacy: {
|
|
1068
1070
|
dontSend: false,
|
|
1069
1071
|
disableUserIds: false,
|
|
@@ -1148,6 +1150,14 @@ function getCookie(name) {
|
|
|
1148
1150
|
const parts = value.split(`; ${name}=`);
|
|
1149
1151
|
return parts.length === 2 ? parts.pop().split(";").shift() : undefined;
|
|
1150
1152
|
}
|
|
1153
|
+
function getClientIds(runtime, customCookieCapture) {
|
|
1154
|
+
const cookieCapture = Object.assign({ fbc: "_fbc", fbp: "_fbp" }, customCookieCapture);
|
|
1155
|
+
const clientIds = Object.entries(cookieCapture).reduce((acc, [key, cookieName]) => {
|
|
1156
|
+
acc[key] = runtime.getCookie(cookieName);
|
|
1157
|
+
return acc;
|
|
1158
|
+
}, {});
|
|
1159
|
+
return Object.assign(Object.assign({}, clientIds), getGa4Ids(runtime));
|
|
1160
|
+
}
|
|
1151
1161
|
function getGa4Ids(runtime) {
|
|
1152
1162
|
var _a;
|
|
1153
1163
|
const allCookies = runtime.getCookies();
|
|
@@ -1225,6 +1235,10 @@ const cookieStorage = (cookieDomain, key2cookie) => {
|
|
|
1225
1235
|
getItem(key) {
|
|
1226
1236
|
const cookieName = key2cookie[key] || key;
|
|
1227
1237
|
const result = getCookie(cookieName);
|
|
1238
|
+
if (key === "__anon_id") {
|
|
1239
|
+
//anonymous id must always be a string, so we don't parse it to preserve its exact value
|
|
1240
|
+
return result;
|
|
1241
|
+
}
|
|
1228
1242
|
if (typeof result === "undefined" && key === "__user_id") {
|
|
1229
1243
|
//backward compatibility with old jitsu cookie. get user id if from traits
|
|
1230
1244
|
const traits = parse(getCookie("__eventn_id_usr")) || {};
|
|
@@ -1411,7 +1425,7 @@ function adjustPayload(payload, config, storage, s2s) {
|
|
|
1411
1425
|
properties.url = targetUrl.replace(hashRegex, "");
|
|
1412
1426
|
properties.path = fixPath(urlPath(targetUrl));
|
|
1413
1427
|
}
|
|
1414
|
-
const customContext = ((_a = payload.properties) === null || _a === void 0 ? void 0 : _a.context) || ((_b = payload.options) === null || _b === void 0 ? void 0 : _b.context) || {};
|
|
1428
|
+
const customContext = deepMerge(config.defaultPayloadContext, ((_a = payload.properties) === null || _a === void 0 ? void 0 : _a.context) || ((_b = payload.options) === null || _b === void 0 ? void 0 : _b.context) || {});
|
|
1415
1429
|
(_c = payload.properties) === null || _c === void 0 ? true : delete _c.context;
|
|
1416
1430
|
const referrer = runtime.referrer();
|
|
1417
1431
|
const context = {
|
|
@@ -1439,8 +1453,7 @@ function adjustPayload(payload, config, storage, s2s) {
|
|
|
1439
1453
|
url: properties.url || url,
|
|
1440
1454
|
encoding: properties.encoding || runtime.documentEncoding(),
|
|
1441
1455
|
},
|
|
1442
|
-
clientIds: !((_e = config.privacy) === null || _e === void 0 ? void 0 : _e.disableUserIds)
|
|
1443
|
-
? Object.assign({ fbc: runtime.getCookie("_fbc"), fbp: runtime.getCookie("_fbp") }, getGa4Ids(runtime)) : undefined,
|
|
1456
|
+
clientIds: !((_e = config.privacy) === null || _e === void 0 ? void 0 : _e.disableUserIds) ? getClientIds(runtime, config.cookieCapture) : undefined,
|
|
1444
1457
|
campaign: parseUtms(query),
|
|
1445
1458
|
};
|
|
1446
1459
|
const withContext = Object.assign(Object.assign({}, payload), { timestamp: new Date().toISOString(), sentAt: new Date().toISOString(), messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)), writeKey: maskWriteKey(config.writeKey), groupId: storage.getItem("__group_id"), context: deepMerge(context, customContext) });
|
|
@@ -1628,7 +1641,8 @@ function send(method, payload, jitsuConfig, instance, store) {
|
|
|
1628
1641
|
console.log(`[JITSU DEBUG] ${url} replied ${fetchResult.status}: ${responseText}. Original payload:\n${JSON.stringify(adjustedPayload, null, 2)}`);
|
|
1629
1642
|
}
|
|
1630
1643
|
if (!fetchResult.ok) {
|
|
1631
|
-
|
|
1644
|
+
getErrorHandler(jitsuConfig)(`Call to ${url} failed with error: ${fetchResult.status} - ${fetchResult.statusText}: ${responseText}`);
|
|
1645
|
+
return Promise.resolve();
|
|
1632
1646
|
}
|
|
1633
1647
|
let responseJson;
|
|
1634
1648
|
try {
|
package/dist/web/p.js.txt
CHANGED
|
@@ -1062,11 +1062,13 @@
|
|
|
1062
1062
|
fetch: null,
|
|
1063
1063
|
echoEvents: false,
|
|
1064
1064
|
cookieDomain: undefined,
|
|
1065
|
+
cookieCapture: {},
|
|
1065
1066
|
runtime: undefined,
|
|
1066
1067
|
fetchTimeoutMs: undefined,
|
|
1067
1068
|
s2s: undefined,
|
|
1068
1069
|
idEndpoint: undefined,
|
|
1069
1070
|
errorPolicy: "log",
|
|
1071
|
+
defaultPayloadContext: {},
|
|
1070
1072
|
privacy: {
|
|
1071
1073
|
dontSend: false,
|
|
1072
1074
|
disableUserIds: false,
|
|
@@ -1151,6 +1153,14 @@
|
|
|
1151
1153
|
const parts = value.split(`; ${name}=`);
|
|
1152
1154
|
return parts.length === 2 ? parts.pop().split(";").shift() : undefined;
|
|
1153
1155
|
}
|
|
1156
|
+
function getClientIds(runtime, customCookieCapture) {
|
|
1157
|
+
const cookieCapture = Object.assign({ fbc: "_fbc", fbp: "_fbp" }, customCookieCapture);
|
|
1158
|
+
const clientIds = Object.entries(cookieCapture).reduce((acc, [key, cookieName]) => {
|
|
1159
|
+
acc[key] = runtime.getCookie(cookieName);
|
|
1160
|
+
return acc;
|
|
1161
|
+
}, {});
|
|
1162
|
+
return Object.assign(Object.assign({}, clientIds), getGa4Ids(runtime));
|
|
1163
|
+
}
|
|
1154
1164
|
function getGa4Ids(runtime) {
|
|
1155
1165
|
var _a;
|
|
1156
1166
|
const allCookies = runtime.getCookies();
|
|
@@ -1228,6 +1238,10 @@
|
|
|
1228
1238
|
getItem(key) {
|
|
1229
1239
|
const cookieName = key2cookie[key] || key;
|
|
1230
1240
|
const result = getCookie(cookieName);
|
|
1241
|
+
if (key === "__anon_id") {
|
|
1242
|
+
//anonymous id must always be a string, so we don't parse it to preserve its exact value
|
|
1243
|
+
return result;
|
|
1244
|
+
}
|
|
1231
1245
|
if (typeof result === "undefined" && key === "__user_id") {
|
|
1232
1246
|
//backward compatibility with old jitsu cookie. get user id if from traits
|
|
1233
1247
|
const traits = parse(getCookie("__eventn_id_usr")) || {};
|
|
@@ -1414,7 +1428,7 @@
|
|
|
1414
1428
|
properties.url = targetUrl.replace(hashRegex, "");
|
|
1415
1429
|
properties.path = fixPath(urlPath(targetUrl));
|
|
1416
1430
|
}
|
|
1417
|
-
const customContext = ((_a = payload.properties) === null || _a === void 0 ? void 0 : _a.context) || ((_b = payload.options) === null || _b === void 0 ? void 0 : _b.context) || {};
|
|
1431
|
+
const customContext = deepMerge(config.defaultPayloadContext, ((_a = payload.properties) === null || _a === void 0 ? void 0 : _a.context) || ((_b = payload.options) === null || _b === void 0 ? void 0 : _b.context) || {});
|
|
1418
1432
|
(_c = payload.properties) === null || _c === void 0 ? true : delete _c.context;
|
|
1419
1433
|
const referrer = runtime.referrer();
|
|
1420
1434
|
const context = {
|
|
@@ -1442,8 +1456,7 @@
|
|
|
1442
1456
|
url: properties.url || url,
|
|
1443
1457
|
encoding: properties.encoding || runtime.documentEncoding(),
|
|
1444
1458
|
},
|
|
1445
|
-
clientIds: !((_e = config.privacy) === null || _e === void 0 ? void 0 : _e.disableUserIds)
|
|
1446
|
-
? Object.assign({ fbc: runtime.getCookie("_fbc"), fbp: runtime.getCookie("_fbp") }, getGa4Ids(runtime)) : undefined,
|
|
1459
|
+
clientIds: !((_e = config.privacy) === null || _e === void 0 ? void 0 : _e.disableUserIds) ? getClientIds(runtime, config.cookieCapture) : undefined,
|
|
1447
1460
|
campaign: parseUtms(query),
|
|
1448
1461
|
};
|
|
1449
1462
|
const withContext = Object.assign(Object.assign({}, payload), { timestamp: new Date().toISOString(), sentAt: new Date().toISOString(), messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)), writeKey: maskWriteKey(config.writeKey), groupId: storage.getItem("__group_id"), context: deepMerge(context, customContext) });
|
|
@@ -1631,7 +1644,8 @@
|
|
|
1631
1644
|
console.log(`[JITSU DEBUG] ${url} replied ${fetchResult.status}: ${responseText}. Original payload:\n${JSON.stringify(adjustedPayload, null, 2)}`);
|
|
1632
1645
|
}
|
|
1633
1646
|
if (!fetchResult.ok) {
|
|
1634
|
-
|
|
1647
|
+
getErrorHandler(jitsuConfig)(`Call to ${url} failed with error: ${fetchResult.status} - ${fetchResult.statusText}: ${responseText}`);
|
|
1648
|
+
return Promise.resolve();
|
|
1635
1649
|
}
|
|
1636
1650
|
let responseJson;
|
|
1637
1651
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jitsu/js",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.13-canary.1167.20250215132227",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "Jitsu Dev Team <dev@jitsu.com>",
|
|
6
6
|
"main": "dist/jitsu.cjs.js",
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"tslib": "^2.6.3",
|
|
16
16
|
"@playwright/test": "1.39.0",
|
|
17
|
-
"@rollup/plugin-commonjs": "^
|
|
17
|
+
"@rollup/plugin-commonjs": "^28.0.2",
|
|
18
18
|
"@rollup/plugin-json": "^5.0.1",
|
|
19
19
|
"@rollup/plugin-multi-entry": "^6.0.0",
|
|
20
|
-
"@rollup/plugin-node-resolve": "^
|
|
20
|
+
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
21
21
|
"@rollup/plugin-replace": "^5.0.1",
|
|
22
22
|
"@rollup/plugin-terser": "^0.1.0",
|
|
23
23
|
"@segment/analytics-next": "^1.75.0",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"chalk": "^4.1.2",
|
|
28
28
|
"cookie-parser": "^1.4.7",
|
|
29
29
|
"ejs": "^3.1.8",
|
|
30
|
-
"express": "^4.21.
|
|
30
|
+
"express": "^4.21.2",
|
|
31
31
|
"jest": "^29.2.2",
|
|
32
32
|
"node-fetch-commonjs": "^3.3.2",
|
|
33
33
|
"node-forge": "^1.3.1",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"rollup": "^3.29.5",
|
|
36
36
|
"ts-jest": "29.0.5",
|
|
37
37
|
"typescript": "^5.6.3",
|
|
38
|
-
"@jitsu/protocols": "1.9.
|
|
39
|
-
"jsondiffpatch": "1.9.
|
|
38
|
+
"@jitsu/protocols": "1.9.13-canary.1167.20250215132227",
|
|
39
|
+
"jsondiffpatch": "1.9.13-canary.1167.20250215132227"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"analytics": "0.8.9"
|
package/src/analytics-plugin.ts
CHANGED
|
@@ -33,11 +33,13 @@ const defaultConfig: Required<JitsuOptions> = {
|
|
|
33
33
|
fetch: null,
|
|
34
34
|
echoEvents: false,
|
|
35
35
|
cookieDomain: undefined,
|
|
36
|
+
cookieCapture: {},
|
|
36
37
|
runtime: undefined,
|
|
37
38
|
fetchTimeoutMs: undefined,
|
|
38
39
|
s2s: undefined,
|
|
39
40
|
idEndpoint: undefined,
|
|
40
41
|
errorPolicy: "log",
|
|
42
|
+
defaultPayloadContext: {},
|
|
41
43
|
privacy: {
|
|
42
44
|
dontSend: false,
|
|
43
45
|
disableUserIds: false,
|
|
@@ -141,6 +143,22 @@ function getCookie(name: string) {
|
|
|
141
143
|
return parts.length === 2 ? parts.pop().split(";").shift() : undefined;
|
|
142
144
|
}
|
|
143
145
|
|
|
146
|
+
function getClientIds(runtime: RuntimeFacade, customCookieCapture: Record<string, string>) {
|
|
147
|
+
const cookieCapture = {
|
|
148
|
+
fbc: "_fbc",
|
|
149
|
+
fbp: "_fbp",
|
|
150
|
+
...customCookieCapture,
|
|
151
|
+
};
|
|
152
|
+
const clientIds = Object.entries(cookieCapture).reduce((acc, [key, cookieName]) => {
|
|
153
|
+
acc[key] = runtime.getCookie(cookieName);
|
|
154
|
+
return acc;
|
|
155
|
+
}, {});
|
|
156
|
+
return {
|
|
157
|
+
...clientIds,
|
|
158
|
+
...getGa4Ids(runtime),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
144
162
|
function getGa4Ids(runtime: RuntimeFacade) {
|
|
145
163
|
const allCookies = runtime.getCookies();
|
|
146
164
|
const clientId = allCookies["_ga"]?.split(".").slice(-2).join(".");
|
|
@@ -223,6 +241,10 @@ const cookieStorage: StorageFactory = (cookieDomain, key2cookie) => {
|
|
|
223
241
|
getItem(key: string) {
|
|
224
242
|
const cookieName = key2cookie[key] || key;
|
|
225
243
|
const result = getCookie(cookieName);
|
|
244
|
+
if (key === "__anon_id") {
|
|
245
|
+
//anonymous id must always be a string, so we don't parse it to preserve its exact value
|
|
246
|
+
return result;
|
|
247
|
+
}
|
|
226
248
|
if (typeof result === "undefined" && key === "__user_id") {
|
|
227
249
|
//backward compatibility with old jitsu cookie. get user id if from traits
|
|
228
250
|
const traits = parse(getCookie("__eventn_id_usr")) || {};
|
|
@@ -424,7 +446,10 @@ function adjustPayload(
|
|
|
424
446
|
properties.path = fixPath(urlPath(targetUrl));
|
|
425
447
|
}
|
|
426
448
|
|
|
427
|
-
const customContext =
|
|
449
|
+
const customContext = deepMerge(
|
|
450
|
+
config.defaultPayloadContext,
|
|
451
|
+
payload.properties?.context || payload.options?.context || {}
|
|
452
|
+
);
|
|
428
453
|
delete payload.properties?.context;
|
|
429
454
|
const referrer = runtime.referrer();
|
|
430
455
|
const context: AnalyticsClientEvent["context"] = {
|
|
@@ -452,13 +477,7 @@ function adjustPayload(
|
|
|
452
477
|
url: properties.url || url,
|
|
453
478
|
encoding: properties.encoding || runtime.documentEncoding(),
|
|
454
479
|
},
|
|
455
|
-
clientIds: !config.privacy?.disableUserIds
|
|
456
|
-
? {
|
|
457
|
-
fbc: runtime.getCookie("_fbc"),
|
|
458
|
-
fbp: runtime.getCookie("_fbp"),
|
|
459
|
-
...getGa4Ids(runtime),
|
|
460
|
-
}
|
|
461
|
-
: undefined,
|
|
480
|
+
clientIds: !config.privacy?.disableUserIds ? getClientIds(runtime, config.cookieCapture) : undefined,
|
|
462
481
|
campaign: parseUtms(query),
|
|
463
482
|
};
|
|
464
483
|
const withContext = {
|
|
@@ -723,7 +742,10 @@ async function send(
|
|
|
723
742
|
);
|
|
724
743
|
}
|
|
725
744
|
if (!fetchResult.ok) {
|
|
726
|
-
|
|
745
|
+
getErrorHandler(jitsuConfig)(
|
|
746
|
+
`Call to ${url} failed with error: ${fetchResult.status} - ${fetchResult.statusText}: ${responseText}`
|
|
747
|
+
);
|
|
748
|
+
return Promise.resolve();
|
|
727
749
|
}
|
|
728
750
|
|
|
729
751
|
let responseJson: any;
|