@drivemetadata-ai/sdk 0.1.1-beta.2 → 0.1.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 +152 -21
- package/dist/angular/index.cjs +946 -95
- package/dist/angular/index.cjs.map +1 -1
- package/dist/angular/index.d.cts +2 -2
- package/dist/angular/index.d.ts +2 -2
- package/dist/angular/index.js +946 -95
- package/dist/angular/index.js.map +1 -1
- package/dist/browser/index.cjs +947 -96
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.d.cts +2 -2
- package/dist/browser/index.d.ts +2 -2
- package/dist/browser/index.js +947 -96
- package/dist/browser/index.js.map +1 -1
- package/dist/next/index.cjs +946 -95
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +1 -1
- package/dist/next/index.d.ts +1 -1
- package/dist/next/index.js +946 -95
- package/dist/next/index.js.map +1 -1
- package/dist/node/index.cjs +81 -9
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.js +81 -9
- package/dist/node/index.js.map +1 -1
- package/dist/react/index.cjs +946 -95
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +946 -95
- package/dist/react/index.js.map +1 -1
- package/dist/{types--V8TVIqT.d.cts → types-mgbdL1V7.d.cts} +17 -4
- package/dist/{types--V8TVIqT.d.ts → types-mgbdL1V7.d.ts} +17 -4
- package/docs/architecture.md +109 -0
- package/docs/index.md +1 -0
- package/docs/integration.md +203 -5
- package/docs/npm-browser-sdk.md +4 -0
- package/package.json +4 -2
package/dist/angular/index.cjs
CHANGED
|
@@ -38,12 +38,62 @@ module.exports = __toCommonJS(angular_exports);
|
|
|
38
38
|
// src/angular/dmd-analytics.service.ts
|
|
39
39
|
var import_core2 = require("@angular/core");
|
|
40
40
|
|
|
41
|
+
// src/browser/core/browser-config.ts
|
|
42
|
+
function setIfDefined(target, key, value) {
|
|
43
|
+
if (value !== void 0) {
|
|
44
|
+
target[key] = value;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function normalizeBrowserConfig(input) {
|
|
48
|
+
const normalized = {
|
|
49
|
+
...input,
|
|
50
|
+
clientId: input.clientId ?? "",
|
|
51
|
+
workspaceId: input.workspaceId ?? "",
|
|
52
|
+
appId: input.appId ?? ""
|
|
53
|
+
};
|
|
54
|
+
setIfDefined(normalized, "apiHost", input.apiHost);
|
|
55
|
+
setIfDefined(normalized, "capturePageview", input.capturePageview);
|
|
56
|
+
setIfDefined(normalized, "capturePageleave", input.capturePageleave);
|
|
57
|
+
setIfDefined(normalized, "captureDeadClicks", input.captureDeadClicks);
|
|
58
|
+
setIfDefined(normalized, "crossSubdomainCookie", input.crossSubdomainCookie);
|
|
59
|
+
setIfDefined(normalized, "sessionIdleTimeoutSeconds", input.sessionIdleTimeoutSeconds);
|
|
60
|
+
setIfDefined(normalized, "schemaValidation", input.schemaValidation);
|
|
61
|
+
setIfDefined(normalized, "beforeSend", input.beforeSend);
|
|
62
|
+
setIfDefined(normalized, "persistence", input.disablePersistence === true ? "none" : input.persistence);
|
|
63
|
+
return normalized;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/core/uuid.ts
|
|
67
|
+
function createUuid() {
|
|
68
|
+
const cryptoApi = globalThis.crypto;
|
|
69
|
+
if (typeof cryptoApi?.randomUUID === "function") {
|
|
70
|
+
return cryptoApi.randomUUID();
|
|
71
|
+
}
|
|
72
|
+
const bytes = new Uint8Array(16);
|
|
73
|
+
if (typeof cryptoApi?.getRandomValues === "function") {
|
|
74
|
+
cryptoApi.getRandomValues(bytes);
|
|
75
|
+
} else {
|
|
76
|
+
for (let index = 0; index < bytes.length; index += 1) {
|
|
77
|
+
bytes[index] = Math.floor(Math.random() * 256);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
81
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
82
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
83
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
84
|
+
}
|
|
85
|
+
function isUuid(value) {
|
|
86
|
+
return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
|
|
87
|
+
}
|
|
88
|
+
function ensureUuid(value) {
|
|
89
|
+
return isUuid(value) ? value : createUuid();
|
|
90
|
+
}
|
|
91
|
+
|
|
41
92
|
// src/core/backend-payload.ts
|
|
42
93
|
function formatUtcTimestamp(value) {
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
return date.toISOString().replace("T", " ").slice(0, 19);
|
|
94
|
+
const date = typeof value === "string" || typeof value === "number" || value instanceof Date ? new Date(value) : /* @__PURE__ */ new Date();
|
|
95
|
+
const safeDate = Number.isNaN(date.getTime()) ? /* @__PURE__ */ new Date() : date;
|
|
96
|
+
return safeDate.toISOString().replace("T", " ").slice(0, 19);
|
|
47
97
|
}
|
|
48
98
|
function cleanObject(value) {
|
|
49
99
|
if (Array.isArray(value)) {
|
|
@@ -74,15 +124,19 @@ function createBackendCollectorPayload(input) {
|
|
|
74
124
|
};
|
|
75
125
|
const metaData = {
|
|
76
126
|
...normalizedEventData,
|
|
77
|
-
requestId: input.requestId,
|
|
127
|
+
requestId: ensureUuid(typeof input.requestId === "string" ? input.requestId : void 0),
|
|
78
128
|
timestamp,
|
|
79
129
|
eventType: input.eventType,
|
|
80
130
|
requestFrom: input.requestFrom ?? "3",
|
|
81
131
|
clientId: input.clientId,
|
|
82
132
|
workspaceId: input.workspaceId,
|
|
83
133
|
token: input.token,
|
|
84
|
-
anonymousId:
|
|
85
|
-
|
|
134
|
+
anonymousId: ensureUuid(
|
|
135
|
+
typeof eventData.anonymousId === "string" ? eventData.anonymousId : typeof input.anonymousId === "string" ? input.anonymousId : void 0
|
|
136
|
+
),
|
|
137
|
+
sessionId: ensureUuid(
|
|
138
|
+
typeof eventData.sessionId === "string" ? eventData.sessionId : typeof input.sessionId === "string" ? input.sessionId : void 0
|
|
139
|
+
),
|
|
86
140
|
ua: input.ua,
|
|
87
141
|
appDetails: { app_id: input.appId },
|
|
88
142
|
page: { ...page2, url: page2.url ?? input.pageUrl },
|
|
@@ -93,12 +147,45 @@ function createBackendCollectorPayload(input) {
|
|
|
93
147
|
return cleanObject(payload);
|
|
94
148
|
}
|
|
95
149
|
|
|
96
|
-
// src/core/
|
|
97
|
-
|
|
98
|
-
|
|
150
|
+
// src/core/backend-schema.ts
|
|
151
|
+
var requiredMetaDataFields = [
|
|
152
|
+
"requestId",
|
|
153
|
+
"timestamp",
|
|
154
|
+
"eventType",
|
|
155
|
+
"requestFrom",
|
|
156
|
+
"clientId",
|
|
157
|
+
"workspaceId",
|
|
158
|
+
"anonymousId",
|
|
159
|
+
"sessionId"
|
|
160
|
+
];
|
|
161
|
+
function isPresent(value) {
|
|
162
|
+
return value !== null && value !== void 0 && value !== "";
|
|
163
|
+
}
|
|
164
|
+
function validateBackendCollectorPayload(payload) {
|
|
165
|
+
const errors = [];
|
|
166
|
+
const metaData = payload.metaData;
|
|
167
|
+
if (!metaData || typeof metaData !== "object" || Array.isArray(metaData)) {
|
|
168
|
+
return {
|
|
169
|
+
ok: false,
|
|
170
|
+
errors: ["metaData is required"]
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
const metadataRecord = metaData;
|
|
174
|
+
for (const field of requiredMetaDataFields) {
|
|
175
|
+
if (!isPresent(metadataRecord[field])) {
|
|
176
|
+
errors.push(`metaData.${field} is required`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (isPresent(metadataRecord.eventType) && typeof metadataRecord.eventType !== "string") {
|
|
180
|
+
errors.push("metaData.eventType must be a string");
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
ok: errors.length === 0,
|
|
184
|
+
errors
|
|
185
|
+
};
|
|
99
186
|
}
|
|
100
187
|
|
|
101
|
-
// src/
|
|
188
|
+
// src/core/consent.ts
|
|
102
189
|
var purposes = [
|
|
103
190
|
"analytics",
|
|
104
191
|
"advertising",
|
|
@@ -138,6 +225,476 @@ function canCollectPurpose(consent, purpose) {
|
|
|
138
225
|
return consent[purpose] === "granted";
|
|
139
226
|
}
|
|
140
227
|
|
|
228
|
+
// src/core/event-schema.ts
|
|
229
|
+
var reservedKeys = /* @__PURE__ */ new Set(["messageId", "timestamp", "type", "event", "anonymousId", "userId", "context"]);
|
|
230
|
+
function validateEventEnvelope(envelope, options = {}) {
|
|
231
|
+
if (options.mode === "off") return { ok: true, errors: [] };
|
|
232
|
+
const errors = [];
|
|
233
|
+
if (typeof envelope.type !== "string") errors.push("type must be a string");
|
|
234
|
+
if (envelope.type === "track" && typeof envelope.event !== "string") {
|
|
235
|
+
errors.push("track event must include event name");
|
|
236
|
+
}
|
|
237
|
+
if (typeof envelope.messageId !== "string") errors.push("messageId must be a string");
|
|
238
|
+
if (typeof envelope.timestamp !== "string") errors.push("timestamp must be an ISO string");
|
|
239
|
+
for (const key of Object.keys(envelope.properties ?? {})) {
|
|
240
|
+
if (reservedKeys.has(key)) errors.push(`properties.${key} is reserved`);
|
|
241
|
+
}
|
|
242
|
+
return { ok: errors.length === 0, errors };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// src/core/environment.ts
|
|
246
|
+
function getBrowserWindow() {
|
|
247
|
+
return typeof window === "undefined" ? void 0 : window;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// src/core/privacy.ts
|
|
251
|
+
var sensitiveKeys = /* @__PURE__ */ new Set([
|
|
252
|
+
"email",
|
|
253
|
+
"phone",
|
|
254
|
+
"mobile",
|
|
255
|
+
"address",
|
|
256
|
+
"address1",
|
|
257
|
+
"address2",
|
|
258
|
+
"first_name",
|
|
259
|
+
"last_name",
|
|
260
|
+
"name",
|
|
261
|
+
"token",
|
|
262
|
+
"secret",
|
|
263
|
+
"password",
|
|
264
|
+
"session",
|
|
265
|
+
"cookie"
|
|
266
|
+
]);
|
|
267
|
+
function redactUrl(url, allowQueryKeys = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"]) {
|
|
268
|
+
const parsed = new URL(url, "https://placeholder.local");
|
|
269
|
+
for (const key of Array.from(parsed.searchParams.keys())) {
|
|
270
|
+
if (!allowQueryKeys.includes(key)) {
|
|
271
|
+
parsed.searchParams.set(key, "[REDACTED]");
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return url.startsWith("http") ? parsed.toString() : `${parsed.pathname}${parsed.search}`;
|
|
275
|
+
}
|
|
276
|
+
function sanitizeValue(value, allow, path = []) {
|
|
277
|
+
if (Array.isArray(value)) {
|
|
278
|
+
return value.map((item) => sanitizeValue(item, allow, path));
|
|
279
|
+
}
|
|
280
|
+
if (value && typeof value === "object") {
|
|
281
|
+
return Object.fromEntries(
|
|
282
|
+
Object.entries(value).filter(([key]) => {
|
|
283
|
+
const lowerKey = key.toLowerCase();
|
|
284
|
+
const lowerPath = path.map((item) => item.toLowerCase());
|
|
285
|
+
const isEcommerceItemName = lowerKey === "name" && lowerPath.includes("ecommerce") && lowerPath.includes("items");
|
|
286
|
+
return isEcommerceItemName || !sensitiveKeys.has(lowerKey) || allow.has(lowerKey);
|
|
287
|
+
}).map(([key, nestedValue]) => [key, sanitizeValue(nestedValue, allow, [...path, key])])
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
return value;
|
|
291
|
+
}
|
|
292
|
+
function sanitizeProperties(input, allowRawKeys = []) {
|
|
293
|
+
const allow = new Set(allowRawKeys.map((key) => key.toLowerCase()));
|
|
294
|
+
return sanitizeValue(input, allow);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// src/browser/core/attribute-persistence.ts
|
|
298
|
+
var DMD_ATTRIBUTES_STORAGE_KEY = "dmd_attributes";
|
|
299
|
+
var SESSION_STORAGE_KEY = "sessionData";
|
|
300
|
+
var SESSION_ID_KEY = "sessionId";
|
|
301
|
+
var SESSION_TIMESTAMP_KEY = "timestamp";
|
|
302
|
+
function isBlankValue(value) {
|
|
303
|
+
return value === null || value === void 0 || typeof value === "string" && value.trim() === "";
|
|
304
|
+
}
|
|
305
|
+
function readAttributes(base) {
|
|
306
|
+
const raw = base.getItem(DMD_ATTRIBUTES_STORAGE_KEY);
|
|
307
|
+
if (!raw) return {};
|
|
308
|
+
try {
|
|
309
|
+
const parsed = JSON.parse(raw);
|
|
310
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
311
|
+
} catch {
|
|
312
|
+
base.removeItem(DMD_ATTRIBUTES_STORAGE_KEY);
|
|
313
|
+
return {};
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function sanitizeAttributes(attributes) {
|
|
317
|
+
return Object.fromEntries(Object.entries(attributes).filter(([, value]) => !isBlankValue(value)));
|
|
318
|
+
}
|
|
319
|
+
function writeAttributes(base, attributes) {
|
|
320
|
+
const sanitized = sanitizeAttributes(attributes);
|
|
321
|
+
if (Object.keys(sanitized).length === 0) {
|
|
322
|
+
base.removeItem(DMD_ATTRIBUTES_STORAGE_KEY);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
base.setItem(DMD_ATTRIBUTES_STORAGE_KEY, JSON.stringify(sanitized));
|
|
326
|
+
}
|
|
327
|
+
function parseSessionData(value) {
|
|
328
|
+
try {
|
|
329
|
+
const parsed = JSON.parse(value);
|
|
330
|
+
const sessionData = {};
|
|
331
|
+
const sessionId = typeof parsed.sessionId === "string" && parsed.sessionId.trim() !== "" ? parsed.sessionId : void 0;
|
|
332
|
+
const timestamp = typeof parsed.timestamp === "number" ? parsed.timestamp : void 0;
|
|
333
|
+
if (sessionId !== void 0) sessionData.sessionId = sessionId;
|
|
334
|
+
if (timestamp !== void 0) sessionData.timestamp = timestamp;
|
|
335
|
+
return sessionData;
|
|
336
|
+
} catch {
|
|
337
|
+
return {};
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
function getAggregateValue(attributes, key) {
|
|
341
|
+
if (key === SESSION_STORAGE_KEY) {
|
|
342
|
+
const sessionId = attributes[SESSION_ID_KEY];
|
|
343
|
+
const timestamp = attributes[SESSION_TIMESTAMP_KEY];
|
|
344
|
+
if (typeof sessionId === "string" && !isBlankValue(sessionId) && typeof timestamp === "number") {
|
|
345
|
+
return JSON.stringify({ sessionId, timestamp });
|
|
346
|
+
}
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
const value = attributes[key];
|
|
350
|
+
if (isBlankValue(value)) return null;
|
|
351
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
352
|
+
}
|
|
353
|
+
function setAggregateValue(attributes, key, value) {
|
|
354
|
+
if (key === SESSION_STORAGE_KEY) {
|
|
355
|
+
const sessionData = parseSessionData(value);
|
|
356
|
+
if (sessionData.sessionId === void 0 || sessionData.timestamp === void 0) {
|
|
357
|
+
delete attributes[SESSION_ID_KEY];
|
|
358
|
+
delete attributes[SESSION_TIMESTAMP_KEY];
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
attributes[SESSION_ID_KEY] = sessionData.sessionId;
|
|
362
|
+
attributes[SESSION_TIMESTAMP_KEY] = sessionData.timestamp;
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
attributes[key] = value;
|
|
366
|
+
}
|
|
367
|
+
function removeAggregateValue(attributes, key) {
|
|
368
|
+
if (key === SESSION_STORAGE_KEY) {
|
|
369
|
+
delete attributes[SESSION_ID_KEY];
|
|
370
|
+
delete attributes[SESSION_TIMESTAMP_KEY];
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
delete attributes[key];
|
|
374
|
+
}
|
|
375
|
+
function createDmdAttributesPersistence(base) {
|
|
376
|
+
return {
|
|
377
|
+
getItem(key) {
|
|
378
|
+
if (key === DMD_ATTRIBUTES_STORAGE_KEY) return base.getItem(key);
|
|
379
|
+
const attributes = readAttributes(base);
|
|
380
|
+
const aggregateValue = getAggregateValue(attributes, key);
|
|
381
|
+
if (aggregateValue !== null) return aggregateValue;
|
|
382
|
+
const legacyValue = base.getItem(key);
|
|
383
|
+
if (isBlankValue(legacyValue)) return null;
|
|
384
|
+
setAggregateValue(attributes, key, String(legacyValue));
|
|
385
|
+
writeAttributes(base, attributes);
|
|
386
|
+
return legacyValue;
|
|
387
|
+
},
|
|
388
|
+
setItem(key, value) {
|
|
389
|
+
if (key === DMD_ATTRIBUTES_STORAGE_KEY) return base.setItem(key, value);
|
|
390
|
+
const attributes = readAttributes(base);
|
|
391
|
+
if (isBlankValue(value)) {
|
|
392
|
+
removeAggregateValue(attributes, key);
|
|
393
|
+
writeAttributes(base, attributes);
|
|
394
|
+
base.removeItem(key);
|
|
395
|
+
return true;
|
|
396
|
+
}
|
|
397
|
+
setAggregateValue(attributes, key, value);
|
|
398
|
+
writeAttributes(base, attributes);
|
|
399
|
+
base.setItem(key, value);
|
|
400
|
+
return true;
|
|
401
|
+
},
|
|
402
|
+
removeItem(key) {
|
|
403
|
+
if (key === DMD_ATTRIBUTES_STORAGE_KEY) {
|
|
404
|
+
base.removeItem(key);
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
const attributes = readAttributes(base);
|
|
408
|
+
removeAggregateValue(attributes, key);
|
|
409
|
+
writeAttributes(base, attributes);
|
|
410
|
+
base.removeItem(key);
|
|
411
|
+
},
|
|
412
|
+
getHealth() {
|
|
413
|
+
return base.getHealth();
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// src/core/attribution.ts
|
|
419
|
+
var dmdUtmKeys = [
|
|
420
|
+
"utm_source",
|
|
421
|
+
"utm_medium",
|
|
422
|
+
"utm_campaign",
|
|
423
|
+
"utm_term",
|
|
424
|
+
"utm_content",
|
|
425
|
+
"utm_id"
|
|
426
|
+
];
|
|
427
|
+
var dmdCampaignKeys = ["campaign_id", "ad_id"];
|
|
428
|
+
var dmdClickIdSources = [
|
|
429
|
+
["gclid", 2],
|
|
430
|
+
["fbclid", 3],
|
|
431
|
+
["ScCid", 1],
|
|
432
|
+
["li_fat_id", 4]
|
|
433
|
+
];
|
|
434
|
+
function cleanAttributionRecord(record) {
|
|
435
|
+
const cleaned = Object.fromEntries(
|
|
436
|
+
Object.entries(record).filter(([, value]) => value !== null && value !== void 0 && value !== "")
|
|
437
|
+
);
|
|
438
|
+
return Object.keys(cleaned).length > 0 ? cleaned : void 0;
|
|
439
|
+
}
|
|
440
|
+
function objectValue(value) {
|
|
441
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
442
|
+
}
|
|
443
|
+
function mergeAttributionRecords(explicitProperties, stored) {
|
|
444
|
+
const attributionData = objectValue(explicitProperties.attributionData);
|
|
445
|
+
const utmParameter = objectValue(explicitProperties.utmParameter);
|
|
446
|
+
return {
|
|
447
|
+
...explicitProperties,
|
|
448
|
+
...stored.attributionData || attributionData ? { attributionData: { ...stored.attributionData ?? {}, ...attributionData ?? {} } } : {},
|
|
449
|
+
...stored.utmParameter || utmParameter ? { utmParameter: { ...stored.utmParameter ?? {}, ...utmParameter ?? {} } } : {}
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// src/browser/core/attribution.ts
|
|
454
|
+
var DMD_CLICK_ID_QUERY_KEY = "click_id";
|
|
455
|
+
var DMD_CLICK_ID_LEGACY_QUERY_KEY = "dmd_click_id";
|
|
456
|
+
var DMD_CLICK_ID_STORAGE_KEY = "dmd_click_id";
|
|
457
|
+
var DMD_CLICK_ID_ATTRIBUTE_KEY = "click_id";
|
|
458
|
+
function getCurrentUrl() {
|
|
459
|
+
return getBrowserWindow()?.location?.href;
|
|
460
|
+
}
|
|
461
|
+
function getCookie(name) {
|
|
462
|
+
const cookie = getBrowserWindow()?.document?.cookie;
|
|
463
|
+
if (!cookie) return void 0;
|
|
464
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
465
|
+
const match = new RegExp(`(?:^|; )${escapedName}=([^;]*)`).exec(cookie);
|
|
466
|
+
return match ? decodeURIComponent(match[1] ?? "") : void 0;
|
|
467
|
+
}
|
|
468
|
+
function getParams(url) {
|
|
469
|
+
return new URL(url, "https://placeholder.local").searchParams;
|
|
470
|
+
}
|
|
471
|
+
function setIfPresent(persistence, key, value) {
|
|
472
|
+
if (value !== null && value !== "") {
|
|
473
|
+
persistence.setItem(key, value);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
function getClickIdParam(params) {
|
|
477
|
+
return params.get(DMD_CLICK_ID_LEGACY_QUERY_KEY) || params.get(DMD_CLICK_ID_QUERY_KEY);
|
|
478
|
+
}
|
|
479
|
+
function getStoredString(persistence, key) {
|
|
480
|
+
const value = persistence.getItem(key);
|
|
481
|
+
return value === null || value === "" ? void 0 : value;
|
|
482
|
+
}
|
|
483
|
+
function getStoredNumberOrString(persistence, key) {
|
|
484
|
+
const value = getStoredString(persistence, key);
|
|
485
|
+
if (value === void 0) return void 0;
|
|
486
|
+
const parsed = Number.parseInt(value, 10);
|
|
487
|
+
return Number.isNaN(parsed) ? value : parsed;
|
|
488
|
+
}
|
|
489
|
+
function captureAttributionFromUrl(persistence, url = getCurrentUrl()) {
|
|
490
|
+
if (!url) return;
|
|
491
|
+
const params = getParams(url);
|
|
492
|
+
for (const key of dmdUtmKeys) {
|
|
493
|
+
setIfPresent(persistence, key, params.get(key));
|
|
494
|
+
}
|
|
495
|
+
for (const key of dmdCampaignKeys) {
|
|
496
|
+
setIfPresent(persistence, key, params.get(key));
|
|
497
|
+
}
|
|
498
|
+
const clickId = getClickIdParam(params);
|
|
499
|
+
setIfPresent(persistence, DMD_CLICK_ID_ATTRIBUTE_KEY, clickId);
|
|
500
|
+
setIfPresent(persistence, DMD_CLICK_ID_STORAGE_KEY, clickId);
|
|
501
|
+
for (const [param, sdkPubId] of dmdClickIdSources) {
|
|
502
|
+
const value = params.get(param);
|
|
503
|
+
if (value) {
|
|
504
|
+
persistence.setItem("unique_id", value);
|
|
505
|
+
persistence.setItem("sdk_pub_id", String(sdkPubId));
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
function getStoredAttributionData(persistence) {
|
|
510
|
+
return cleanAttributionRecord({
|
|
511
|
+
unique_id: getStoredString(persistence, "unique_id"),
|
|
512
|
+
sdk_pub_id: getStoredNumberOrString(persistence, "sdk_pub_id"),
|
|
513
|
+
fbc: getStoredString(persistence, "fbc") ?? getCookie("_fbc"),
|
|
514
|
+
fbp: getStoredString(persistence, "fbp") ?? getCookie("_fbp"),
|
|
515
|
+
campaign_id: getStoredString(persistence, "campaign_id"),
|
|
516
|
+
ad_id: getStoredString(persistence, "ad_id"),
|
|
517
|
+
click_id: getStoredString(persistence, DMD_CLICK_ID_STORAGE_KEY) ?? getStoredString(persistence, DMD_CLICK_ID_ATTRIBUTE_KEY)
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
function getStoredUtmParameter(persistence) {
|
|
521
|
+
return cleanAttributionRecord(Object.fromEntries(dmdUtmKeys.map((key) => [key, getStoredString(persistence, key)])));
|
|
522
|
+
}
|
|
523
|
+
function mergeStoredAttribution(properties, persistence) {
|
|
524
|
+
const stored = {};
|
|
525
|
+
const attributionData = getStoredAttributionData(persistence);
|
|
526
|
+
const utmParameter = getStoredUtmParameter(persistence);
|
|
527
|
+
if (attributionData !== void 0) stored.attributionData = attributionData;
|
|
528
|
+
if (utmParameter !== void 0) stored.utmParameter = utmParameter;
|
|
529
|
+
return mergeAttributionRecords(properties, stored);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// src/browser/core/autocapture.ts
|
|
533
|
+
function installAutocapture(config) {
|
|
534
|
+
const trackedPageUrls = /* @__PURE__ */ new Set();
|
|
535
|
+
const timers = /* @__PURE__ */ new Set();
|
|
536
|
+
const pageviewDelayMs = config.pageviewDelayMs ?? 500;
|
|
537
|
+
const history = config.browserWindow.history;
|
|
538
|
+
const originalPushState = history?.pushState;
|
|
539
|
+
const originalReplaceState = history?.replaceState;
|
|
540
|
+
function clearTimer(timer) {
|
|
541
|
+
timers.delete(timer);
|
|
542
|
+
clearTimeout(timer);
|
|
543
|
+
}
|
|
544
|
+
function canonicalUrl() {
|
|
545
|
+
return config.browserWindow.location.href;
|
|
546
|
+
}
|
|
547
|
+
function trackCurrentPageview() {
|
|
548
|
+
if (!config.capturePageview) return;
|
|
549
|
+
const url = canonicalUrl();
|
|
550
|
+
if (trackedPageUrls.has(url)) return;
|
|
551
|
+
trackedPageUrls.add(url);
|
|
552
|
+
config.onPageView();
|
|
553
|
+
}
|
|
554
|
+
function schedulePageview(delayMs) {
|
|
555
|
+
if (!config.capturePageview) return;
|
|
556
|
+
const timer = setTimeout(() => {
|
|
557
|
+
timers.delete(timer);
|
|
558
|
+
trackCurrentPageview();
|
|
559
|
+
}, delayMs);
|
|
560
|
+
timers.add(timer);
|
|
561
|
+
}
|
|
562
|
+
function handleRouteChange() {
|
|
563
|
+
config.onRouteChange?.();
|
|
564
|
+
trackCurrentPageview();
|
|
565
|
+
}
|
|
566
|
+
function wrapHistoryMethod(method) {
|
|
567
|
+
if (!history) return;
|
|
568
|
+
const original = history[method];
|
|
569
|
+
if (typeof original !== "function") return;
|
|
570
|
+
history[method] = function wrappedHistoryMethod(...args) {
|
|
571
|
+
const result = original.apply(this, args);
|
|
572
|
+
const timer = setTimeout(() => {
|
|
573
|
+
timers.delete(timer);
|
|
574
|
+
handleRouteChange();
|
|
575
|
+
}, 0);
|
|
576
|
+
timers.add(timer);
|
|
577
|
+
return result;
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
function handlePopOrHashChange() {
|
|
581
|
+
handleRouteChange();
|
|
582
|
+
}
|
|
583
|
+
function handlePageLeave() {
|
|
584
|
+
if (config.capturePageleave) {
|
|
585
|
+
config.onPageLeave();
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
schedulePageview(pageviewDelayMs);
|
|
589
|
+
wrapHistoryMethod("pushState");
|
|
590
|
+
wrapHistoryMethod("replaceState");
|
|
591
|
+
const canListen = typeof config.browserWindow.addEventListener === "function" && typeof config.browserWindow.removeEventListener === "function";
|
|
592
|
+
if (canListen) {
|
|
593
|
+
config.browserWindow.addEventListener("popstate", handlePopOrHashChange);
|
|
594
|
+
config.browserWindow.addEventListener("hashchange", handlePopOrHashChange);
|
|
595
|
+
config.browserWindow.addEventListener("beforeunload", handlePageLeave);
|
|
596
|
+
}
|
|
597
|
+
return {
|
|
598
|
+
cleanup() {
|
|
599
|
+
for (const timer of Array.from(timers)) {
|
|
600
|
+
clearTimer(timer);
|
|
601
|
+
}
|
|
602
|
+
if (history && originalPushState) history.pushState = originalPushState;
|
|
603
|
+
if (history && originalReplaceState) history.replaceState = originalReplaceState;
|
|
604
|
+
if (canListen) {
|
|
605
|
+
config.browserWindow.removeEventListener("popstate", handlePopOrHashChange);
|
|
606
|
+
config.browserWindow.removeEventListener("hashchange", handlePopOrHashChange);
|
|
607
|
+
config.browserWindow.removeEventListener("beforeunload", handlePageLeave);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// src/core/payload-size.ts
|
|
614
|
+
var preserveStringKeys = /* @__PURE__ */ new Set([
|
|
615
|
+
"requestId",
|
|
616
|
+
"eventType",
|
|
617
|
+
"requestFrom",
|
|
618
|
+
"clientId",
|
|
619
|
+
"workspaceId",
|
|
620
|
+
"anonymousId",
|
|
621
|
+
"sessionId",
|
|
622
|
+
"token"
|
|
623
|
+
]);
|
|
624
|
+
function payloadByteLength(payload) {
|
|
625
|
+
const serialized = JSON.stringify(payload);
|
|
626
|
+
if (typeof TextEncoder !== "undefined") {
|
|
627
|
+
return new TextEncoder().encode(serialized).length;
|
|
628
|
+
}
|
|
629
|
+
return serialized.length;
|
|
630
|
+
}
|
|
631
|
+
function clonePayload(payload) {
|
|
632
|
+
try {
|
|
633
|
+
return JSON.parse(JSON.stringify(payload));
|
|
634
|
+
} catch {
|
|
635
|
+
return void 0;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
function truncateValue(value, truncateStringLength, key) {
|
|
639
|
+
if (typeof value === "string") {
|
|
640
|
+
if (key && preserveStringKeys.has(key)) return value;
|
|
641
|
+
if (value.length <= truncateStringLength) return value;
|
|
642
|
+
return `${value.slice(0, truncateStringLength)}...[TRUNCATED]`;
|
|
643
|
+
}
|
|
644
|
+
if (Array.isArray(value)) {
|
|
645
|
+
return value.map((item) => truncateValue(item, truncateStringLength));
|
|
646
|
+
}
|
|
647
|
+
if (value && typeof value === "object") {
|
|
648
|
+
return Object.fromEntries(
|
|
649
|
+
Object.entries(value).map(([childKey, childValue]) => [
|
|
650
|
+
childKey,
|
|
651
|
+
truncateValue(childValue, truncateStringLength, childKey)
|
|
652
|
+
])
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
return value;
|
|
656
|
+
}
|
|
657
|
+
function markPayloadTruncated(payload) {
|
|
658
|
+
if (payload.metaData && typeof payload.metaData === "object" && !Array.isArray(payload.metaData)) {
|
|
659
|
+
return {
|
|
660
|
+
...payload,
|
|
661
|
+
metaData: {
|
|
662
|
+
...payload.metaData,
|
|
663
|
+
payloadTruncated: true
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
return {
|
|
668
|
+
...payload,
|
|
669
|
+
payloadTruncated: true
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
function truncatePayload(payload, truncateStringLength) {
|
|
673
|
+
const cloned = clonePayload(payload);
|
|
674
|
+
if (!cloned) return void 0;
|
|
675
|
+
return markPayloadTruncated(truncateValue(cloned, truncateStringLength));
|
|
676
|
+
}
|
|
677
|
+
function getPayloadMessageId(payload) {
|
|
678
|
+
const value = payload.metaData?.requestId ?? payload.messageId;
|
|
679
|
+
return value === void 0 ? void 0 : String(value);
|
|
680
|
+
}
|
|
681
|
+
function preparePayloadForSizePolicy(payload, options = {}) {
|
|
682
|
+
const maxPayloadBytes = options.maxPayloadBytes ?? 64e3;
|
|
683
|
+
const payloadSizePolicy = options.payloadSizePolicy ?? "drop";
|
|
684
|
+
const payloadTruncateStringLength = options.payloadTruncateStringLength ?? 1024;
|
|
685
|
+
if (payloadByteLength(payload) <= maxPayloadBytes) {
|
|
686
|
+
return { ok: true, payload, truncated: false };
|
|
687
|
+
}
|
|
688
|
+
if (payloadSizePolicy === "truncate") {
|
|
689
|
+
const truncatedPayload = truncatePayload(payload, payloadTruncateStringLength);
|
|
690
|
+
if (truncatedPayload && payloadByteLength(truncatedPayload) <= maxPayloadBytes) {
|
|
691
|
+
return { ok: true, payload: truncatedPayload, truncated: true };
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
const messageId = getPayloadMessageId(payload);
|
|
695
|
+
return messageId === void 0 ? { ok: false, reason: "payload_too_large" } : { ok: false, reason: "payload_too_large", messageId };
|
|
696
|
+
}
|
|
697
|
+
|
|
141
698
|
// src/browser/core/delivery.ts
|
|
142
699
|
function createId(prefix) {
|
|
143
700
|
return `${prefix}_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
|
|
@@ -169,7 +726,6 @@ function createDeliveryManager(config) {
|
|
|
169
726
|
const lockTtlMs = config.lockTtlMs ?? 5e3;
|
|
170
727
|
const tabId = config.tabId ?? createId("tab");
|
|
171
728
|
const batchSize = config.batchSize ?? 25;
|
|
172
|
-
const maxPayloadBytes = config.maxPayloadBytes ?? 64e3;
|
|
173
729
|
function recordDrop(event) {
|
|
174
730
|
diagnostics.dropped.push(event);
|
|
175
731
|
config.onDrop?.(event);
|
|
@@ -178,12 +734,22 @@ function createDeliveryManager(config) {
|
|
|
178
734
|
diagnostics.lastError = error.message;
|
|
179
735
|
config.onError?.(error);
|
|
180
736
|
}
|
|
181
|
-
function
|
|
182
|
-
const
|
|
183
|
-
if (
|
|
184
|
-
|
|
737
|
+
function preparePayloadForSend(payload) {
|
|
738
|
+
const sizePolicyOptions = {};
|
|
739
|
+
if (config.maxPayloadBytes !== void 0) sizePolicyOptions.maxPayloadBytes = config.maxPayloadBytes;
|
|
740
|
+
if (config.payloadSizePolicy !== void 0) sizePolicyOptions.payloadSizePolicy = config.payloadSizePolicy;
|
|
741
|
+
if (config.payloadTruncateStringLength !== void 0) {
|
|
742
|
+
sizePolicyOptions.payloadTruncateStringLength = config.payloadTruncateStringLength;
|
|
185
743
|
}
|
|
186
|
-
|
|
744
|
+
const prepared = preparePayloadForSizePolicy(payload, sizePolicyOptions);
|
|
745
|
+
if (prepared.ok) return prepared.payload;
|
|
746
|
+
const diagnostic = {
|
|
747
|
+
reason: prepared.reason,
|
|
748
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
749
|
+
};
|
|
750
|
+
if (prepared.messageId !== void 0) diagnostic.messageId = prepared.messageId;
|
|
751
|
+
recordDrop(diagnostic);
|
|
752
|
+
return void 0;
|
|
187
753
|
}
|
|
188
754
|
function recordStorageUnavailable() {
|
|
189
755
|
recordDrop({
|
|
@@ -273,7 +839,19 @@ function createDeliveryManager(config) {
|
|
|
273
839
|
idempotencyKey: String(payload.idempotencyKey ?? createIdempotencyKey(payload, messageId))
|
|
274
840
|
};
|
|
275
841
|
}
|
|
842
|
+
function tryBeacon(body) {
|
|
843
|
+
if (!config.useBeacon) return false;
|
|
844
|
+
const sendBeacon = globalThis.navigator?.sendBeacon;
|
|
845
|
+
if (typeof sendBeacon !== "function") return false;
|
|
846
|
+
try {
|
|
847
|
+
const blob = new Blob([JSON.stringify(body)], { type: "application/json" });
|
|
848
|
+
return sendBeacon.call(globalThis.navigator, config.endpoint, blob);
|
|
849
|
+
} catch {
|
|
850
|
+
return false;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
276
853
|
async function deliver(body) {
|
|
854
|
+
if (tryBeacon(body)) return;
|
|
277
855
|
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
278
856
|
if (typeof fetchImpl !== "function") {
|
|
279
857
|
throw new Error("fetch_unavailable");
|
|
@@ -290,26 +868,22 @@ function createDeliveryManager(config) {
|
|
|
290
868
|
return {
|
|
291
869
|
async send(payload) {
|
|
292
870
|
const body = withEnvelope(payload);
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
messageId: String(body.metaData?.requestId ?? body.messageId),
|
|
296
|
-
reason: "payload_too_large",
|
|
297
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
298
|
-
});
|
|
871
|
+
const preparedBody = preparePayloadForSend(body);
|
|
872
|
+
if (!preparedBody) {
|
|
299
873
|
return;
|
|
300
874
|
}
|
|
301
875
|
diagnostics.inFlight += 1;
|
|
302
876
|
try {
|
|
303
|
-
await deliver(
|
|
877
|
+
await deliver(preparedBody);
|
|
304
878
|
} catch (error) {
|
|
305
879
|
const deliveryError = error instanceof Error ? error : new Error(String(error));
|
|
306
880
|
recordError(deliveryError);
|
|
307
881
|
enqueue({
|
|
308
|
-
messageId: String(body
|
|
882
|
+
messageId: String(getPayloadMessageId(body)),
|
|
309
883
|
savedAt: Date.now(),
|
|
310
884
|
attempts: 1,
|
|
311
885
|
lastError: deliveryError.message,
|
|
312
|
-
payload:
|
|
886
|
+
payload: preparedBody
|
|
313
887
|
});
|
|
314
888
|
} finally {
|
|
315
889
|
diagnostics.inFlight -= 1;
|
|
@@ -422,60 +996,286 @@ function createDeliveryManager(config) {
|
|
|
422
996
|
};
|
|
423
997
|
}
|
|
424
998
|
|
|
425
|
-
// src/browser/core/
|
|
426
|
-
var
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
"name",
|
|
436
|
-
"token",
|
|
437
|
-
"secret",
|
|
438
|
-
"password",
|
|
439
|
-
"session",
|
|
440
|
-
"cookie"
|
|
441
|
-
]);
|
|
442
|
-
function sanitizeValue(value, allow) {
|
|
443
|
-
if (Array.isArray(value)) {
|
|
444
|
-
return value.map((item) => sanitizeValue(item, allow));
|
|
999
|
+
// src/browser/core/identity.ts
|
|
1000
|
+
var ANONYMOUS_ID_STORAGE_KEY = "dmd_anonymous_id";
|
|
1001
|
+
var LEGACY_ANONYMOUS_ID_STORAGE_KEY = "anonymousId";
|
|
1002
|
+
function getUrlParam(name) {
|
|
1003
|
+
const href = getBrowserWindow()?.location?.href;
|
|
1004
|
+
if (!href) return null;
|
|
1005
|
+
try {
|
|
1006
|
+
return new URL(href).searchParams.get(name);
|
|
1007
|
+
} catch {
|
|
1008
|
+
return null;
|
|
445
1009
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
1010
|
+
}
|
|
1011
|
+
function resolveAnonymousId(persistence) {
|
|
1012
|
+
const urlAnonymousId = getUrlParam("aid");
|
|
1013
|
+
if (isUuid(urlAnonymousId)) {
|
|
1014
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, urlAnonymousId);
|
|
1015
|
+
return urlAnonymousId;
|
|
1016
|
+
}
|
|
1017
|
+
const storedAnonymousId = persistence.getItem(ANONYMOUS_ID_STORAGE_KEY);
|
|
1018
|
+
if (isUuid(storedAnonymousId)) {
|
|
1019
|
+
return storedAnonymousId;
|
|
1020
|
+
}
|
|
1021
|
+
const legacyAnonymousId = persistence.getItem(LEGACY_ANONYMOUS_ID_STORAGE_KEY);
|
|
1022
|
+
if (isUuid(legacyAnonymousId)) {
|
|
1023
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, legacyAnonymousId);
|
|
1024
|
+
return legacyAnonymousId;
|
|
1025
|
+
}
|
|
1026
|
+
const anonymousId = createUuid();
|
|
1027
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, anonymousId);
|
|
1028
|
+
return anonymousId;
|
|
1029
|
+
}
|
|
1030
|
+
function resetAnonymousId(persistence) {
|
|
1031
|
+
const anonymousId = createUuid();
|
|
1032
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, anonymousId);
|
|
1033
|
+
return anonymousId;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
// src/browser/core/page-context.ts
|
|
1037
|
+
function redactSearch(search) {
|
|
1038
|
+
const redacted = redactUrl(search);
|
|
1039
|
+
return redacted.startsWith("/?") ? redacted.slice(1) : redacted;
|
|
1040
|
+
}
|
|
1041
|
+
function getBrowserPageContext() {
|
|
1042
|
+
const browserWindow = getBrowserWindow();
|
|
1043
|
+
const documentRef = browserWindow?.document ?? globalThis.document;
|
|
1044
|
+
const location = browserWindow?.location;
|
|
1045
|
+
const page2 = {};
|
|
1046
|
+
if (location?.href) page2.url = location.href;
|
|
1047
|
+
if (location?.pathname) page2.path = location.pathname;
|
|
1048
|
+
if (location?.search) page2.search = redactSearch(location.search);
|
|
1049
|
+
if (documentRef?.title) page2.title = documentRef.title;
|
|
1050
|
+
if (documentRef?.referrer) page2.referrer = redactUrl(documentRef.referrer);
|
|
1051
|
+
return page2;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// src/browser/core/persistence.ts
|
|
1055
|
+
function createPersistenceHealth(requested) {
|
|
1056
|
+
return {
|
|
1057
|
+
requested,
|
|
1058
|
+
cookieFallbackUsed: false,
|
|
1059
|
+
memoryFallbackUsed: requested === "memory",
|
|
1060
|
+
failures: []
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
function recordFailure(health, backend, operation, error) {
|
|
1064
|
+
health.failures.push({
|
|
1065
|
+
backend,
|
|
1066
|
+
operation,
|
|
1067
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1068
|
+
});
|
|
1069
|
+
if (health.failures.length > 25) {
|
|
1070
|
+
health.failures.shift();
|
|
450
1071
|
}
|
|
451
|
-
return value;
|
|
452
1072
|
}
|
|
453
|
-
function
|
|
454
|
-
const
|
|
455
|
-
return
|
|
1073
|
+
function createMemoryPersistence(health = createPersistenceHealth("memory")) {
|
|
1074
|
+
const memory = {};
|
|
1075
|
+
return {
|
|
1076
|
+
getItem(key) {
|
|
1077
|
+
return Object.prototype.hasOwnProperty.call(memory, key) ? memory[key] ?? null : null;
|
|
1078
|
+
},
|
|
1079
|
+
setItem(key, value) {
|
|
1080
|
+
memory[key] = value;
|
|
1081
|
+
return true;
|
|
1082
|
+
},
|
|
1083
|
+
removeItem(key) {
|
|
1084
|
+
delete memory[key];
|
|
1085
|
+
},
|
|
1086
|
+
getHealth() {
|
|
1087
|
+
return {
|
|
1088
|
+
...health,
|
|
1089
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
1090
|
+
};
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
function getCookie2(name) {
|
|
1095
|
+
const browserWindow = getBrowserWindow();
|
|
1096
|
+
const cookie = browserWindow?.document?.cookie;
|
|
1097
|
+
if (!cookie) return null;
|
|
1098
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1099
|
+
const match = new RegExp(`(?:^|; )${escapedName}=([^;]*)`).exec(cookie);
|
|
1100
|
+
return match ? decodeURIComponent(match[1] ?? "") : null;
|
|
1101
|
+
}
|
|
1102
|
+
function setCookie(name, value) {
|
|
1103
|
+
const browserWindow = getBrowserWindow();
|
|
1104
|
+
if (!browserWindow?.document) return false;
|
|
1105
|
+
try {
|
|
1106
|
+
const expires = new Date(Date.now() + 365 * 24 * 60 * 60 * 1e3).toUTCString();
|
|
1107
|
+
const secure = browserWindow.location?.protocol === "https:" ? "; Secure" : "";
|
|
1108
|
+
browserWindow.document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/${secure}; SameSite=Lax`;
|
|
1109
|
+
return true;
|
|
1110
|
+
} catch {
|
|
1111
|
+
return false;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
function removeCookie(name) {
|
|
1115
|
+
const browserWindow = getBrowserWindow();
|
|
1116
|
+
if (!browserWindow?.document) return;
|
|
1117
|
+
browserWindow.document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
|
1118
|
+
}
|
|
1119
|
+
function getLocalStorage() {
|
|
1120
|
+
const browserWindow = getBrowserWindow();
|
|
1121
|
+
try {
|
|
1122
|
+
return browserWindow?.localStorage;
|
|
1123
|
+
} catch {
|
|
1124
|
+
return void 0;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
function getSessionStorage() {
|
|
1128
|
+
const browserWindow = getBrowserWindow();
|
|
1129
|
+
try {
|
|
1130
|
+
return browserWindow?.sessionStorage;
|
|
1131
|
+
} catch {
|
|
1132
|
+
return void 0;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
function createBrowserPersistence(mode = "localStorage+cookie") {
|
|
1136
|
+
const health = createPersistenceHealth(mode);
|
|
1137
|
+
const memory = createMemoryPersistence(health);
|
|
1138
|
+
if (mode === "none") {
|
|
1139
|
+
return {
|
|
1140
|
+
getItem() {
|
|
1141
|
+
return null;
|
|
1142
|
+
},
|
|
1143
|
+
setItem() {
|
|
1144
|
+
return false;
|
|
1145
|
+
},
|
|
1146
|
+
removeItem() {
|
|
1147
|
+
},
|
|
1148
|
+
getHealth() {
|
|
1149
|
+
return {
|
|
1150
|
+
...health,
|
|
1151
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
};
|
|
1155
|
+
}
|
|
1156
|
+
if (mode === "memory") return memory;
|
|
1157
|
+
const primary = mode === "sessionStorage" ? getSessionStorage() : getLocalStorage();
|
|
1158
|
+
const useCookie = mode === "cookie" || mode === "localStorage+cookie" || !primary;
|
|
1159
|
+
return {
|
|
1160
|
+
getItem(key) {
|
|
1161
|
+
try {
|
|
1162
|
+
const stored = primary?.getItem(key);
|
|
1163
|
+
if (stored) return stored;
|
|
1164
|
+
} catch (error) {
|
|
1165
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "get", error);
|
|
1166
|
+
}
|
|
1167
|
+
if (useCookie) {
|
|
1168
|
+
const cookie = getCookie2(key);
|
|
1169
|
+
if (cookie) {
|
|
1170
|
+
health.cookieFallbackUsed = true;
|
|
1171
|
+
return cookie;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
const value = memory.getItem(key);
|
|
1175
|
+
if (value !== null) health.memoryFallbackUsed = true;
|
|
1176
|
+
return value;
|
|
1177
|
+
},
|
|
1178
|
+
setItem(key, value) {
|
|
1179
|
+
let wrote = false;
|
|
1180
|
+
try {
|
|
1181
|
+
primary?.setItem(key, value);
|
|
1182
|
+
wrote = primary !== void 0;
|
|
1183
|
+
} catch (error) {
|
|
1184
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "set", error);
|
|
1185
|
+
wrote = false;
|
|
1186
|
+
}
|
|
1187
|
+
if (useCookie) {
|
|
1188
|
+
const cookieWrote = setCookie(key, value);
|
|
1189
|
+
if (cookieWrote) health.cookieFallbackUsed = true;
|
|
1190
|
+
wrote = cookieWrote || wrote;
|
|
1191
|
+
}
|
|
1192
|
+
if (!wrote) {
|
|
1193
|
+
health.memoryFallbackUsed = true;
|
|
1194
|
+
return memory.setItem(key, value);
|
|
1195
|
+
}
|
|
1196
|
+
if (mode === "localStorage+cookie") {
|
|
1197
|
+
memory.setItem(key, value);
|
|
1198
|
+
}
|
|
1199
|
+
return true;
|
|
1200
|
+
},
|
|
1201
|
+
removeItem(key) {
|
|
1202
|
+
try {
|
|
1203
|
+
primary?.removeItem(key);
|
|
1204
|
+
} catch (error) {
|
|
1205
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "remove", error);
|
|
1206
|
+
}
|
|
1207
|
+
if (useCookie) removeCookie(key);
|
|
1208
|
+
memory.removeItem(key);
|
|
1209
|
+
},
|
|
1210
|
+
getHealth() {
|
|
1211
|
+
return {
|
|
1212
|
+
...health,
|
|
1213
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
};
|
|
456
1217
|
}
|
|
457
1218
|
|
|
458
|
-
// src/browser/core/
|
|
459
|
-
var
|
|
460
|
-
function
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
1219
|
+
// src/browser/core/session.ts
|
|
1220
|
+
var SESSION_STORAGE_KEY2 = "sessionData";
|
|
1221
|
+
function getUrlParam2(name) {
|
|
1222
|
+
const href = getBrowserWindow()?.location?.href;
|
|
1223
|
+
if (!href) return null;
|
|
1224
|
+
try {
|
|
1225
|
+
return new URL(href).searchParams.get(name);
|
|
1226
|
+
} catch {
|
|
1227
|
+
return null;
|
|
466
1228
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
1229
|
+
}
|
|
1230
|
+
function readStoredSession(persistence) {
|
|
1231
|
+
const rawSession = persistence.getItem(SESSION_STORAGE_KEY2);
|
|
1232
|
+
if (!rawSession) return void 0;
|
|
1233
|
+
try {
|
|
1234
|
+
const parsed = JSON.parse(rawSession);
|
|
1235
|
+
if (isUuid(parsed.sessionId) && typeof parsed.timestamp === "number") {
|
|
1236
|
+
return {
|
|
1237
|
+
sessionId: parsed.sessionId,
|
|
1238
|
+
timestamp: parsed.timestamp
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
} catch {
|
|
1242
|
+
persistence.removeItem(SESSION_STORAGE_KEY2);
|
|
471
1243
|
}
|
|
472
|
-
return
|
|
1244
|
+
return void 0;
|
|
1245
|
+
}
|
|
1246
|
+
function writeStoredSession(persistence, sessionId, timestamp) {
|
|
1247
|
+
persistence.setItem(SESSION_STORAGE_KEY2, JSON.stringify({ sessionId, timestamp }));
|
|
1248
|
+
}
|
|
1249
|
+
function createSessionManager(persistence, idleTimeoutSeconds = 30 * 60) {
|
|
1250
|
+
function resolveSessionId() {
|
|
1251
|
+
const now = Date.now();
|
|
1252
|
+
const urlSessionId = getUrlParam2("sid") ?? getUrlParam2("session_id");
|
|
1253
|
+
if (isUuid(urlSessionId)) {
|
|
1254
|
+
writeStoredSession(persistence, urlSessionId, now);
|
|
1255
|
+
return urlSessionId;
|
|
1256
|
+
}
|
|
1257
|
+
const storedSession = readStoredSession(persistence);
|
|
1258
|
+
if (storedSession && now - storedSession.timestamp <= idleTimeoutSeconds * 1e3) {
|
|
1259
|
+
writeStoredSession(persistence, storedSession.sessionId, now);
|
|
1260
|
+
return storedSession.sessionId;
|
|
1261
|
+
}
|
|
1262
|
+
const sessionId = createUuid();
|
|
1263
|
+
writeStoredSession(persistence, sessionId, now);
|
|
1264
|
+
return sessionId;
|
|
1265
|
+
}
|
|
1266
|
+
return {
|
|
1267
|
+
getSessionId() {
|
|
1268
|
+
return resolveSessionId();
|
|
1269
|
+
},
|
|
1270
|
+
reset() {
|
|
1271
|
+
const sessionId = createUuid();
|
|
1272
|
+
writeStoredSession(persistence, sessionId, Date.now());
|
|
1273
|
+
return sessionId;
|
|
1274
|
+
}
|
|
1275
|
+
};
|
|
473
1276
|
}
|
|
474
1277
|
|
|
475
1278
|
// src/browser/core/DriveMetaDataSDK.ts
|
|
476
|
-
function createId2(prefix) {
|
|
477
|
-
return `${prefix}_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
|
|
478
|
-
}
|
|
479
1279
|
function endpointFromConfig(config) {
|
|
480
1280
|
const host = config.apiHost ?? "https://sdk.drivemetadata.com/v2";
|
|
481
1281
|
return `${host.replace(/\/$/, "")}/data-collector`;
|
|
@@ -486,14 +1286,6 @@ function requireConfigString(value, field) {
|
|
|
486
1286
|
}
|
|
487
1287
|
return value;
|
|
488
1288
|
}
|
|
489
|
-
function getBrowserStorage() {
|
|
490
|
-
const browserWindow = getBrowserWindow();
|
|
491
|
-
try {
|
|
492
|
-
return browserWindow?.localStorage;
|
|
493
|
-
} catch {
|
|
494
|
-
return void 0;
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
1289
|
var DriveMetaDataSDK = class {
|
|
498
1290
|
constructor(config) {
|
|
499
1291
|
this.initialized = true;
|
|
@@ -506,30 +1298,36 @@ var DriveMetaDataSDK = class {
|
|
|
506
1298
|
requireConfigString(config.writeKey || config.token, "writeKey or token");
|
|
507
1299
|
this.config = config;
|
|
508
1300
|
this.endpoint = endpointFromConfig(config);
|
|
509
|
-
const
|
|
1301
|
+
const storagePersistence = createBrowserPersistence(config.persistence);
|
|
1302
|
+
this.persistence = createDmdAttributesPersistence(storagePersistence);
|
|
1303
|
+
this.session = createSessionManager(this.persistence, config.sessionIdleTimeoutSeconds);
|
|
510
1304
|
const deliveryConfig = {
|
|
511
|
-
endpoint: this.endpoint
|
|
1305
|
+
endpoint: this.endpoint,
|
|
1306
|
+
storage: storagePersistence
|
|
512
1307
|
};
|
|
513
1308
|
if (config.delivery?.maxQueueSize !== void 0) deliveryConfig.maxQueueSize = config.delivery.maxQueueSize;
|
|
514
1309
|
if (config.delivery?.queueTtlMs !== void 0) deliveryConfig.queueTtlMs = config.delivery.queueTtlMs;
|
|
515
1310
|
if (config.delivery?.retryDelayMs !== void 0) deliveryConfig.retryDelayMs = config.delivery.retryDelayMs;
|
|
516
1311
|
if (config.delivery?.maxRetryDelayMs !== void 0) deliveryConfig.maxRetryDelayMs = config.delivery.maxRetryDelayMs;
|
|
517
1312
|
if (config.delivery?.maxPayloadBytes !== void 0) deliveryConfig.maxPayloadBytes = config.delivery.maxPayloadBytes;
|
|
1313
|
+
if (config.delivery?.payloadSizePolicy !== void 0) deliveryConfig.payloadSizePolicy = config.delivery.payloadSizePolicy;
|
|
1314
|
+
if (config.delivery?.payloadTruncateStringLength !== void 0) {
|
|
1315
|
+
deliveryConfig.payloadTruncateStringLength = config.delivery.payloadTruncateStringLength;
|
|
1316
|
+
}
|
|
1317
|
+
if (config.delivery?.useBeacon !== void 0) deliveryConfig.useBeacon = config.delivery.useBeacon;
|
|
518
1318
|
if (config.delivery?.batchSize !== void 0) deliveryConfig.batchSize = config.delivery.batchSize;
|
|
519
1319
|
if (config.onDrop !== void 0) deliveryConfig.onDrop = config.onDrop;
|
|
520
1320
|
if (config.onError !== void 0) deliveryConfig.onError = config.onError;
|
|
521
|
-
this.delivery = createDeliveryManager(
|
|
522
|
-
...deliveryConfig,
|
|
523
|
-
storage
|
|
524
|
-
} : deliveryConfig);
|
|
1321
|
+
this.delivery = createDeliveryManager(deliveryConfig);
|
|
525
1322
|
this.initialRetryDelayMs = config.delivery?.retryDelayMs ?? 1e3;
|
|
526
1323
|
this.retryDelayMs = this.initialRetryDelayMs;
|
|
527
1324
|
this.maxRetryDelayMs = config.delivery?.maxRetryDelayMs ?? 3e4;
|
|
528
1325
|
this.writeKey = config.writeKey || config.token || "";
|
|
529
|
-
this.identity = { anonymousId:
|
|
530
|
-
this.
|
|
1326
|
+
this.identity = { anonymousId: resolveAnonymousId(this.persistence) };
|
|
1327
|
+
captureAttributionFromUrl(this.persistence);
|
|
531
1328
|
this.consentState = normalizeConsent(config.gdprConsent ?? config.consent);
|
|
532
1329
|
this.gdprConsent = this.consentState.analytics;
|
|
1330
|
+
this.installAutocapture();
|
|
533
1331
|
if (!config.delivery?.disableLifecycleFlush) {
|
|
534
1332
|
this.installLifecycleFlush();
|
|
535
1333
|
}
|
|
@@ -569,7 +1367,8 @@ var DriveMetaDataSDK = class {
|
|
|
569
1367
|
}
|
|
570
1368
|
}
|
|
571
1369
|
reset() {
|
|
572
|
-
this.identity = { anonymousId:
|
|
1370
|
+
this.identity = { anonymousId: resetAnonymousId(this.persistence) };
|
|
1371
|
+
this.session.reset();
|
|
573
1372
|
this.queue = [];
|
|
574
1373
|
this.offline = false;
|
|
575
1374
|
if (this.retryTimer !== void 0) {
|
|
@@ -578,8 +1377,20 @@ var DriveMetaDataSDK = class {
|
|
|
578
1377
|
}
|
|
579
1378
|
this.lifecycleCleanup?.();
|
|
580
1379
|
this.lifecycleCleanup = void 0;
|
|
1380
|
+
this.autocaptureCleanup?.();
|
|
1381
|
+
this.autocaptureCleanup = void 0;
|
|
581
1382
|
this.delivery.clearQueue("manual_clear");
|
|
582
1383
|
}
|
|
1384
|
+
disposeForTests() {
|
|
1385
|
+
if (this.retryTimer !== void 0) {
|
|
1386
|
+
clearTimeout(this.retryTimer);
|
|
1387
|
+
this.retryTimer = void 0;
|
|
1388
|
+
}
|
|
1389
|
+
this.lifecycleCleanup?.();
|
|
1390
|
+
this.lifecycleCleanup = void 0;
|
|
1391
|
+
this.autocaptureCleanup?.();
|
|
1392
|
+
this.autocaptureCleanup = void 0;
|
|
1393
|
+
}
|
|
583
1394
|
setConsent(consent) {
|
|
584
1395
|
this.consentState = typeof consent === "object" ? mergeConsent(this.consentState, consent) : normalizeConsent(consent);
|
|
585
1396
|
this.gdprConsent = this.consentState.analytics;
|
|
@@ -594,6 +1405,7 @@ var DriveMetaDataSDK = class {
|
|
|
594
1405
|
initialized: this.initialized,
|
|
595
1406
|
consent: this.gdprConsent,
|
|
596
1407
|
consentPurposes: this.consentState,
|
|
1408
|
+
persistence: this.persistence.getHealth(),
|
|
597
1409
|
queueSize: deliveryDiagnostics.queued,
|
|
598
1410
|
offline: this.offline || deliveryDiagnostics.queued > 0,
|
|
599
1411
|
droppedEvents: this.droppedEvents + deliveryDiagnostics.dropped.length,
|
|
@@ -608,7 +1420,9 @@ var DriveMetaDataSDK = class {
|
|
|
608
1420
|
void this.delivery.send(payload).then(() => {
|
|
609
1421
|
const diagnostics = this.delivery.getDiagnostics();
|
|
610
1422
|
this.offline = diagnostics.queued > 0;
|
|
611
|
-
|
|
1423
|
+
if (diagnostics.lastError !== void 0) {
|
|
1424
|
+
this.lastError = diagnostics.lastError;
|
|
1425
|
+
}
|
|
612
1426
|
if (diagnostics.queued > 0) {
|
|
613
1427
|
this.scheduleRetryFlush();
|
|
614
1428
|
}
|
|
@@ -640,6 +1454,28 @@ var DriveMetaDataSDK = class {
|
|
|
640
1454
|
}
|
|
641
1455
|
};
|
|
642
1456
|
}
|
|
1457
|
+
installAutocapture() {
|
|
1458
|
+
const browserWindow = getBrowserWindow();
|
|
1459
|
+
if (!browserWindow) return;
|
|
1460
|
+
if (this.config.autocapture === false) return;
|
|
1461
|
+
const capturePageview = this.config.capturePageview !== false;
|
|
1462
|
+
const capturePageleave = this.config.capturePageleave !== false;
|
|
1463
|
+
const controller = installAutocapture({
|
|
1464
|
+
browserWindow,
|
|
1465
|
+
capturePageview,
|
|
1466
|
+
capturePageleave,
|
|
1467
|
+
onPageView: () => {
|
|
1468
|
+
this.page();
|
|
1469
|
+
},
|
|
1470
|
+
onPageLeave: () => {
|
|
1471
|
+
this.trackEvent("page_leave", { url: browserWindow.location.href });
|
|
1472
|
+
},
|
|
1473
|
+
onRouteChange: () => {
|
|
1474
|
+
captureAttributionFromUrl(this.persistence);
|
|
1475
|
+
}
|
|
1476
|
+
});
|
|
1477
|
+
this.autocaptureCleanup = controller.cleanup;
|
|
1478
|
+
}
|
|
643
1479
|
scheduleRetryFlush() {
|
|
644
1480
|
if (this.retryTimer !== void 0) return;
|
|
645
1481
|
const delay = Math.min(this.retryDelayMs, this.maxRetryDelayMs);
|
|
@@ -665,7 +1501,7 @@ var DriveMetaDataSDK = class {
|
|
|
665
1501
|
type,
|
|
666
1502
|
event,
|
|
667
1503
|
properties: sanitizeProperties(properties),
|
|
668
|
-
messageId: options.messageId
|
|
1504
|
+
messageId: ensureUuid(options.messageId),
|
|
669
1505
|
timestamp: options.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
670
1506
|
context: options.context ?? {},
|
|
671
1507
|
anonymousId: this.identity.anonymousId,
|
|
@@ -674,7 +1510,7 @@ var DriveMetaDataSDK = class {
|
|
|
674
1510
|
appId: this.config.appId,
|
|
675
1511
|
writeKey: this.writeKey,
|
|
676
1512
|
consent: this.consentState,
|
|
677
|
-
sessionId: this.
|
|
1513
|
+
sessionId: this.session.getSessionId()
|
|
678
1514
|
};
|
|
679
1515
|
if (this.identity.userId !== void 0) prepared.userId = this.identity.userId;
|
|
680
1516
|
if (this.identity.groupId !== void 0) prepared.groupId = this.identity.groupId;
|
|
@@ -698,10 +1534,21 @@ var DriveMetaDataSDK = class {
|
|
|
698
1534
|
if (!validation.ok) {
|
|
699
1535
|
this.lastError = `DMD SDK schema warning: ${validation.errors.join(", ")}`;
|
|
700
1536
|
}
|
|
701
|
-
this.
|
|
1537
|
+
const collectorPayload = this.toCollectorPayload(prepared);
|
|
1538
|
+
const backendValidation = validateBackendCollectorPayload(collectorPayload);
|
|
1539
|
+
if (!backendValidation.ok && this.config.schemaValidation === "strict") {
|
|
1540
|
+
this.lastError = `DMD SDK backend schema warning: ${backendValidation.errors.join(", ")}`;
|
|
1541
|
+
this.recordDrop(type, "invalid_payload", event);
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1544
|
+
if (!backendValidation.ok) {
|
|
1545
|
+
this.lastError = `DMD SDK backend schema warning: ${backendValidation.errors.join(", ")}`;
|
|
1546
|
+
}
|
|
1547
|
+
this.sendEvent(collectorPayload);
|
|
702
1548
|
}
|
|
703
1549
|
toCollectorPayload(prepared) {
|
|
704
1550
|
const browserWindow = getBrowserWindow();
|
|
1551
|
+
const pageContext = getBrowserPageContext();
|
|
705
1552
|
return createBackendCollectorPayload({
|
|
706
1553
|
requestId: prepared.messageId,
|
|
707
1554
|
timestamp: prepared.timestamp,
|
|
@@ -713,15 +1560,19 @@ var DriveMetaDataSDK = class {
|
|
|
713
1560
|
sessionId: prepared.sessionId,
|
|
714
1561
|
ua: browserWindow?.navigator?.userAgent,
|
|
715
1562
|
appId: prepared.appId,
|
|
716
|
-
pageUrl: browserWindow?.location?.href,
|
|
717
|
-
eventData: {
|
|
1563
|
+
pageUrl: pageContext.url ?? browserWindow?.location?.href,
|
|
1564
|
+
eventData: mergeStoredAttribution({
|
|
718
1565
|
...prepared.properties,
|
|
1566
|
+
page: {
|
|
1567
|
+
...pageContext,
|
|
1568
|
+
...prepared.properties.page && typeof prepared.properties.page === "object" ? prepared.properties.page : {}
|
|
1569
|
+
},
|
|
719
1570
|
anonymousId: prepared.anonymousId,
|
|
720
1571
|
sessionId: prepared.sessionId,
|
|
721
1572
|
timestamp: prepared.timestamp,
|
|
722
1573
|
requestSentAt: prepared.timestamp,
|
|
723
1574
|
requestReceivedAt: prepared.timestamp
|
|
724
|
-
}
|
|
1575
|
+
}, this.persistence)
|
|
725
1576
|
});
|
|
726
1577
|
}
|
|
727
1578
|
recordDrop(type, reason, event) {
|
|
@@ -797,7 +1648,7 @@ function initDmdSDK(config) {
|
|
|
797
1648
|
return publicSingleton;
|
|
798
1649
|
}
|
|
799
1650
|
try {
|
|
800
|
-
const instance = new DriveMetaDataSDK(config);
|
|
1651
|
+
const instance = new DriveMetaDataSDK(normalizeBrowserConfig(config));
|
|
801
1652
|
return setSingleton(instance);
|
|
802
1653
|
} catch (error) {
|
|
803
1654
|
lastError = error instanceof Error ? error.message : String(error);
|