@mparticle/web-sdk 3.6.2 → 3.8.0
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/dist/mparticle.common.js +63 -42
- package/dist/mparticle.esm.js +63 -42
- package/dist/mparticle.js +204 -90
- package/dist/types/src/events.interfaces.d.ts +2 -1
- package/dist/types/src/integrationCapture.d.ts +3 -0
- package/dist/types/src/pageViewTracker.d.ts +9 -2
- package/dist/types/src/types.d.ts +1 -0
- package/dist/types/src/utils.d.ts +4 -3
- package/package.json +1 -1
- package/src/consent.ts +3 -3
- package/src/cookieConsentManager.ts +2 -3
- package/src/cookieSyncManager.ts +82 -69
- package/src/events.interfaces.ts +2 -1
- package/src/events.ts +7 -2
- package/src/filteredMparticleUser.ts +18 -10
- package/src/forwarders.ts +2 -2
- package/src/helpers.ts +9 -1
- package/src/identity-utils.ts +2 -3
- package/src/identity.ts +29 -11
- package/src/integrationCapture.ts +59 -0
- package/src/mp-instance.ts +4 -2
- package/src/pageViewTracker.ts +27 -1
- package/src/persistence.ts +3 -3
- package/src/store.ts +1 -1
- package/src/types.ts +14 -0
- package/src/utils.ts +29 -10
package/src/pageViewTracker.ts
CHANGED
|
@@ -127,6 +127,13 @@ interface IPageSnapshot {
|
|
|
127
127
|
interface IPageViewData extends IPageSnapshot {
|
|
128
128
|
hostname: string;
|
|
129
129
|
title: string;
|
|
130
|
+
isAutoPageView?: boolean;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Options for the emitters the AutoLogPageView flag drives. Passing this is how
|
|
134
|
+
// an emitter is told it is automatic; it never reads the feature flag itself.
|
|
135
|
+
export interface IPageViewOptions {
|
|
136
|
+
isAutoPageView?: boolean;
|
|
130
137
|
}
|
|
131
138
|
|
|
132
139
|
interface IPendingNavigation {
|
|
@@ -147,6 +154,16 @@ interface IPendingNavigation {
|
|
|
147
154
|
export const allowedQueryParams = (href: string): Dictionary<string> =>
|
|
148
155
|
queryStringParser(href, ALLOWED_QUERY_PARAMS);
|
|
149
156
|
|
|
157
|
+
export const AUTO_PAGE_VIEW_ATTRIBUTE = 'is_auto_page_view';
|
|
158
|
+
|
|
159
|
+
// Absent rather than false on a manual page view, so the attribute is only ever
|
|
160
|
+
// added by the automatic emitters. Shared by both of them so the key and that
|
|
161
|
+
// rule have one definition instead of two that can drift.
|
|
162
|
+
export const autoPageViewAttribute = (
|
|
163
|
+
isAutoPageView?: boolean
|
|
164
|
+
): Dictionary<boolean> =>
|
|
165
|
+
isAutoPageView ? { [AUTO_PAGE_VIEW_ATTRIBUTE]: true } : {};
|
|
166
|
+
|
|
150
167
|
// The captured params, in allowlist order. Ordering comes from the constant
|
|
151
168
|
// rather than a sort: it is deterministic without needing a comparator, and it
|
|
152
169
|
// does not depend on the object's insertion order, so reordering the query string
|
|
@@ -200,6 +217,7 @@ export const buildPageViewEvent = ({
|
|
|
200
217
|
hostname,
|
|
201
218
|
title,
|
|
202
219
|
path,
|
|
220
|
+
isAutoPageView,
|
|
203
221
|
}: IPageViewData): BaseEvent => ({
|
|
204
222
|
messageType: MessageType.PageView,
|
|
205
223
|
name: 'PageView',
|
|
@@ -211,6 +229,7 @@ export const buildPageViewEvent = ({
|
|
|
211
229
|
hostname,
|
|
212
230
|
title,
|
|
213
231
|
path,
|
|
232
|
+
...autoPageViewAttribute(isAutoPageView),
|
|
214
233
|
},
|
|
215
234
|
eventType: EventType.Unknown,
|
|
216
235
|
});
|
|
@@ -411,8 +430,14 @@ export class PageViewTracker {
|
|
|
411
430
|
private undoHistoryPatch: (() => void) | null = null;
|
|
412
431
|
private popStateListener: (() => void) | null = null;
|
|
413
432
|
|
|
414
|
-
|
|
433
|
+
private readonly isAutoPageView: boolean;
|
|
434
|
+
|
|
435
|
+
constructor(
|
|
436
|
+
mpInstance: IMParticleWebSDKInstance,
|
|
437
|
+
options?: IPageViewOptions
|
|
438
|
+
) {
|
|
415
439
|
this.mpInstance = mpInstance;
|
|
440
|
+
this.isAutoPageView = !!(options && options.isAutoPageView);
|
|
416
441
|
}
|
|
417
442
|
|
|
418
443
|
// True while this tracker owns the history patch and is listening for
|
|
@@ -589,6 +614,7 @@ export class PageViewTracker {
|
|
|
589
614
|
...page,
|
|
590
615
|
hostname: window.location.hostname,
|
|
591
616
|
title,
|
|
617
|
+
isAutoPageView: this.isAutoPageView,
|
|
592
618
|
});
|
|
593
619
|
|
|
594
620
|
this.log(
|
package/src/persistence.ts
CHANGED
|
@@ -1023,7 +1023,7 @@ export default function _Persistence(
|
|
|
1023
1023
|
if (csd) {
|
|
1024
1024
|
let persistence = self.getPersistence();
|
|
1025
1025
|
if (persistence) {
|
|
1026
|
-
if (persistence[mpid]) {
|
|
1026
|
+
if (mpInstance._Helpers.isObject(persistence[mpid])) {
|
|
1027
1027
|
persistence[mpid].csd = csd;
|
|
1028
1028
|
} else {
|
|
1029
1029
|
persistence[mpid] = {
|
|
@@ -1140,7 +1140,7 @@ export default function _Persistence(
|
|
|
1140
1140
|
}
|
|
1141
1141
|
let persistence = self.getPersistence();
|
|
1142
1142
|
if (persistence) {
|
|
1143
|
-
if (!persistence[mpid]) {
|
|
1143
|
+
if (!mpInstance._Helpers.isObject(persistence[mpid])) {
|
|
1144
1144
|
persistence[mpid] = {};
|
|
1145
1145
|
}
|
|
1146
1146
|
if (!persistence[mpid].fst) {
|
|
@@ -1180,7 +1180,7 @@ export default function _Persistence(
|
|
|
1180
1180
|
time = new Date().getTime();
|
|
1181
1181
|
}
|
|
1182
1182
|
let persistence = self.getPersistence();
|
|
1183
|
-
if (persistence && persistence[mpid]) {
|
|
1183
|
+
if (persistence && mpInstance._Helpers.isObject(persistence[mpid])) {
|
|
1184
1184
|
persistence[mpid].lst = time;
|
|
1185
1185
|
self.savePersistence(persistence);
|
|
1186
1186
|
}
|
package/src/store.ts
CHANGED
|
@@ -533,7 +533,7 @@ export default function Store(
|
|
|
533
533
|
this.syncPersistenceData();
|
|
534
534
|
|
|
535
535
|
if (this.persistenceData) {
|
|
536
|
-
if (this.persistenceData[mpid]) {
|
|
536
|
+
if (isObject(this.persistenceData[mpid])) {
|
|
537
537
|
this.persistenceData[mpid][key] = value;
|
|
538
538
|
} else {
|
|
539
539
|
this.persistenceData[mpid] = {
|
package/src/types.ts
CHANGED
|
@@ -558,6 +558,20 @@ export function getEventCategoryFromCustomEventType(
|
|
|
558
558
|
}
|
|
559
559
|
}
|
|
560
560
|
|
|
561
|
+
// A stored `ui` key is the decimal string of an IdentityType; anything else was
|
|
562
|
+
// not written by this SDK. The round-trip comparison is load bearing: parseNumber
|
|
563
|
+
// returns 0 for any non-numeric key and IdentityType.Other is 0, so after parsing
|
|
564
|
+
// alone a stored "hasOwnProperty" is indistinguishable from a genuine Other entry.
|
|
565
|
+
export function getIdentityTypeFromStoredKey(key: string): number | null {
|
|
566
|
+
const identityType = parseNumber(key);
|
|
567
|
+
|
|
568
|
+
if (String(identityType) !== key || !IdentityType.isValid(identityType)) {
|
|
569
|
+
return null;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
return identityType;
|
|
573
|
+
}
|
|
574
|
+
|
|
561
575
|
export function getIdentityTypeFromBatchKey(
|
|
562
576
|
key: string
|
|
563
577
|
): number {
|
package/src/utils.ts
CHANGED
|
@@ -44,7 +44,7 @@ const findKeyInObject = (obj: any, key: string): string => {
|
|
|
44
44
|
if (key && obj) {
|
|
45
45
|
for (var prop in obj) {
|
|
46
46
|
if (
|
|
47
|
-
obj
|
|
47
|
+
hasOwnProp(obj, prop) &&
|
|
48
48
|
prop.toLowerCase() === key.toLowerCase()
|
|
49
49
|
) {
|
|
50
50
|
return prop;
|
|
@@ -246,8 +246,13 @@ const WEB_SAFE_BASE64_REPLACEMENTS: Dictionary<string> = {
|
|
|
246
246
|
'=': '',
|
|
247
247
|
};
|
|
248
248
|
|
|
249
|
-
|
|
250
|
-
|
|
249
|
+
// btoa is defined only over Latin-1 and throws InvalidCharacterError above U+00FF
|
|
250
|
+
const isLatin1 = (value: string): boolean => !/[^\u0000-\u00ff]/.test(value);
|
|
251
|
+
|
|
252
|
+
const toWebSafeBase64 = (value: string): string | undefined =>
|
|
253
|
+
isLatin1(value)
|
|
254
|
+
? btoa(value).replace(/[+/=]/g, c => WEB_SAFE_BASE64_REPLACEMENTS[c])
|
|
255
|
+
: undefined;
|
|
251
256
|
|
|
252
257
|
// FIXME: REFACTOR for V3
|
|
253
258
|
// only used in store.js to sanitize server-side formatting of
|
|
@@ -316,9 +321,26 @@ const moveElementToEnd = <T>(array: T[], index: number): T[] =>
|
|
|
316
321
|
// does not compile under this project's `lib: ["es5", "es6", "dom"]`; widening that
|
|
317
322
|
// would emit a call absent from every browser before 2021, and this same file still
|
|
318
323
|
// carries a fallback for browsers with no URLSearchParams.
|
|
319
|
-
const hasOwnProp = (obj: object, key:
|
|
324
|
+
const hasOwnProp = (obj: object, key: PropertyKey): boolean =>
|
|
320
325
|
Object.prototype.hasOwnProperty.call(obj, key);
|
|
321
326
|
|
|
327
|
+
// Assigning `__proto__` replaces the target's prototype instead of adding an own
|
|
328
|
+
// property; `constructor` is reserved alongside it by the stored-record contract.
|
|
329
|
+
// `prototype` is deliberately absent: isValidKeyValue accepts it, so setUserAttribute
|
|
330
|
+
// persists it and the getters must hand it back.
|
|
331
|
+
const isReservedStoredPropertyName = (name: string): boolean =>
|
|
332
|
+
name === '__proto__' || name === 'constructor';
|
|
333
|
+
|
|
334
|
+
// extend's historical set, which additionally refuses `prototype` when merging.
|
|
335
|
+
const isUncopyableMergeName = (name: string): boolean =>
|
|
336
|
+
isReservedStoredPropertyName(name) || name === 'prototype';
|
|
337
|
+
|
|
338
|
+
// Kit-facing copies stay compatible with conventional own-property iteration, such as
|
|
339
|
+
// attributes.hasOwnProperty(key), which is the one read pattern an attribute of that name
|
|
340
|
+
// interferes with. The public getters keep the name; only this filter drops it.
|
|
341
|
+
const isReservedKitPropertyName = (name: string): boolean =>
|
|
342
|
+
isReservedStoredPropertyName(name) || name === 'hasOwnProperty';
|
|
343
|
+
|
|
322
344
|
const queryStringParser = (
|
|
323
345
|
url: string,
|
|
324
346
|
keys: string[] = []
|
|
@@ -446,7 +468,7 @@ const filterDictionaryWithHash = <T>(
|
|
|
446
468
|
|
|
447
469
|
if (!isEmpty(dictionary)) {
|
|
448
470
|
for (const key in dictionary) {
|
|
449
|
-
if (dictionary
|
|
471
|
+
if (hasOwnProp(dictionary, key) && !isReservedKitPropertyName(key)) {
|
|
450
472
|
const hashedKey = hashFn(key);
|
|
451
473
|
if (!inArray(filterList, hashedKey)) {
|
|
452
474
|
filtered[key] = dictionary[key];
|
|
@@ -612,11 +634,7 @@ function extend(...args: any[]): any {
|
|
|
612
634
|
for (; i < length; i++) {
|
|
613
635
|
if ((options = args[i]) != null) {
|
|
614
636
|
for (name in options) {
|
|
615
|
-
if (
|
|
616
|
-
name === '__proto__' ||
|
|
617
|
-
name === 'constructor' ||
|
|
618
|
-
name === 'prototype'
|
|
619
|
-
) {
|
|
637
|
+
if (isUncopyableMergeName(name)) {
|
|
620
638
|
continue;
|
|
621
639
|
}
|
|
622
640
|
|
|
@@ -721,6 +739,7 @@ export {
|
|
|
721
739
|
moveElementToEnd,
|
|
722
740
|
queryStringParser,
|
|
723
741
|
hasOwnProp,
|
|
742
|
+
isReservedStoredPropertyName,
|
|
724
743
|
getCookies,
|
|
725
744
|
getHref,
|
|
726
745
|
replaceMPID,
|