@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.js
CHANGED
|
@@ -13,12 +13,62 @@ var __decorateParam = (index, decorator) => (target, key) => decorator(target, k
|
|
|
13
13
|
// src/angular/dmd-analytics.service.ts
|
|
14
14
|
import { Inject, Injectable, Optional } from "@angular/core";
|
|
15
15
|
|
|
16
|
+
// src/browser/core/browser-config.ts
|
|
17
|
+
function setIfDefined(target, key, value) {
|
|
18
|
+
if (value !== void 0) {
|
|
19
|
+
target[key] = value;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function normalizeBrowserConfig(input) {
|
|
23
|
+
const normalized = {
|
|
24
|
+
...input,
|
|
25
|
+
clientId: input.clientId ?? "",
|
|
26
|
+
workspaceId: input.workspaceId ?? "",
|
|
27
|
+
appId: input.appId ?? ""
|
|
28
|
+
};
|
|
29
|
+
setIfDefined(normalized, "apiHost", input.apiHost);
|
|
30
|
+
setIfDefined(normalized, "capturePageview", input.capturePageview);
|
|
31
|
+
setIfDefined(normalized, "capturePageleave", input.capturePageleave);
|
|
32
|
+
setIfDefined(normalized, "captureDeadClicks", input.captureDeadClicks);
|
|
33
|
+
setIfDefined(normalized, "crossSubdomainCookie", input.crossSubdomainCookie);
|
|
34
|
+
setIfDefined(normalized, "sessionIdleTimeoutSeconds", input.sessionIdleTimeoutSeconds);
|
|
35
|
+
setIfDefined(normalized, "schemaValidation", input.schemaValidation);
|
|
36
|
+
setIfDefined(normalized, "beforeSend", input.beforeSend);
|
|
37
|
+
setIfDefined(normalized, "persistence", input.disablePersistence === true ? "none" : input.persistence);
|
|
38
|
+
return normalized;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/core/uuid.ts
|
|
42
|
+
function createUuid() {
|
|
43
|
+
const cryptoApi = globalThis.crypto;
|
|
44
|
+
if (typeof cryptoApi?.randomUUID === "function") {
|
|
45
|
+
return cryptoApi.randomUUID();
|
|
46
|
+
}
|
|
47
|
+
const bytes = new Uint8Array(16);
|
|
48
|
+
if (typeof cryptoApi?.getRandomValues === "function") {
|
|
49
|
+
cryptoApi.getRandomValues(bytes);
|
|
50
|
+
} else {
|
|
51
|
+
for (let index = 0; index < bytes.length; index += 1) {
|
|
52
|
+
bytes[index] = Math.floor(Math.random() * 256);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
56
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
57
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
58
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
59
|
+
}
|
|
60
|
+
function isUuid(value) {
|
|
61
|
+
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);
|
|
62
|
+
}
|
|
63
|
+
function ensureUuid(value) {
|
|
64
|
+
return isUuid(value) ? value : createUuid();
|
|
65
|
+
}
|
|
66
|
+
|
|
16
67
|
// src/core/backend-payload.ts
|
|
17
68
|
function formatUtcTimestamp(value) {
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
return date.toISOString().replace("T", " ").slice(0, 19);
|
|
69
|
+
const date = typeof value === "string" || typeof value === "number" || value instanceof Date ? new Date(value) : /* @__PURE__ */ new Date();
|
|
70
|
+
const safeDate = Number.isNaN(date.getTime()) ? /* @__PURE__ */ new Date() : date;
|
|
71
|
+
return safeDate.toISOString().replace("T", " ").slice(0, 19);
|
|
22
72
|
}
|
|
23
73
|
function cleanObject(value) {
|
|
24
74
|
if (Array.isArray(value)) {
|
|
@@ -49,15 +99,19 @@ function createBackendCollectorPayload(input) {
|
|
|
49
99
|
};
|
|
50
100
|
const metaData = {
|
|
51
101
|
...normalizedEventData,
|
|
52
|
-
requestId: input.requestId,
|
|
102
|
+
requestId: ensureUuid(typeof input.requestId === "string" ? input.requestId : void 0),
|
|
53
103
|
timestamp,
|
|
54
104
|
eventType: input.eventType,
|
|
55
105
|
requestFrom: input.requestFrom ?? "3",
|
|
56
106
|
clientId: input.clientId,
|
|
57
107
|
workspaceId: input.workspaceId,
|
|
58
108
|
token: input.token,
|
|
59
|
-
anonymousId:
|
|
60
|
-
|
|
109
|
+
anonymousId: ensureUuid(
|
|
110
|
+
typeof eventData.anonymousId === "string" ? eventData.anonymousId : typeof input.anonymousId === "string" ? input.anonymousId : void 0
|
|
111
|
+
),
|
|
112
|
+
sessionId: ensureUuid(
|
|
113
|
+
typeof eventData.sessionId === "string" ? eventData.sessionId : typeof input.sessionId === "string" ? input.sessionId : void 0
|
|
114
|
+
),
|
|
61
115
|
ua: input.ua,
|
|
62
116
|
appDetails: { app_id: input.appId },
|
|
63
117
|
page: { ...page2, url: page2.url ?? input.pageUrl },
|
|
@@ -68,12 +122,45 @@ function createBackendCollectorPayload(input) {
|
|
|
68
122
|
return cleanObject(payload);
|
|
69
123
|
}
|
|
70
124
|
|
|
71
|
-
// src/core/
|
|
72
|
-
|
|
73
|
-
|
|
125
|
+
// src/core/backend-schema.ts
|
|
126
|
+
var requiredMetaDataFields = [
|
|
127
|
+
"requestId",
|
|
128
|
+
"timestamp",
|
|
129
|
+
"eventType",
|
|
130
|
+
"requestFrom",
|
|
131
|
+
"clientId",
|
|
132
|
+
"workspaceId",
|
|
133
|
+
"anonymousId",
|
|
134
|
+
"sessionId"
|
|
135
|
+
];
|
|
136
|
+
function isPresent(value) {
|
|
137
|
+
return value !== null && value !== void 0 && value !== "";
|
|
138
|
+
}
|
|
139
|
+
function validateBackendCollectorPayload(payload) {
|
|
140
|
+
const errors = [];
|
|
141
|
+
const metaData = payload.metaData;
|
|
142
|
+
if (!metaData || typeof metaData !== "object" || Array.isArray(metaData)) {
|
|
143
|
+
return {
|
|
144
|
+
ok: false,
|
|
145
|
+
errors: ["metaData is required"]
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const metadataRecord = metaData;
|
|
149
|
+
for (const field of requiredMetaDataFields) {
|
|
150
|
+
if (!isPresent(metadataRecord[field])) {
|
|
151
|
+
errors.push(`metaData.${field} is required`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (isPresent(metadataRecord.eventType) && typeof metadataRecord.eventType !== "string") {
|
|
155
|
+
errors.push("metaData.eventType must be a string");
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
ok: errors.length === 0,
|
|
159
|
+
errors
|
|
160
|
+
};
|
|
74
161
|
}
|
|
75
162
|
|
|
76
|
-
// src/
|
|
163
|
+
// src/core/consent.ts
|
|
77
164
|
var purposes = [
|
|
78
165
|
"analytics",
|
|
79
166
|
"advertising",
|
|
@@ -113,6 +200,476 @@ function canCollectPurpose(consent, purpose) {
|
|
|
113
200
|
return consent[purpose] === "granted";
|
|
114
201
|
}
|
|
115
202
|
|
|
203
|
+
// src/core/event-schema.ts
|
|
204
|
+
var reservedKeys = /* @__PURE__ */ new Set(["messageId", "timestamp", "type", "event", "anonymousId", "userId", "context"]);
|
|
205
|
+
function validateEventEnvelope(envelope, options = {}) {
|
|
206
|
+
if (options.mode === "off") return { ok: true, errors: [] };
|
|
207
|
+
const errors = [];
|
|
208
|
+
if (typeof envelope.type !== "string") errors.push("type must be a string");
|
|
209
|
+
if (envelope.type === "track" && typeof envelope.event !== "string") {
|
|
210
|
+
errors.push("track event must include event name");
|
|
211
|
+
}
|
|
212
|
+
if (typeof envelope.messageId !== "string") errors.push("messageId must be a string");
|
|
213
|
+
if (typeof envelope.timestamp !== "string") errors.push("timestamp must be an ISO string");
|
|
214
|
+
for (const key of Object.keys(envelope.properties ?? {})) {
|
|
215
|
+
if (reservedKeys.has(key)) errors.push(`properties.${key} is reserved`);
|
|
216
|
+
}
|
|
217
|
+
return { ok: errors.length === 0, errors };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/core/environment.ts
|
|
221
|
+
function getBrowserWindow() {
|
|
222
|
+
return typeof window === "undefined" ? void 0 : window;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/core/privacy.ts
|
|
226
|
+
var sensitiveKeys = /* @__PURE__ */ new Set([
|
|
227
|
+
"email",
|
|
228
|
+
"phone",
|
|
229
|
+
"mobile",
|
|
230
|
+
"address",
|
|
231
|
+
"address1",
|
|
232
|
+
"address2",
|
|
233
|
+
"first_name",
|
|
234
|
+
"last_name",
|
|
235
|
+
"name",
|
|
236
|
+
"token",
|
|
237
|
+
"secret",
|
|
238
|
+
"password",
|
|
239
|
+
"session",
|
|
240
|
+
"cookie"
|
|
241
|
+
]);
|
|
242
|
+
function redactUrl(url, allowQueryKeys = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"]) {
|
|
243
|
+
const parsed = new URL(url, "https://placeholder.local");
|
|
244
|
+
for (const key of Array.from(parsed.searchParams.keys())) {
|
|
245
|
+
if (!allowQueryKeys.includes(key)) {
|
|
246
|
+
parsed.searchParams.set(key, "[REDACTED]");
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return url.startsWith("http") ? parsed.toString() : `${parsed.pathname}${parsed.search}`;
|
|
250
|
+
}
|
|
251
|
+
function sanitizeValue(value, allow, path = []) {
|
|
252
|
+
if (Array.isArray(value)) {
|
|
253
|
+
return value.map((item) => sanitizeValue(item, allow, path));
|
|
254
|
+
}
|
|
255
|
+
if (value && typeof value === "object") {
|
|
256
|
+
return Object.fromEntries(
|
|
257
|
+
Object.entries(value).filter(([key]) => {
|
|
258
|
+
const lowerKey = key.toLowerCase();
|
|
259
|
+
const lowerPath = path.map((item) => item.toLowerCase());
|
|
260
|
+
const isEcommerceItemName = lowerKey === "name" && lowerPath.includes("ecommerce") && lowerPath.includes("items");
|
|
261
|
+
return isEcommerceItemName || !sensitiveKeys.has(lowerKey) || allow.has(lowerKey);
|
|
262
|
+
}).map(([key, nestedValue]) => [key, sanitizeValue(nestedValue, allow, [...path, key])])
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
return value;
|
|
266
|
+
}
|
|
267
|
+
function sanitizeProperties(input, allowRawKeys = []) {
|
|
268
|
+
const allow = new Set(allowRawKeys.map((key) => key.toLowerCase()));
|
|
269
|
+
return sanitizeValue(input, allow);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/browser/core/attribute-persistence.ts
|
|
273
|
+
var DMD_ATTRIBUTES_STORAGE_KEY = "dmd_attributes";
|
|
274
|
+
var SESSION_STORAGE_KEY = "sessionData";
|
|
275
|
+
var SESSION_ID_KEY = "sessionId";
|
|
276
|
+
var SESSION_TIMESTAMP_KEY = "timestamp";
|
|
277
|
+
function isBlankValue(value) {
|
|
278
|
+
return value === null || value === void 0 || typeof value === "string" && value.trim() === "";
|
|
279
|
+
}
|
|
280
|
+
function readAttributes(base) {
|
|
281
|
+
const raw = base.getItem(DMD_ATTRIBUTES_STORAGE_KEY);
|
|
282
|
+
if (!raw) return {};
|
|
283
|
+
try {
|
|
284
|
+
const parsed = JSON.parse(raw);
|
|
285
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
286
|
+
} catch {
|
|
287
|
+
base.removeItem(DMD_ATTRIBUTES_STORAGE_KEY);
|
|
288
|
+
return {};
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function sanitizeAttributes(attributes) {
|
|
292
|
+
return Object.fromEntries(Object.entries(attributes).filter(([, value]) => !isBlankValue(value)));
|
|
293
|
+
}
|
|
294
|
+
function writeAttributes(base, attributes) {
|
|
295
|
+
const sanitized = sanitizeAttributes(attributes);
|
|
296
|
+
if (Object.keys(sanitized).length === 0) {
|
|
297
|
+
base.removeItem(DMD_ATTRIBUTES_STORAGE_KEY);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
base.setItem(DMD_ATTRIBUTES_STORAGE_KEY, JSON.stringify(sanitized));
|
|
301
|
+
}
|
|
302
|
+
function parseSessionData(value) {
|
|
303
|
+
try {
|
|
304
|
+
const parsed = JSON.parse(value);
|
|
305
|
+
const sessionData = {};
|
|
306
|
+
const sessionId = typeof parsed.sessionId === "string" && parsed.sessionId.trim() !== "" ? parsed.sessionId : void 0;
|
|
307
|
+
const timestamp = typeof parsed.timestamp === "number" ? parsed.timestamp : void 0;
|
|
308
|
+
if (sessionId !== void 0) sessionData.sessionId = sessionId;
|
|
309
|
+
if (timestamp !== void 0) sessionData.timestamp = timestamp;
|
|
310
|
+
return sessionData;
|
|
311
|
+
} catch {
|
|
312
|
+
return {};
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function getAggregateValue(attributes, key) {
|
|
316
|
+
if (key === SESSION_STORAGE_KEY) {
|
|
317
|
+
const sessionId = attributes[SESSION_ID_KEY];
|
|
318
|
+
const timestamp = attributes[SESSION_TIMESTAMP_KEY];
|
|
319
|
+
if (typeof sessionId === "string" && !isBlankValue(sessionId) && typeof timestamp === "number") {
|
|
320
|
+
return JSON.stringify({ sessionId, timestamp });
|
|
321
|
+
}
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
const value = attributes[key];
|
|
325
|
+
if (isBlankValue(value)) return null;
|
|
326
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
327
|
+
}
|
|
328
|
+
function setAggregateValue(attributes, key, value) {
|
|
329
|
+
if (key === SESSION_STORAGE_KEY) {
|
|
330
|
+
const sessionData = parseSessionData(value);
|
|
331
|
+
if (sessionData.sessionId === void 0 || sessionData.timestamp === void 0) {
|
|
332
|
+
delete attributes[SESSION_ID_KEY];
|
|
333
|
+
delete attributes[SESSION_TIMESTAMP_KEY];
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
attributes[SESSION_ID_KEY] = sessionData.sessionId;
|
|
337
|
+
attributes[SESSION_TIMESTAMP_KEY] = sessionData.timestamp;
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
attributes[key] = value;
|
|
341
|
+
}
|
|
342
|
+
function removeAggregateValue(attributes, key) {
|
|
343
|
+
if (key === SESSION_STORAGE_KEY) {
|
|
344
|
+
delete attributes[SESSION_ID_KEY];
|
|
345
|
+
delete attributes[SESSION_TIMESTAMP_KEY];
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
delete attributes[key];
|
|
349
|
+
}
|
|
350
|
+
function createDmdAttributesPersistence(base) {
|
|
351
|
+
return {
|
|
352
|
+
getItem(key) {
|
|
353
|
+
if (key === DMD_ATTRIBUTES_STORAGE_KEY) return base.getItem(key);
|
|
354
|
+
const attributes = readAttributes(base);
|
|
355
|
+
const aggregateValue = getAggregateValue(attributes, key);
|
|
356
|
+
if (aggregateValue !== null) return aggregateValue;
|
|
357
|
+
const legacyValue = base.getItem(key);
|
|
358
|
+
if (isBlankValue(legacyValue)) return null;
|
|
359
|
+
setAggregateValue(attributes, key, String(legacyValue));
|
|
360
|
+
writeAttributes(base, attributes);
|
|
361
|
+
return legacyValue;
|
|
362
|
+
},
|
|
363
|
+
setItem(key, value) {
|
|
364
|
+
if (key === DMD_ATTRIBUTES_STORAGE_KEY) return base.setItem(key, value);
|
|
365
|
+
const attributes = readAttributes(base);
|
|
366
|
+
if (isBlankValue(value)) {
|
|
367
|
+
removeAggregateValue(attributes, key);
|
|
368
|
+
writeAttributes(base, attributes);
|
|
369
|
+
base.removeItem(key);
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
setAggregateValue(attributes, key, value);
|
|
373
|
+
writeAttributes(base, attributes);
|
|
374
|
+
base.setItem(key, value);
|
|
375
|
+
return true;
|
|
376
|
+
},
|
|
377
|
+
removeItem(key) {
|
|
378
|
+
if (key === DMD_ATTRIBUTES_STORAGE_KEY) {
|
|
379
|
+
base.removeItem(key);
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
const attributes = readAttributes(base);
|
|
383
|
+
removeAggregateValue(attributes, key);
|
|
384
|
+
writeAttributes(base, attributes);
|
|
385
|
+
base.removeItem(key);
|
|
386
|
+
},
|
|
387
|
+
getHealth() {
|
|
388
|
+
return base.getHealth();
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// src/core/attribution.ts
|
|
394
|
+
var dmdUtmKeys = [
|
|
395
|
+
"utm_source",
|
|
396
|
+
"utm_medium",
|
|
397
|
+
"utm_campaign",
|
|
398
|
+
"utm_term",
|
|
399
|
+
"utm_content",
|
|
400
|
+
"utm_id"
|
|
401
|
+
];
|
|
402
|
+
var dmdCampaignKeys = ["campaign_id", "ad_id"];
|
|
403
|
+
var dmdClickIdSources = [
|
|
404
|
+
["gclid", 2],
|
|
405
|
+
["fbclid", 3],
|
|
406
|
+
["ScCid", 1],
|
|
407
|
+
["li_fat_id", 4]
|
|
408
|
+
];
|
|
409
|
+
function cleanAttributionRecord(record) {
|
|
410
|
+
const cleaned = Object.fromEntries(
|
|
411
|
+
Object.entries(record).filter(([, value]) => value !== null && value !== void 0 && value !== "")
|
|
412
|
+
);
|
|
413
|
+
return Object.keys(cleaned).length > 0 ? cleaned : void 0;
|
|
414
|
+
}
|
|
415
|
+
function objectValue(value) {
|
|
416
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
417
|
+
}
|
|
418
|
+
function mergeAttributionRecords(explicitProperties, stored) {
|
|
419
|
+
const attributionData = objectValue(explicitProperties.attributionData);
|
|
420
|
+
const utmParameter = objectValue(explicitProperties.utmParameter);
|
|
421
|
+
return {
|
|
422
|
+
...explicitProperties,
|
|
423
|
+
...stored.attributionData || attributionData ? { attributionData: { ...stored.attributionData ?? {}, ...attributionData ?? {} } } : {},
|
|
424
|
+
...stored.utmParameter || utmParameter ? { utmParameter: { ...stored.utmParameter ?? {}, ...utmParameter ?? {} } } : {}
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// src/browser/core/attribution.ts
|
|
429
|
+
var DMD_CLICK_ID_QUERY_KEY = "click_id";
|
|
430
|
+
var DMD_CLICK_ID_LEGACY_QUERY_KEY = "dmd_click_id";
|
|
431
|
+
var DMD_CLICK_ID_STORAGE_KEY = "dmd_click_id";
|
|
432
|
+
var DMD_CLICK_ID_ATTRIBUTE_KEY = "click_id";
|
|
433
|
+
function getCurrentUrl() {
|
|
434
|
+
return getBrowserWindow()?.location?.href;
|
|
435
|
+
}
|
|
436
|
+
function getCookie(name) {
|
|
437
|
+
const cookie = getBrowserWindow()?.document?.cookie;
|
|
438
|
+
if (!cookie) return void 0;
|
|
439
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
440
|
+
const match = new RegExp(`(?:^|; )${escapedName}=([^;]*)`).exec(cookie);
|
|
441
|
+
return match ? decodeURIComponent(match[1] ?? "") : void 0;
|
|
442
|
+
}
|
|
443
|
+
function getParams(url) {
|
|
444
|
+
return new URL(url, "https://placeholder.local").searchParams;
|
|
445
|
+
}
|
|
446
|
+
function setIfPresent(persistence, key, value) {
|
|
447
|
+
if (value !== null && value !== "") {
|
|
448
|
+
persistence.setItem(key, value);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
function getClickIdParam(params) {
|
|
452
|
+
return params.get(DMD_CLICK_ID_LEGACY_QUERY_KEY) || params.get(DMD_CLICK_ID_QUERY_KEY);
|
|
453
|
+
}
|
|
454
|
+
function getStoredString(persistence, key) {
|
|
455
|
+
const value = persistence.getItem(key);
|
|
456
|
+
return value === null || value === "" ? void 0 : value;
|
|
457
|
+
}
|
|
458
|
+
function getStoredNumberOrString(persistence, key) {
|
|
459
|
+
const value = getStoredString(persistence, key);
|
|
460
|
+
if (value === void 0) return void 0;
|
|
461
|
+
const parsed = Number.parseInt(value, 10);
|
|
462
|
+
return Number.isNaN(parsed) ? value : parsed;
|
|
463
|
+
}
|
|
464
|
+
function captureAttributionFromUrl(persistence, url = getCurrentUrl()) {
|
|
465
|
+
if (!url) return;
|
|
466
|
+
const params = getParams(url);
|
|
467
|
+
for (const key of dmdUtmKeys) {
|
|
468
|
+
setIfPresent(persistence, key, params.get(key));
|
|
469
|
+
}
|
|
470
|
+
for (const key of dmdCampaignKeys) {
|
|
471
|
+
setIfPresent(persistence, key, params.get(key));
|
|
472
|
+
}
|
|
473
|
+
const clickId = getClickIdParam(params);
|
|
474
|
+
setIfPresent(persistence, DMD_CLICK_ID_ATTRIBUTE_KEY, clickId);
|
|
475
|
+
setIfPresent(persistence, DMD_CLICK_ID_STORAGE_KEY, clickId);
|
|
476
|
+
for (const [param, sdkPubId] of dmdClickIdSources) {
|
|
477
|
+
const value = params.get(param);
|
|
478
|
+
if (value) {
|
|
479
|
+
persistence.setItem("unique_id", value);
|
|
480
|
+
persistence.setItem("sdk_pub_id", String(sdkPubId));
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
function getStoredAttributionData(persistence) {
|
|
485
|
+
return cleanAttributionRecord({
|
|
486
|
+
unique_id: getStoredString(persistence, "unique_id"),
|
|
487
|
+
sdk_pub_id: getStoredNumberOrString(persistence, "sdk_pub_id"),
|
|
488
|
+
fbc: getStoredString(persistence, "fbc") ?? getCookie("_fbc"),
|
|
489
|
+
fbp: getStoredString(persistence, "fbp") ?? getCookie("_fbp"),
|
|
490
|
+
campaign_id: getStoredString(persistence, "campaign_id"),
|
|
491
|
+
ad_id: getStoredString(persistence, "ad_id"),
|
|
492
|
+
click_id: getStoredString(persistence, DMD_CLICK_ID_STORAGE_KEY) ?? getStoredString(persistence, DMD_CLICK_ID_ATTRIBUTE_KEY)
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
function getStoredUtmParameter(persistence) {
|
|
496
|
+
return cleanAttributionRecord(Object.fromEntries(dmdUtmKeys.map((key) => [key, getStoredString(persistence, key)])));
|
|
497
|
+
}
|
|
498
|
+
function mergeStoredAttribution(properties, persistence) {
|
|
499
|
+
const stored = {};
|
|
500
|
+
const attributionData = getStoredAttributionData(persistence);
|
|
501
|
+
const utmParameter = getStoredUtmParameter(persistence);
|
|
502
|
+
if (attributionData !== void 0) stored.attributionData = attributionData;
|
|
503
|
+
if (utmParameter !== void 0) stored.utmParameter = utmParameter;
|
|
504
|
+
return mergeAttributionRecords(properties, stored);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// src/browser/core/autocapture.ts
|
|
508
|
+
function installAutocapture(config) {
|
|
509
|
+
const trackedPageUrls = /* @__PURE__ */ new Set();
|
|
510
|
+
const timers = /* @__PURE__ */ new Set();
|
|
511
|
+
const pageviewDelayMs = config.pageviewDelayMs ?? 500;
|
|
512
|
+
const history = config.browserWindow.history;
|
|
513
|
+
const originalPushState = history?.pushState;
|
|
514
|
+
const originalReplaceState = history?.replaceState;
|
|
515
|
+
function clearTimer(timer) {
|
|
516
|
+
timers.delete(timer);
|
|
517
|
+
clearTimeout(timer);
|
|
518
|
+
}
|
|
519
|
+
function canonicalUrl() {
|
|
520
|
+
return config.browserWindow.location.href;
|
|
521
|
+
}
|
|
522
|
+
function trackCurrentPageview() {
|
|
523
|
+
if (!config.capturePageview) return;
|
|
524
|
+
const url = canonicalUrl();
|
|
525
|
+
if (trackedPageUrls.has(url)) return;
|
|
526
|
+
trackedPageUrls.add(url);
|
|
527
|
+
config.onPageView();
|
|
528
|
+
}
|
|
529
|
+
function schedulePageview(delayMs) {
|
|
530
|
+
if (!config.capturePageview) return;
|
|
531
|
+
const timer = setTimeout(() => {
|
|
532
|
+
timers.delete(timer);
|
|
533
|
+
trackCurrentPageview();
|
|
534
|
+
}, delayMs);
|
|
535
|
+
timers.add(timer);
|
|
536
|
+
}
|
|
537
|
+
function handleRouteChange() {
|
|
538
|
+
config.onRouteChange?.();
|
|
539
|
+
trackCurrentPageview();
|
|
540
|
+
}
|
|
541
|
+
function wrapHistoryMethod(method) {
|
|
542
|
+
if (!history) return;
|
|
543
|
+
const original = history[method];
|
|
544
|
+
if (typeof original !== "function") return;
|
|
545
|
+
history[method] = function wrappedHistoryMethod(...args) {
|
|
546
|
+
const result = original.apply(this, args);
|
|
547
|
+
const timer = setTimeout(() => {
|
|
548
|
+
timers.delete(timer);
|
|
549
|
+
handleRouteChange();
|
|
550
|
+
}, 0);
|
|
551
|
+
timers.add(timer);
|
|
552
|
+
return result;
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
function handlePopOrHashChange() {
|
|
556
|
+
handleRouteChange();
|
|
557
|
+
}
|
|
558
|
+
function handlePageLeave() {
|
|
559
|
+
if (config.capturePageleave) {
|
|
560
|
+
config.onPageLeave();
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
schedulePageview(pageviewDelayMs);
|
|
564
|
+
wrapHistoryMethod("pushState");
|
|
565
|
+
wrapHistoryMethod("replaceState");
|
|
566
|
+
const canListen = typeof config.browserWindow.addEventListener === "function" && typeof config.browserWindow.removeEventListener === "function";
|
|
567
|
+
if (canListen) {
|
|
568
|
+
config.browserWindow.addEventListener("popstate", handlePopOrHashChange);
|
|
569
|
+
config.browserWindow.addEventListener("hashchange", handlePopOrHashChange);
|
|
570
|
+
config.browserWindow.addEventListener("beforeunload", handlePageLeave);
|
|
571
|
+
}
|
|
572
|
+
return {
|
|
573
|
+
cleanup() {
|
|
574
|
+
for (const timer of Array.from(timers)) {
|
|
575
|
+
clearTimer(timer);
|
|
576
|
+
}
|
|
577
|
+
if (history && originalPushState) history.pushState = originalPushState;
|
|
578
|
+
if (history && originalReplaceState) history.replaceState = originalReplaceState;
|
|
579
|
+
if (canListen) {
|
|
580
|
+
config.browserWindow.removeEventListener("popstate", handlePopOrHashChange);
|
|
581
|
+
config.browserWindow.removeEventListener("hashchange", handlePopOrHashChange);
|
|
582
|
+
config.browserWindow.removeEventListener("beforeunload", handlePageLeave);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// src/core/payload-size.ts
|
|
589
|
+
var preserveStringKeys = /* @__PURE__ */ new Set([
|
|
590
|
+
"requestId",
|
|
591
|
+
"eventType",
|
|
592
|
+
"requestFrom",
|
|
593
|
+
"clientId",
|
|
594
|
+
"workspaceId",
|
|
595
|
+
"anonymousId",
|
|
596
|
+
"sessionId",
|
|
597
|
+
"token"
|
|
598
|
+
]);
|
|
599
|
+
function payloadByteLength(payload) {
|
|
600
|
+
const serialized = JSON.stringify(payload);
|
|
601
|
+
if (typeof TextEncoder !== "undefined") {
|
|
602
|
+
return new TextEncoder().encode(serialized).length;
|
|
603
|
+
}
|
|
604
|
+
return serialized.length;
|
|
605
|
+
}
|
|
606
|
+
function clonePayload(payload) {
|
|
607
|
+
try {
|
|
608
|
+
return JSON.parse(JSON.stringify(payload));
|
|
609
|
+
} catch {
|
|
610
|
+
return void 0;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
function truncateValue(value, truncateStringLength, key) {
|
|
614
|
+
if (typeof value === "string") {
|
|
615
|
+
if (key && preserveStringKeys.has(key)) return value;
|
|
616
|
+
if (value.length <= truncateStringLength) return value;
|
|
617
|
+
return `${value.slice(0, truncateStringLength)}...[TRUNCATED]`;
|
|
618
|
+
}
|
|
619
|
+
if (Array.isArray(value)) {
|
|
620
|
+
return value.map((item) => truncateValue(item, truncateStringLength));
|
|
621
|
+
}
|
|
622
|
+
if (value && typeof value === "object") {
|
|
623
|
+
return Object.fromEntries(
|
|
624
|
+
Object.entries(value).map(([childKey, childValue]) => [
|
|
625
|
+
childKey,
|
|
626
|
+
truncateValue(childValue, truncateStringLength, childKey)
|
|
627
|
+
])
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
return value;
|
|
631
|
+
}
|
|
632
|
+
function markPayloadTruncated(payload) {
|
|
633
|
+
if (payload.metaData && typeof payload.metaData === "object" && !Array.isArray(payload.metaData)) {
|
|
634
|
+
return {
|
|
635
|
+
...payload,
|
|
636
|
+
metaData: {
|
|
637
|
+
...payload.metaData,
|
|
638
|
+
payloadTruncated: true
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
return {
|
|
643
|
+
...payload,
|
|
644
|
+
payloadTruncated: true
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
function truncatePayload(payload, truncateStringLength) {
|
|
648
|
+
const cloned = clonePayload(payload);
|
|
649
|
+
if (!cloned) return void 0;
|
|
650
|
+
return markPayloadTruncated(truncateValue(cloned, truncateStringLength));
|
|
651
|
+
}
|
|
652
|
+
function getPayloadMessageId(payload) {
|
|
653
|
+
const value = payload.metaData?.requestId ?? payload.messageId;
|
|
654
|
+
return value === void 0 ? void 0 : String(value);
|
|
655
|
+
}
|
|
656
|
+
function preparePayloadForSizePolicy(payload, options = {}) {
|
|
657
|
+
const maxPayloadBytes = options.maxPayloadBytes ?? 64e3;
|
|
658
|
+
const payloadSizePolicy = options.payloadSizePolicy ?? "drop";
|
|
659
|
+
const payloadTruncateStringLength = options.payloadTruncateStringLength ?? 1024;
|
|
660
|
+
if (payloadByteLength(payload) <= maxPayloadBytes) {
|
|
661
|
+
return { ok: true, payload, truncated: false };
|
|
662
|
+
}
|
|
663
|
+
if (payloadSizePolicy === "truncate") {
|
|
664
|
+
const truncatedPayload = truncatePayload(payload, payloadTruncateStringLength);
|
|
665
|
+
if (truncatedPayload && payloadByteLength(truncatedPayload) <= maxPayloadBytes) {
|
|
666
|
+
return { ok: true, payload: truncatedPayload, truncated: true };
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
const messageId = getPayloadMessageId(payload);
|
|
670
|
+
return messageId === void 0 ? { ok: false, reason: "payload_too_large" } : { ok: false, reason: "payload_too_large", messageId };
|
|
671
|
+
}
|
|
672
|
+
|
|
116
673
|
// src/browser/core/delivery.ts
|
|
117
674
|
function createId(prefix) {
|
|
118
675
|
return `${prefix}_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
|
|
@@ -144,7 +701,6 @@ function createDeliveryManager(config) {
|
|
|
144
701
|
const lockTtlMs = config.lockTtlMs ?? 5e3;
|
|
145
702
|
const tabId = config.tabId ?? createId("tab");
|
|
146
703
|
const batchSize = config.batchSize ?? 25;
|
|
147
|
-
const maxPayloadBytes = config.maxPayloadBytes ?? 64e3;
|
|
148
704
|
function recordDrop(event) {
|
|
149
705
|
diagnostics.dropped.push(event);
|
|
150
706
|
config.onDrop?.(event);
|
|
@@ -153,12 +709,22 @@ function createDeliveryManager(config) {
|
|
|
153
709
|
diagnostics.lastError = error.message;
|
|
154
710
|
config.onError?.(error);
|
|
155
711
|
}
|
|
156
|
-
function
|
|
157
|
-
const
|
|
158
|
-
if (
|
|
159
|
-
|
|
712
|
+
function preparePayloadForSend(payload) {
|
|
713
|
+
const sizePolicyOptions = {};
|
|
714
|
+
if (config.maxPayloadBytes !== void 0) sizePolicyOptions.maxPayloadBytes = config.maxPayloadBytes;
|
|
715
|
+
if (config.payloadSizePolicy !== void 0) sizePolicyOptions.payloadSizePolicy = config.payloadSizePolicy;
|
|
716
|
+
if (config.payloadTruncateStringLength !== void 0) {
|
|
717
|
+
sizePolicyOptions.payloadTruncateStringLength = config.payloadTruncateStringLength;
|
|
160
718
|
}
|
|
161
|
-
|
|
719
|
+
const prepared = preparePayloadForSizePolicy(payload, sizePolicyOptions);
|
|
720
|
+
if (prepared.ok) return prepared.payload;
|
|
721
|
+
const diagnostic = {
|
|
722
|
+
reason: prepared.reason,
|
|
723
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
724
|
+
};
|
|
725
|
+
if (prepared.messageId !== void 0) diagnostic.messageId = prepared.messageId;
|
|
726
|
+
recordDrop(diagnostic);
|
|
727
|
+
return void 0;
|
|
162
728
|
}
|
|
163
729
|
function recordStorageUnavailable() {
|
|
164
730
|
recordDrop({
|
|
@@ -248,7 +814,19 @@ function createDeliveryManager(config) {
|
|
|
248
814
|
idempotencyKey: String(payload.idempotencyKey ?? createIdempotencyKey(payload, messageId))
|
|
249
815
|
};
|
|
250
816
|
}
|
|
817
|
+
function tryBeacon(body) {
|
|
818
|
+
if (!config.useBeacon) return false;
|
|
819
|
+
const sendBeacon = globalThis.navigator?.sendBeacon;
|
|
820
|
+
if (typeof sendBeacon !== "function") return false;
|
|
821
|
+
try {
|
|
822
|
+
const blob = new Blob([JSON.stringify(body)], { type: "application/json" });
|
|
823
|
+
return sendBeacon.call(globalThis.navigator, config.endpoint, blob);
|
|
824
|
+
} catch {
|
|
825
|
+
return false;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
251
828
|
async function deliver(body) {
|
|
829
|
+
if (tryBeacon(body)) return;
|
|
252
830
|
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
253
831
|
if (typeof fetchImpl !== "function") {
|
|
254
832
|
throw new Error("fetch_unavailable");
|
|
@@ -265,26 +843,22 @@ function createDeliveryManager(config) {
|
|
|
265
843
|
return {
|
|
266
844
|
async send(payload) {
|
|
267
845
|
const body = withEnvelope(payload);
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
messageId: String(body.metaData?.requestId ?? body.messageId),
|
|
271
|
-
reason: "payload_too_large",
|
|
272
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
273
|
-
});
|
|
846
|
+
const preparedBody = preparePayloadForSend(body);
|
|
847
|
+
if (!preparedBody) {
|
|
274
848
|
return;
|
|
275
849
|
}
|
|
276
850
|
diagnostics.inFlight += 1;
|
|
277
851
|
try {
|
|
278
|
-
await deliver(
|
|
852
|
+
await deliver(preparedBody);
|
|
279
853
|
} catch (error) {
|
|
280
854
|
const deliveryError = error instanceof Error ? error : new Error(String(error));
|
|
281
855
|
recordError(deliveryError);
|
|
282
856
|
enqueue({
|
|
283
|
-
messageId: String(body
|
|
857
|
+
messageId: String(getPayloadMessageId(body)),
|
|
284
858
|
savedAt: Date.now(),
|
|
285
859
|
attempts: 1,
|
|
286
860
|
lastError: deliveryError.message,
|
|
287
|
-
payload:
|
|
861
|
+
payload: preparedBody
|
|
288
862
|
});
|
|
289
863
|
} finally {
|
|
290
864
|
diagnostics.inFlight -= 1;
|
|
@@ -397,60 +971,286 @@ function createDeliveryManager(config) {
|
|
|
397
971
|
};
|
|
398
972
|
}
|
|
399
973
|
|
|
400
|
-
// src/browser/core/
|
|
401
|
-
var
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
"name",
|
|
411
|
-
"token",
|
|
412
|
-
"secret",
|
|
413
|
-
"password",
|
|
414
|
-
"session",
|
|
415
|
-
"cookie"
|
|
416
|
-
]);
|
|
417
|
-
function sanitizeValue(value, allow) {
|
|
418
|
-
if (Array.isArray(value)) {
|
|
419
|
-
return value.map((item) => sanitizeValue(item, allow));
|
|
974
|
+
// src/browser/core/identity.ts
|
|
975
|
+
var ANONYMOUS_ID_STORAGE_KEY = "dmd_anonymous_id";
|
|
976
|
+
var LEGACY_ANONYMOUS_ID_STORAGE_KEY = "anonymousId";
|
|
977
|
+
function getUrlParam(name) {
|
|
978
|
+
const href = getBrowserWindow()?.location?.href;
|
|
979
|
+
if (!href) return null;
|
|
980
|
+
try {
|
|
981
|
+
return new URL(href).searchParams.get(name);
|
|
982
|
+
} catch {
|
|
983
|
+
return null;
|
|
420
984
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
985
|
+
}
|
|
986
|
+
function resolveAnonymousId(persistence) {
|
|
987
|
+
const urlAnonymousId = getUrlParam("aid");
|
|
988
|
+
if (isUuid(urlAnonymousId)) {
|
|
989
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, urlAnonymousId);
|
|
990
|
+
return urlAnonymousId;
|
|
991
|
+
}
|
|
992
|
+
const storedAnonymousId = persistence.getItem(ANONYMOUS_ID_STORAGE_KEY);
|
|
993
|
+
if (isUuid(storedAnonymousId)) {
|
|
994
|
+
return storedAnonymousId;
|
|
995
|
+
}
|
|
996
|
+
const legacyAnonymousId = persistence.getItem(LEGACY_ANONYMOUS_ID_STORAGE_KEY);
|
|
997
|
+
if (isUuid(legacyAnonymousId)) {
|
|
998
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, legacyAnonymousId);
|
|
999
|
+
return legacyAnonymousId;
|
|
1000
|
+
}
|
|
1001
|
+
const anonymousId = createUuid();
|
|
1002
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, anonymousId);
|
|
1003
|
+
return anonymousId;
|
|
1004
|
+
}
|
|
1005
|
+
function resetAnonymousId(persistence) {
|
|
1006
|
+
const anonymousId = createUuid();
|
|
1007
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, anonymousId);
|
|
1008
|
+
return anonymousId;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// src/browser/core/page-context.ts
|
|
1012
|
+
function redactSearch(search) {
|
|
1013
|
+
const redacted = redactUrl(search);
|
|
1014
|
+
return redacted.startsWith("/?") ? redacted.slice(1) : redacted;
|
|
1015
|
+
}
|
|
1016
|
+
function getBrowserPageContext() {
|
|
1017
|
+
const browserWindow = getBrowserWindow();
|
|
1018
|
+
const documentRef = browserWindow?.document ?? globalThis.document;
|
|
1019
|
+
const location = browserWindow?.location;
|
|
1020
|
+
const page2 = {};
|
|
1021
|
+
if (location?.href) page2.url = location.href;
|
|
1022
|
+
if (location?.pathname) page2.path = location.pathname;
|
|
1023
|
+
if (location?.search) page2.search = redactSearch(location.search);
|
|
1024
|
+
if (documentRef?.title) page2.title = documentRef.title;
|
|
1025
|
+
if (documentRef?.referrer) page2.referrer = redactUrl(documentRef.referrer);
|
|
1026
|
+
return page2;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
// src/browser/core/persistence.ts
|
|
1030
|
+
function createPersistenceHealth(requested) {
|
|
1031
|
+
return {
|
|
1032
|
+
requested,
|
|
1033
|
+
cookieFallbackUsed: false,
|
|
1034
|
+
memoryFallbackUsed: requested === "memory",
|
|
1035
|
+
failures: []
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
function recordFailure(health, backend, operation, error) {
|
|
1039
|
+
health.failures.push({
|
|
1040
|
+
backend,
|
|
1041
|
+
operation,
|
|
1042
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1043
|
+
});
|
|
1044
|
+
if (health.failures.length > 25) {
|
|
1045
|
+
health.failures.shift();
|
|
425
1046
|
}
|
|
426
|
-
return value;
|
|
427
1047
|
}
|
|
428
|
-
function
|
|
429
|
-
const
|
|
430
|
-
return
|
|
1048
|
+
function createMemoryPersistence(health = createPersistenceHealth("memory")) {
|
|
1049
|
+
const memory = {};
|
|
1050
|
+
return {
|
|
1051
|
+
getItem(key) {
|
|
1052
|
+
return Object.prototype.hasOwnProperty.call(memory, key) ? memory[key] ?? null : null;
|
|
1053
|
+
},
|
|
1054
|
+
setItem(key, value) {
|
|
1055
|
+
memory[key] = value;
|
|
1056
|
+
return true;
|
|
1057
|
+
},
|
|
1058
|
+
removeItem(key) {
|
|
1059
|
+
delete memory[key];
|
|
1060
|
+
},
|
|
1061
|
+
getHealth() {
|
|
1062
|
+
return {
|
|
1063
|
+
...health,
|
|
1064
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
function getCookie2(name) {
|
|
1070
|
+
const browserWindow = getBrowserWindow();
|
|
1071
|
+
const cookie = browserWindow?.document?.cookie;
|
|
1072
|
+
if (!cookie) return null;
|
|
1073
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1074
|
+
const match = new RegExp(`(?:^|; )${escapedName}=([^;]*)`).exec(cookie);
|
|
1075
|
+
return match ? decodeURIComponent(match[1] ?? "") : null;
|
|
1076
|
+
}
|
|
1077
|
+
function setCookie(name, value) {
|
|
1078
|
+
const browserWindow = getBrowserWindow();
|
|
1079
|
+
if (!browserWindow?.document) return false;
|
|
1080
|
+
try {
|
|
1081
|
+
const expires = new Date(Date.now() + 365 * 24 * 60 * 60 * 1e3).toUTCString();
|
|
1082
|
+
const secure = browserWindow.location?.protocol === "https:" ? "; Secure" : "";
|
|
1083
|
+
browserWindow.document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/${secure}; SameSite=Lax`;
|
|
1084
|
+
return true;
|
|
1085
|
+
} catch {
|
|
1086
|
+
return false;
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
function removeCookie(name) {
|
|
1090
|
+
const browserWindow = getBrowserWindow();
|
|
1091
|
+
if (!browserWindow?.document) return;
|
|
1092
|
+
browserWindow.document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
|
1093
|
+
}
|
|
1094
|
+
function getLocalStorage() {
|
|
1095
|
+
const browserWindow = getBrowserWindow();
|
|
1096
|
+
try {
|
|
1097
|
+
return browserWindow?.localStorage;
|
|
1098
|
+
} catch {
|
|
1099
|
+
return void 0;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
function getSessionStorage() {
|
|
1103
|
+
const browserWindow = getBrowserWindow();
|
|
1104
|
+
try {
|
|
1105
|
+
return browserWindow?.sessionStorage;
|
|
1106
|
+
} catch {
|
|
1107
|
+
return void 0;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
function createBrowserPersistence(mode = "localStorage+cookie") {
|
|
1111
|
+
const health = createPersistenceHealth(mode);
|
|
1112
|
+
const memory = createMemoryPersistence(health);
|
|
1113
|
+
if (mode === "none") {
|
|
1114
|
+
return {
|
|
1115
|
+
getItem() {
|
|
1116
|
+
return null;
|
|
1117
|
+
},
|
|
1118
|
+
setItem() {
|
|
1119
|
+
return false;
|
|
1120
|
+
},
|
|
1121
|
+
removeItem() {
|
|
1122
|
+
},
|
|
1123
|
+
getHealth() {
|
|
1124
|
+
return {
|
|
1125
|
+
...health,
|
|
1126
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
if (mode === "memory") return memory;
|
|
1132
|
+
const primary = mode === "sessionStorage" ? getSessionStorage() : getLocalStorage();
|
|
1133
|
+
const useCookie = mode === "cookie" || mode === "localStorage+cookie" || !primary;
|
|
1134
|
+
return {
|
|
1135
|
+
getItem(key) {
|
|
1136
|
+
try {
|
|
1137
|
+
const stored = primary?.getItem(key);
|
|
1138
|
+
if (stored) return stored;
|
|
1139
|
+
} catch (error) {
|
|
1140
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "get", error);
|
|
1141
|
+
}
|
|
1142
|
+
if (useCookie) {
|
|
1143
|
+
const cookie = getCookie2(key);
|
|
1144
|
+
if (cookie) {
|
|
1145
|
+
health.cookieFallbackUsed = true;
|
|
1146
|
+
return cookie;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
const value = memory.getItem(key);
|
|
1150
|
+
if (value !== null) health.memoryFallbackUsed = true;
|
|
1151
|
+
return value;
|
|
1152
|
+
},
|
|
1153
|
+
setItem(key, value) {
|
|
1154
|
+
let wrote = false;
|
|
1155
|
+
try {
|
|
1156
|
+
primary?.setItem(key, value);
|
|
1157
|
+
wrote = primary !== void 0;
|
|
1158
|
+
} catch (error) {
|
|
1159
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "set", error);
|
|
1160
|
+
wrote = false;
|
|
1161
|
+
}
|
|
1162
|
+
if (useCookie) {
|
|
1163
|
+
const cookieWrote = setCookie(key, value);
|
|
1164
|
+
if (cookieWrote) health.cookieFallbackUsed = true;
|
|
1165
|
+
wrote = cookieWrote || wrote;
|
|
1166
|
+
}
|
|
1167
|
+
if (!wrote) {
|
|
1168
|
+
health.memoryFallbackUsed = true;
|
|
1169
|
+
return memory.setItem(key, value);
|
|
1170
|
+
}
|
|
1171
|
+
if (mode === "localStorage+cookie") {
|
|
1172
|
+
memory.setItem(key, value);
|
|
1173
|
+
}
|
|
1174
|
+
return true;
|
|
1175
|
+
},
|
|
1176
|
+
removeItem(key) {
|
|
1177
|
+
try {
|
|
1178
|
+
primary?.removeItem(key);
|
|
1179
|
+
} catch (error) {
|
|
1180
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "remove", error);
|
|
1181
|
+
}
|
|
1182
|
+
if (useCookie) removeCookie(key);
|
|
1183
|
+
memory.removeItem(key);
|
|
1184
|
+
},
|
|
1185
|
+
getHealth() {
|
|
1186
|
+
return {
|
|
1187
|
+
...health,
|
|
1188
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
431
1192
|
}
|
|
432
1193
|
|
|
433
|
-
// src/browser/core/
|
|
434
|
-
var
|
|
435
|
-
function
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
1194
|
+
// src/browser/core/session.ts
|
|
1195
|
+
var SESSION_STORAGE_KEY2 = "sessionData";
|
|
1196
|
+
function getUrlParam2(name) {
|
|
1197
|
+
const href = getBrowserWindow()?.location?.href;
|
|
1198
|
+
if (!href) return null;
|
|
1199
|
+
try {
|
|
1200
|
+
return new URL(href).searchParams.get(name);
|
|
1201
|
+
} catch {
|
|
1202
|
+
return null;
|
|
441
1203
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
1204
|
+
}
|
|
1205
|
+
function readStoredSession(persistence) {
|
|
1206
|
+
const rawSession = persistence.getItem(SESSION_STORAGE_KEY2);
|
|
1207
|
+
if (!rawSession) return void 0;
|
|
1208
|
+
try {
|
|
1209
|
+
const parsed = JSON.parse(rawSession);
|
|
1210
|
+
if (isUuid(parsed.sessionId) && typeof parsed.timestamp === "number") {
|
|
1211
|
+
return {
|
|
1212
|
+
sessionId: parsed.sessionId,
|
|
1213
|
+
timestamp: parsed.timestamp
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
} catch {
|
|
1217
|
+
persistence.removeItem(SESSION_STORAGE_KEY2);
|
|
446
1218
|
}
|
|
447
|
-
return
|
|
1219
|
+
return void 0;
|
|
1220
|
+
}
|
|
1221
|
+
function writeStoredSession(persistence, sessionId, timestamp) {
|
|
1222
|
+
persistence.setItem(SESSION_STORAGE_KEY2, JSON.stringify({ sessionId, timestamp }));
|
|
1223
|
+
}
|
|
1224
|
+
function createSessionManager(persistence, idleTimeoutSeconds = 30 * 60) {
|
|
1225
|
+
function resolveSessionId() {
|
|
1226
|
+
const now = Date.now();
|
|
1227
|
+
const urlSessionId = getUrlParam2("sid") ?? getUrlParam2("session_id");
|
|
1228
|
+
if (isUuid(urlSessionId)) {
|
|
1229
|
+
writeStoredSession(persistence, urlSessionId, now);
|
|
1230
|
+
return urlSessionId;
|
|
1231
|
+
}
|
|
1232
|
+
const storedSession = readStoredSession(persistence);
|
|
1233
|
+
if (storedSession && now - storedSession.timestamp <= idleTimeoutSeconds * 1e3) {
|
|
1234
|
+
writeStoredSession(persistence, storedSession.sessionId, now);
|
|
1235
|
+
return storedSession.sessionId;
|
|
1236
|
+
}
|
|
1237
|
+
const sessionId = createUuid();
|
|
1238
|
+
writeStoredSession(persistence, sessionId, now);
|
|
1239
|
+
return sessionId;
|
|
1240
|
+
}
|
|
1241
|
+
return {
|
|
1242
|
+
getSessionId() {
|
|
1243
|
+
return resolveSessionId();
|
|
1244
|
+
},
|
|
1245
|
+
reset() {
|
|
1246
|
+
const sessionId = createUuid();
|
|
1247
|
+
writeStoredSession(persistence, sessionId, Date.now());
|
|
1248
|
+
return sessionId;
|
|
1249
|
+
}
|
|
1250
|
+
};
|
|
448
1251
|
}
|
|
449
1252
|
|
|
450
1253
|
// src/browser/core/DriveMetaDataSDK.ts
|
|
451
|
-
function createId2(prefix) {
|
|
452
|
-
return `${prefix}_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
|
|
453
|
-
}
|
|
454
1254
|
function endpointFromConfig(config) {
|
|
455
1255
|
const host = config.apiHost ?? "https://sdk.drivemetadata.com/v2";
|
|
456
1256
|
return `${host.replace(/\/$/, "")}/data-collector`;
|
|
@@ -461,14 +1261,6 @@ function requireConfigString(value, field) {
|
|
|
461
1261
|
}
|
|
462
1262
|
return value;
|
|
463
1263
|
}
|
|
464
|
-
function getBrowserStorage() {
|
|
465
|
-
const browserWindow = getBrowserWindow();
|
|
466
|
-
try {
|
|
467
|
-
return browserWindow?.localStorage;
|
|
468
|
-
} catch {
|
|
469
|
-
return void 0;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
1264
|
var DriveMetaDataSDK = class {
|
|
473
1265
|
constructor(config) {
|
|
474
1266
|
this.initialized = true;
|
|
@@ -481,30 +1273,36 @@ var DriveMetaDataSDK = class {
|
|
|
481
1273
|
requireConfigString(config.writeKey || config.token, "writeKey or token");
|
|
482
1274
|
this.config = config;
|
|
483
1275
|
this.endpoint = endpointFromConfig(config);
|
|
484
|
-
const
|
|
1276
|
+
const storagePersistence = createBrowserPersistence(config.persistence);
|
|
1277
|
+
this.persistence = createDmdAttributesPersistence(storagePersistence);
|
|
1278
|
+
this.session = createSessionManager(this.persistence, config.sessionIdleTimeoutSeconds);
|
|
485
1279
|
const deliveryConfig = {
|
|
486
|
-
endpoint: this.endpoint
|
|
1280
|
+
endpoint: this.endpoint,
|
|
1281
|
+
storage: storagePersistence
|
|
487
1282
|
};
|
|
488
1283
|
if (config.delivery?.maxQueueSize !== void 0) deliveryConfig.maxQueueSize = config.delivery.maxQueueSize;
|
|
489
1284
|
if (config.delivery?.queueTtlMs !== void 0) deliveryConfig.queueTtlMs = config.delivery.queueTtlMs;
|
|
490
1285
|
if (config.delivery?.retryDelayMs !== void 0) deliveryConfig.retryDelayMs = config.delivery.retryDelayMs;
|
|
491
1286
|
if (config.delivery?.maxRetryDelayMs !== void 0) deliveryConfig.maxRetryDelayMs = config.delivery.maxRetryDelayMs;
|
|
492
1287
|
if (config.delivery?.maxPayloadBytes !== void 0) deliveryConfig.maxPayloadBytes = config.delivery.maxPayloadBytes;
|
|
1288
|
+
if (config.delivery?.payloadSizePolicy !== void 0) deliveryConfig.payloadSizePolicy = config.delivery.payloadSizePolicy;
|
|
1289
|
+
if (config.delivery?.payloadTruncateStringLength !== void 0) {
|
|
1290
|
+
deliveryConfig.payloadTruncateStringLength = config.delivery.payloadTruncateStringLength;
|
|
1291
|
+
}
|
|
1292
|
+
if (config.delivery?.useBeacon !== void 0) deliveryConfig.useBeacon = config.delivery.useBeacon;
|
|
493
1293
|
if (config.delivery?.batchSize !== void 0) deliveryConfig.batchSize = config.delivery.batchSize;
|
|
494
1294
|
if (config.onDrop !== void 0) deliveryConfig.onDrop = config.onDrop;
|
|
495
1295
|
if (config.onError !== void 0) deliveryConfig.onError = config.onError;
|
|
496
|
-
this.delivery = createDeliveryManager(
|
|
497
|
-
...deliveryConfig,
|
|
498
|
-
storage
|
|
499
|
-
} : deliveryConfig);
|
|
1296
|
+
this.delivery = createDeliveryManager(deliveryConfig);
|
|
500
1297
|
this.initialRetryDelayMs = config.delivery?.retryDelayMs ?? 1e3;
|
|
501
1298
|
this.retryDelayMs = this.initialRetryDelayMs;
|
|
502
1299
|
this.maxRetryDelayMs = config.delivery?.maxRetryDelayMs ?? 3e4;
|
|
503
1300
|
this.writeKey = config.writeKey || config.token || "";
|
|
504
|
-
this.identity = { anonymousId:
|
|
505
|
-
this.
|
|
1301
|
+
this.identity = { anonymousId: resolveAnonymousId(this.persistence) };
|
|
1302
|
+
captureAttributionFromUrl(this.persistence);
|
|
506
1303
|
this.consentState = normalizeConsent(config.gdprConsent ?? config.consent);
|
|
507
1304
|
this.gdprConsent = this.consentState.analytics;
|
|
1305
|
+
this.installAutocapture();
|
|
508
1306
|
if (!config.delivery?.disableLifecycleFlush) {
|
|
509
1307
|
this.installLifecycleFlush();
|
|
510
1308
|
}
|
|
@@ -544,7 +1342,8 @@ var DriveMetaDataSDK = class {
|
|
|
544
1342
|
}
|
|
545
1343
|
}
|
|
546
1344
|
reset() {
|
|
547
|
-
this.identity = { anonymousId:
|
|
1345
|
+
this.identity = { anonymousId: resetAnonymousId(this.persistence) };
|
|
1346
|
+
this.session.reset();
|
|
548
1347
|
this.queue = [];
|
|
549
1348
|
this.offline = false;
|
|
550
1349
|
if (this.retryTimer !== void 0) {
|
|
@@ -553,8 +1352,20 @@ var DriveMetaDataSDK = class {
|
|
|
553
1352
|
}
|
|
554
1353
|
this.lifecycleCleanup?.();
|
|
555
1354
|
this.lifecycleCleanup = void 0;
|
|
1355
|
+
this.autocaptureCleanup?.();
|
|
1356
|
+
this.autocaptureCleanup = void 0;
|
|
556
1357
|
this.delivery.clearQueue("manual_clear");
|
|
557
1358
|
}
|
|
1359
|
+
disposeForTests() {
|
|
1360
|
+
if (this.retryTimer !== void 0) {
|
|
1361
|
+
clearTimeout(this.retryTimer);
|
|
1362
|
+
this.retryTimer = void 0;
|
|
1363
|
+
}
|
|
1364
|
+
this.lifecycleCleanup?.();
|
|
1365
|
+
this.lifecycleCleanup = void 0;
|
|
1366
|
+
this.autocaptureCleanup?.();
|
|
1367
|
+
this.autocaptureCleanup = void 0;
|
|
1368
|
+
}
|
|
558
1369
|
setConsent(consent) {
|
|
559
1370
|
this.consentState = typeof consent === "object" ? mergeConsent(this.consentState, consent) : normalizeConsent(consent);
|
|
560
1371
|
this.gdprConsent = this.consentState.analytics;
|
|
@@ -569,6 +1380,7 @@ var DriveMetaDataSDK = class {
|
|
|
569
1380
|
initialized: this.initialized,
|
|
570
1381
|
consent: this.gdprConsent,
|
|
571
1382
|
consentPurposes: this.consentState,
|
|
1383
|
+
persistence: this.persistence.getHealth(),
|
|
572
1384
|
queueSize: deliveryDiagnostics.queued,
|
|
573
1385
|
offline: this.offline || deliveryDiagnostics.queued > 0,
|
|
574
1386
|
droppedEvents: this.droppedEvents + deliveryDiagnostics.dropped.length,
|
|
@@ -583,7 +1395,9 @@ var DriveMetaDataSDK = class {
|
|
|
583
1395
|
void this.delivery.send(payload).then(() => {
|
|
584
1396
|
const diagnostics = this.delivery.getDiagnostics();
|
|
585
1397
|
this.offline = diagnostics.queued > 0;
|
|
586
|
-
|
|
1398
|
+
if (diagnostics.lastError !== void 0) {
|
|
1399
|
+
this.lastError = diagnostics.lastError;
|
|
1400
|
+
}
|
|
587
1401
|
if (diagnostics.queued > 0) {
|
|
588
1402
|
this.scheduleRetryFlush();
|
|
589
1403
|
}
|
|
@@ -615,6 +1429,28 @@ var DriveMetaDataSDK = class {
|
|
|
615
1429
|
}
|
|
616
1430
|
};
|
|
617
1431
|
}
|
|
1432
|
+
installAutocapture() {
|
|
1433
|
+
const browserWindow = getBrowserWindow();
|
|
1434
|
+
if (!browserWindow) return;
|
|
1435
|
+
if (this.config.autocapture === false) return;
|
|
1436
|
+
const capturePageview = this.config.capturePageview !== false;
|
|
1437
|
+
const capturePageleave = this.config.capturePageleave !== false;
|
|
1438
|
+
const controller = installAutocapture({
|
|
1439
|
+
browserWindow,
|
|
1440
|
+
capturePageview,
|
|
1441
|
+
capturePageleave,
|
|
1442
|
+
onPageView: () => {
|
|
1443
|
+
this.page();
|
|
1444
|
+
},
|
|
1445
|
+
onPageLeave: () => {
|
|
1446
|
+
this.trackEvent("page_leave", { url: browserWindow.location.href });
|
|
1447
|
+
},
|
|
1448
|
+
onRouteChange: () => {
|
|
1449
|
+
captureAttributionFromUrl(this.persistence);
|
|
1450
|
+
}
|
|
1451
|
+
});
|
|
1452
|
+
this.autocaptureCleanup = controller.cleanup;
|
|
1453
|
+
}
|
|
618
1454
|
scheduleRetryFlush() {
|
|
619
1455
|
if (this.retryTimer !== void 0) return;
|
|
620
1456
|
const delay = Math.min(this.retryDelayMs, this.maxRetryDelayMs);
|
|
@@ -640,7 +1476,7 @@ var DriveMetaDataSDK = class {
|
|
|
640
1476
|
type,
|
|
641
1477
|
event,
|
|
642
1478
|
properties: sanitizeProperties(properties),
|
|
643
|
-
messageId: options.messageId
|
|
1479
|
+
messageId: ensureUuid(options.messageId),
|
|
644
1480
|
timestamp: options.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
645
1481
|
context: options.context ?? {},
|
|
646
1482
|
anonymousId: this.identity.anonymousId,
|
|
@@ -649,7 +1485,7 @@ var DriveMetaDataSDK = class {
|
|
|
649
1485
|
appId: this.config.appId,
|
|
650
1486
|
writeKey: this.writeKey,
|
|
651
1487
|
consent: this.consentState,
|
|
652
|
-
sessionId: this.
|
|
1488
|
+
sessionId: this.session.getSessionId()
|
|
653
1489
|
};
|
|
654
1490
|
if (this.identity.userId !== void 0) prepared.userId = this.identity.userId;
|
|
655
1491
|
if (this.identity.groupId !== void 0) prepared.groupId = this.identity.groupId;
|
|
@@ -673,10 +1509,21 @@ var DriveMetaDataSDK = class {
|
|
|
673
1509
|
if (!validation.ok) {
|
|
674
1510
|
this.lastError = `DMD SDK schema warning: ${validation.errors.join(", ")}`;
|
|
675
1511
|
}
|
|
676
|
-
this.
|
|
1512
|
+
const collectorPayload = this.toCollectorPayload(prepared);
|
|
1513
|
+
const backendValidation = validateBackendCollectorPayload(collectorPayload);
|
|
1514
|
+
if (!backendValidation.ok && this.config.schemaValidation === "strict") {
|
|
1515
|
+
this.lastError = `DMD SDK backend schema warning: ${backendValidation.errors.join(", ")}`;
|
|
1516
|
+
this.recordDrop(type, "invalid_payload", event);
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
if (!backendValidation.ok) {
|
|
1520
|
+
this.lastError = `DMD SDK backend schema warning: ${backendValidation.errors.join(", ")}`;
|
|
1521
|
+
}
|
|
1522
|
+
this.sendEvent(collectorPayload);
|
|
677
1523
|
}
|
|
678
1524
|
toCollectorPayload(prepared) {
|
|
679
1525
|
const browserWindow = getBrowserWindow();
|
|
1526
|
+
const pageContext = getBrowserPageContext();
|
|
680
1527
|
return createBackendCollectorPayload({
|
|
681
1528
|
requestId: prepared.messageId,
|
|
682
1529
|
timestamp: prepared.timestamp,
|
|
@@ -688,15 +1535,19 @@ var DriveMetaDataSDK = class {
|
|
|
688
1535
|
sessionId: prepared.sessionId,
|
|
689
1536
|
ua: browserWindow?.navigator?.userAgent,
|
|
690
1537
|
appId: prepared.appId,
|
|
691
|
-
pageUrl: browserWindow?.location?.href,
|
|
692
|
-
eventData: {
|
|
1538
|
+
pageUrl: pageContext.url ?? browserWindow?.location?.href,
|
|
1539
|
+
eventData: mergeStoredAttribution({
|
|
693
1540
|
...prepared.properties,
|
|
1541
|
+
page: {
|
|
1542
|
+
...pageContext,
|
|
1543
|
+
...prepared.properties.page && typeof prepared.properties.page === "object" ? prepared.properties.page : {}
|
|
1544
|
+
},
|
|
694
1545
|
anonymousId: prepared.anonymousId,
|
|
695
1546
|
sessionId: prepared.sessionId,
|
|
696
1547
|
timestamp: prepared.timestamp,
|
|
697
1548
|
requestSentAt: prepared.timestamp,
|
|
698
1549
|
requestReceivedAt: prepared.timestamp
|
|
699
|
-
}
|
|
1550
|
+
}, this.persistence)
|
|
700
1551
|
});
|
|
701
1552
|
}
|
|
702
1553
|
recordDrop(type, reason, event) {
|
|
@@ -772,7 +1623,7 @@ function initDmdSDK(config) {
|
|
|
772
1623
|
return publicSingleton;
|
|
773
1624
|
}
|
|
774
1625
|
try {
|
|
775
|
-
const instance = new DriveMetaDataSDK(config);
|
|
1626
|
+
const instance = new DriveMetaDataSDK(normalizeBrowserConfig(config));
|
|
776
1627
|
return setSingleton(instance);
|
|
777
1628
|
} catch (error) {
|
|
778
1629
|
lastError = error instanceof Error ? error.message : String(error);
|