@mparticle/web-sdk 3.6.1 → 3.7.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 +61 -40
- package/dist/mparticle.esm.js +61 -40
- package/dist/mparticle.js +200 -88
- 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/identity-utils.ts +2 -3
- package/src/identity.ts +27 -10
- 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/dist/mparticle.js
CHANGED
|
@@ -204,7 +204,7 @@ var mParticle = (function () {
|
|
|
204
204
|
Base64: Base64$1
|
|
205
205
|
};
|
|
206
206
|
|
|
207
|
-
var version = "3.
|
|
207
|
+
var version = "3.7.0";
|
|
208
208
|
|
|
209
209
|
var Constants = {
|
|
210
210
|
sdkVersion: version,
|
|
@@ -547,7 +547,7 @@ var mParticle = (function () {
|
|
|
547
547
|
var findKeyInObject = function findKeyInObject(obj, key) {
|
|
548
548
|
if (key && obj) {
|
|
549
549
|
for (var prop in obj) {
|
|
550
|
-
if (obj
|
|
550
|
+
if (hasOwnProp(obj, prop) && prop.toLowerCase() === key.toLowerCase()) {
|
|
551
551
|
return prop;
|
|
552
552
|
}
|
|
553
553
|
}
|
|
@@ -704,10 +704,14 @@ var mParticle = (function () {
|
|
|
704
704
|
'/': '_',
|
|
705
705
|
'=': ''
|
|
706
706
|
};
|
|
707
|
+
// btoa is defined only over Latin-1 and throws InvalidCharacterError above U+00FF
|
|
708
|
+
var isLatin1 = function isLatin1(value) {
|
|
709
|
+
return !/[^\u0000-\u00ff]/.test(value);
|
|
710
|
+
};
|
|
707
711
|
var toWebSafeBase64 = function toWebSafeBase64(value) {
|
|
708
|
-
return btoa(value).replace(/[+/=]/g, function (c) {
|
|
712
|
+
return isLatin1(value) ? btoa(value).replace(/[+/=]/g, function (c) {
|
|
709
713
|
return WEB_SAFE_BASE64_REPLACEMENTS[c];
|
|
710
|
-
});
|
|
714
|
+
}) : undefined;
|
|
711
715
|
};
|
|
712
716
|
// FIXME: REFACTOR for V3
|
|
713
717
|
// only used in store.js to sanitize server-side formatting of
|
|
@@ -773,6 +777,23 @@ var mParticle = (function () {
|
|
|
773
777
|
var hasOwnProp = function hasOwnProp(obj, key) {
|
|
774
778
|
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
775
779
|
};
|
|
780
|
+
// Assigning `__proto__` replaces the target's prototype instead of adding an own
|
|
781
|
+
// property; `constructor` is reserved alongside it by the stored-record contract.
|
|
782
|
+
// `prototype` is deliberately absent: isValidKeyValue accepts it, so setUserAttribute
|
|
783
|
+
// persists it and the getters must hand it back.
|
|
784
|
+
var isReservedStoredPropertyName = function isReservedStoredPropertyName(name) {
|
|
785
|
+
return name === '__proto__' || name === 'constructor';
|
|
786
|
+
};
|
|
787
|
+
// extend's historical set, which additionally refuses `prototype` when merging.
|
|
788
|
+
var isUncopyableMergeName = function isUncopyableMergeName(name) {
|
|
789
|
+
return isReservedStoredPropertyName(name) || name === 'prototype';
|
|
790
|
+
};
|
|
791
|
+
// Kit-facing copies stay compatible with conventional own-property iteration, such as
|
|
792
|
+
// attributes.hasOwnProperty(key), which is the one read pattern an attribute of that name
|
|
793
|
+
// interferes with. The public getters keep the name; only this filter drops it.
|
|
794
|
+
var isReservedKitPropertyName = function isReservedKitPropertyName(name) {
|
|
795
|
+
return isReservedStoredPropertyName(name) || name === 'hasOwnProperty';
|
|
796
|
+
};
|
|
776
797
|
var queryStringParser = function queryStringParser(url, keys) {
|
|
777
798
|
if (keys === void 0) {
|
|
778
799
|
keys = [];
|
|
@@ -877,7 +898,7 @@ var mParticle = (function () {
|
|
|
877
898
|
var filtered = {};
|
|
878
899
|
if (!isEmpty(dictionary)) {
|
|
879
900
|
for (var key in dictionary) {
|
|
880
|
-
if (dictionary
|
|
901
|
+
if (hasOwnProp(dictionary, key) && !isReservedKitPropertyName(key)) {
|
|
881
902
|
var hashedKey = hashFn(key);
|
|
882
903
|
if (!inArray(filterList, hashedKey)) {
|
|
883
904
|
filtered[key] = dictionary[key];
|
|
@@ -1013,7 +1034,7 @@ var mParticle = (function () {
|
|
|
1013
1034
|
for (; i < length; i++) {
|
|
1014
1035
|
if ((options = args[i]) != null) {
|
|
1015
1036
|
for (name in options) {
|
|
1016
|
-
if (name
|
|
1037
|
+
if (isUncopyableMergeName(name)) {
|
|
1017
1038
|
continue;
|
|
1018
1039
|
}
|
|
1019
1040
|
if (!Object.prototype.hasOwnProperty.call(options, name)) {
|
|
@@ -1484,6 +1505,17 @@ var mParticle = (function () {
|
|
|
1484
1505
|
JointSdkSelectPlacements: 'mp:jointSdkSelectPlacements',
|
|
1485
1506
|
JointSdkRoktKitInit: 'mp:jointSdkRoktKitInit'
|
|
1486
1507
|
};
|
|
1508
|
+
// A stored `ui` key is the decimal string of an IdentityType; anything else was
|
|
1509
|
+
// not written by this SDK. The round-trip comparison is load bearing: parseNumber
|
|
1510
|
+
// returns 0 for any non-numeric key and IdentityType.Other is 0, so after parsing
|
|
1511
|
+
// alone a stored "hasOwnProperty" is indistinguishable from a genuine Other entry.
|
|
1512
|
+
function getIdentityTypeFromStoredKey(key) {
|
|
1513
|
+
var identityType = parseNumber(key);
|
|
1514
|
+
if (String(identityType) !== key || !IdentityType.isValid(identityType)) {
|
|
1515
|
+
return null;
|
|
1516
|
+
}
|
|
1517
|
+
return identityType;
|
|
1518
|
+
}
|
|
1487
1519
|
var Types = {
|
|
1488
1520
|
MessageType: MessageType$1,
|
|
1489
1521
|
EventType: EventType,
|
|
@@ -3462,8 +3494,7 @@ var mParticle = (function () {
|
|
|
3462
3494
|
}
|
|
3463
3495
|
var cacheKey = concatenateIdentities(method, proposedUserIdentities);
|
|
3464
3496
|
var hashedKey = generateHash(cacheKey);
|
|
3465
|
-
|
|
3466
|
-
if (!cache.hasOwnProperty(hashedKey)) {
|
|
3497
|
+
if (!hasOwnProp(cache, hashedKey)) {
|
|
3467
3498
|
return false;
|
|
3468
3499
|
}
|
|
3469
3500
|
// If there is a valid cache key, compare the expireTimestamp to the current time.
|
|
@@ -4223,57 +4254,65 @@ var mParticle = (function () {
|
|
|
4223
4254
|
}
|
|
4224
4255
|
pixelConfigurations.forEach(function (pixelSettings) {
|
|
4225
4256
|
var _a, _b, _c;
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4257
|
+
try {
|
|
4258
|
+
// set requiresConsent to false to start each additional pixel configuration
|
|
4259
|
+
// set to true only if filteringConsenRuleValues.values.length exists
|
|
4260
|
+
var requiresConsent = false;
|
|
4261
|
+
// Filtering rules as defined in UI
|
|
4262
|
+
var filteringConsentRuleValues = pixelSettings.filteringConsentRuleValues,
|
|
4263
|
+
pixelUrl = pixelSettings.pixelUrl,
|
|
4264
|
+
redirectUrl = pixelSettings.redirectUrl,
|
|
4265
|
+
moduleId = pixelSettings.moduleId,
|
|
4266
|
+
settings = pixelSettings.settings,
|
|
4267
|
+
// Tells you how often we should do a cookie sync (in days)
|
|
4268
|
+
frequencyCap = pixelSettings.frequencyCap;
|
|
4269
|
+
var values = (filteringConsentRuleValues || {}).values;
|
|
4270
|
+
if (isEmpty(pixelUrl)) {
|
|
4271
|
+
return;
|
|
4272
|
+
}
|
|
4273
|
+
if (!isEmpty(values)) {
|
|
4274
|
+
requiresConsent = true;
|
|
4275
|
+
}
|
|
4276
|
+
// If MPID is new to cookies, we should not try to perform the cookie sync
|
|
4277
|
+
// because a cookie sync can only occur once a user either consents or doesn't.
|
|
4278
|
+
// we should not check if it's enabled if the user has a blank consent
|
|
4279
|
+
if (requiresConsent && mpidIsNotInCookies) {
|
|
4280
|
+
return;
|
|
4281
|
+
}
|
|
4282
|
+
// For Rokt, block cookie sync when noTargeting privacy flag is true
|
|
4283
|
+
if (moduleId === PARTNER_MODULE_IDS.Rokt && mpInstance._CookieConsentManager.getNoTargeting()) {
|
|
4284
|
+
return;
|
|
4285
|
+
}
|
|
4286
|
+
var isEnabledForUserConsent = mpInstance._Consent.isEnabledForUserConsent;
|
|
4287
|
+
if (!isEnabledForUserConsent(filteringConsentRuleValues, mpInstance.Identity.getCurrentUser())) {
|
|
4288
|
+
return;
|
|
4289
|
+
}
|
|
4290
|
+
var cookieSyncDates = (_b = (_a = persistence[mpid]) === null || _a === void 0 ? void 0 : _a.csd) !== null && _b !== void 0 ? _b : {};
|
|
4291
|
+
var lastSyncDateForModule = cookieSyncDates[moduleId] || null;
|
|
4292
|
+
if (!isLastSyncDateExpired(frequencyCap, lastSyncDateForModule)) {
|
|
4293
|
+
return;
|
|
4294
|
+
}
|
|
4295
|
+
// The Trade Desk requires a URL parameter for GDPR enabled users.
|
|
4296
|
+
// It is optional but to simplify the code, we add it for all Trade
|
|
4297
|
+
// // Desk cookie syncs.
|
|
4298
|
+
var domain = moduleId === PARTNER_MODULE_IDS.TradeDesk ? window.location.hostname : undefined;
|
|
4299
|
+
// Google Marketing Platform accepts a web-safe base64-encoded MPID via the
|
|
4300
|
+
// `google_hm` query parameter, but only for accounts provisioned for Google
|
|
4301
|
+
// Hosted Matching — Google returns errors otherwise. It is therefore gated
|
|
4302
|
+
// behind the opt-in `enableHmTag` setting (off by default), which the server
|
|
4303
|
+
// delivers as the string 'True' when the UI toggle is enabled.
|
|
4304
|
+
var enableHmTag = ((_c = settings === null || settings === void 0 ? void 0 : settings.enableHmTag) === null || _c === void 0 ? void 0 : _c.toLowerCase()) === 'true';
|
|
4305
|
+
var isDoubleClickModule = moduleId === PARTNER_MODULE_IDS.DoubleclickDFP;
|
|
4306
|
+
var usesHostedMatching = isDoubleClickModule && enableHmTag;
|
|
4307
|
+
var base64Mpid = usesHostedMatching ? toWebSafeBase64(mpid) : undefined;
|
|
4308
|
+
if (usesHostedMatching && !base64Mpid) {
|
|
4309
|
+
mpInstance.Logger.warning('Unable to base64 encode the current MPID; omitting the google_hm parameter from this cookie sync');
|
|
4310
|
+
}
|
|
4311
|
+
var fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain, base64Mpid);
|
|
4312
|
+
self.performCookieSync(fullUrl, moduleId.toString(), mpid, cookieSyncDates);
|
|
4313
|
+
} catch (e) {
|
|
4314
|
+
mpInstance.Logger.error('Error performing cookie sync: ' + e);
|
|
4262
4315
|
}
|
|
4263
|
-
// The Trade Desk requires a URL parameter for GDPR enabled users.
|
|
4264
|
-
// It is optional but to simplify the code, we add it for all Trade
|
|
4265
|
-
// // Desk cookie syncs.
|
|
4266
|
-
var domain = moduleId === PARTNER_MODULE_IDS.TradeDesk ? window.location.hostname : undefined;
|
|
4267
|
-
// Google Marketing Platform accepts a web-safe base64-encoded MPID via the
|
|
4268
|
-
// `google_hm` query parameter, but only for accounts provisioned for Google
|
|
4269
|
-
// Hosted Matching — Google returns errors otherwise. It is therefore gated
|
|
4270
|
-
// behind the opt-in `enableHmTag` setting (off by default), which the server
|
|
4271
|
-
// delivers as the string 'True' when the UI toggle is enabled.
|
|
4272
|
-
var enableHmTag = ((_c = settings === null || settings === void 0 ? void 0 : settings.enableHmTag) === null || _c === void 0 ? void 0 : _c.toLowerCase()) === 'true';
|
|
4273
|
-
var isDoubleClickModule = moduleId === PARTNER_MODULE_IDS.DoubleclickDFP;
|
|
4274
|
-
var base64Mpid = isDoubleClickModule && enableHmTag ? toWebSafeBase64(mpid) : undefined;
|
|
4275
|
-
var fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain, base64Mpid);
|
|
4276
|
-
self.performCookieSync(fullUrl, moduleId.toString(), mpid, cookieSyncDates);
|
|
4277
4316
|
});
|
|
4278
4317
|
};
|
|
4279
4318
|
// Private
|
|
@@ -5259,7 +5298,7 @@ var mParticle = (function () {
|
|
|
5259
5298
|
}
|
|
5260
5299
|
_this.syncPersistenceData();
|
|
5261
5300
|
if (_this.persistenceData) {
|
|
5262
|
-
if (_this.persistenceData[mpid]) {
|
|
5301
|
+
if (isObject(_this.persistenceData[mpid])) {
|
|
5263
5302
|
_this.persistenceData[mpid][key] = value;
|
|
5264
5303
|
} else {
|
|
5265
5304
|
_this.persistenceData[mpid] = (_a = {}, _a[key] = value, _a);
|
|
@@ -6237,7 +6276,7 @@ var mParticle = (function () {
|
|
|
6237
6276
|
if (csd) {
|
|
6238
6277
|
var persistence = self.getPersistence();
|
|
6239
6278
|
if (persistence) {
|
|
6240
|
-
if (persistence[mpid]) {
|
|
6279
|
+
if (mpInstance._Helpers.isObject(persistence[mpid])) {
|
|
6241
6280
|
persistence[mpid].csd = csd;
|
|
6242
6281
|
} else {
|
|
6243
6282
|
persistence[mpid] = {
|
|
@@ -6318,7 +6357,7 @@ var mParticle = (function () {
|
|
|
6318
6357
|
}
|
|
6319
6358
|
var persistence = self.getPersistence();
|
|
6320
6359
|
if (persistence) {
|
|
6321
|
-
if (!persistence[mpid]) {
|
|
6360
|
+
if (!mpInstance._Helpers.isObject(persistence[mpid])) {
|
|
6322
6361
|
persistence[mpid] = {};
|
|
6323
6362
|
}
|
|
6324
6363
|
if (!persistence[mpid].fst) {
|
|
@@ -6356,7 +6395,7 @@ var mParticle = (function () {
|
|
|
6356
6395
|
time = new Date().getTime();
|
|
6357
6396
|
}
|
|
6358
6397
|
var persistence = self.getPersistence();
|
|
6359
|
-
if (persistence && persistence[mpid]) {
|
|
6398
|
+
if (persistence && mpInstance._Helpers.isObject(persistence[mpid])) {
|
|
6360
6399
|
persistence[mpid].lst = time;
|
|
6361
6400
|
self.savePersistence(persistence);
|
|
6362
6401
|
}
|
|
@@ -6445,6 +6484,14 @@ var mParticle = (function () {
|
|
|
6445
6484
|
var allowedQueryParams = function allowedQueryParams(href) {
|
|
6446
6485
|
return queryStringParser(href, ALLOWED_QUERY_PARAMS);
|
|
6447
6486
|
};
|
|
6487
|
+
var AUTO_PAGE_VIEW_ATTRIBUTE = 'is_auto_page_view';
|
|
6488
|
+
// Absent rather than false on a manual page view, so the attribute is only ever
|
|
6489
|
+
// added by the automatic emitters. Shared by both of them so the key and that
|
|
6490
|
+
// rule have one definition instead of two that can drift.
|
|
6491
|
+
var autoPageViewAttribute = function autoPageViewAttribute(isAutoPageView) {
|
|
6492
|
+
var _a;
|
|
6493
|
+
return isAutoPageView ? (_a = {}, _a[AUTO_PAGE_VIEW_ATTRIBUTE] = true, _a) : {};
|
|
6494
|
+
};
|
|
6448
6495
|
// The captured params, in allowlist order. Ordering comes from the constant
|
|
6449
6496
|
// rather than a sort: it is deterministic without needing a comparator, and it
|
|
6450
6497
|
// does not depend on the object's insertion order, so reordering the query string
|
|
@@ -6492,18 +6539,19 @@ var mParticle = (function () {
|
|
|
6492
6539
|
var params = _a.params,
|
|
6493
6540
|
hostname = _a.hostname,
|
|
6494
6541
|
title = _a.title,
|
|
6495
|
-
path = _a.path
|
|
6542
|
+
path = _a.path,
|
|
6543
|
+
isAutoPageView = _a.isAutoPageView;
|
|
6496
6544
|
return {
|
|
6497
6545
|
messageType: MessageType$1.PageView,
|
|
6498
6546
|
name: 'PageView',
|
|
6499
6547
|
// Params spread first, then the core fields by name, so a core field always
|
|
6500
6548
|
// wins. No allowlist entry collides with hostname/title/path today; naming
|
|
6501
6549
|
// them here is what keeps a later addition from silently overwriting one.
|
|
6502
|
-
data: __assign(__assign({}, params), {
|
|
6550
|
+
data: __assign(__assign(__assign({}, params), {
|
|
6503
6551
|
hostname: hostname,
|
|
6504
6552
|
title: title,
|
|
6505
6553
|
path: path
|
|
6506
|
-
}),
|
|
6554
|
+
}), autoPageViewAttribute(isAutoPageView)),
|
|
6507
6555
|
eventType: EventType.Unknown
|
|
6508
6556
|
};
|
|
6509
6557
|
};
|
|
@@ -6663,13 +6711,14 @@ var mParticle = (function () {
|
|
|
6663
6711
|
// Tracker
|
|
6664
6712
|
// ---------------------------------------------------------------------------
|
|
6665
6713
|
var PageViewTracker = /** @class */function () {
|
|
6666
|
-
function PageViewTracker(mpInstance) {
|
|
6714
|
+
function PageViewTracker(mpInstance, options) {
|
|
6667
6715
|
this.lastPage = null;
|
|
6668
6716
|
this.active = false;
|
|
6669
6717
|
this.pendingNavigations = [];
|
|
6670
6718
|
this.undoHistoryPatch = null;
|
|
6671
6719
|
this.popStateListener = null;
|
|
6672
6720
|
this.mpInstance = mpInstance;
|
|
6721
|
+
this.isAutoPageView = !!(options && options.isAutoPageView);
|
|
6673
6722
|
}
|
|
6674
6723
|
Object.defineProperty(PageViewTracker.prototype, "isActive", {
|
|
6675
6724
|
// True while this tracker owns the history patch and is listening for
|
|
@@ -6812,7 +6861,8 @@ var mParticle = (function () {
|
|
|
6812
6861
|
var title = window.document.title;
|
|
6813
6862
|
var event = buildPageViewEvent(__assign(__assign({}, page), {
|
|
6814
6863
|
hostname: window.location.hostname,
|
|
6815
|
-
title: title
|
|
6864
|
+
title: title,
|
|
6865
|
+
isAutoPageView: this.isAutoPageView
|
|
6816
6866
|
}));
|
|
6817
6867
|
this.log("[fire] deferred flush -> _Events.logEvent(PageView) (page: ".concat(describePage(page), ", title: ").concat(title, ")"));
|
|
6818
6868
|
this.mpInstance._Events.logEvent(event);
|
|
@@ -6904,14 +6954,14 @@ var mParticle = (function () {
|
|
|
6904
6954
|
// come from PageViewTracker instead, so both emitters attach the same
|
|
6905
6955
|
// allowlisted query params — and this is the one that matters for campaign
|
|
6906
6956
|
// attribution, since utm_*/gclid live on the entry URL.
|
|
6907
|
-
this.logPageView = function () {
|
|
6957
|
+
this.logPageView = function (options) {
|
|
6908
6958
|
self.logEvent({
|
|
6909
6959
|
messageType: Types.MessageType.PageView,
|
|
6910
6960
|
name: 'PageView',
|
|
6911
|
-
data: __assign(__assign({}, allowedQueryParams(getHref())), {
|
|
6961
|
+
data: __assign(__assign(__assign({}, allowedQueryParams(getHref())), {
|
|
6912
6962
|
hostname: window.location.hostname,
|
|
6913
6963
|
title: window.document.title
|
|
6914
|
-
}),
|
|
6964
|
+
}), autoPageViewAttribute(options && options.isAutoPageView)),
|
|
6915
6965
|
eventType: Types.EventType.Unknown
|
|
6916
6966
|
});
|
|
6917
6967
|
};
|
|
@@ -7095,7 +7145,7 @@ var mParticle = (function () {
|
|
|
7095
7145
|
return userAttributesCopy;
|
|
7096
7146
|
}
|
|
7097
7147
|
for (var prop in userAttributes) {
|
|
7098
|
-
if (!userAttributes
|
|
7148
|
+
if (!hasOwnProp(userAttributes, prop) || isReservedStoredPropertyName(prop) || !isAttributeKeyAllowed(kitBlocker, prop)) {
|
|
7099
7149
|
continue;
|
|
7100
7150
|
}
|
|
7101
7151
|
userAttributesCopy[prop] = copyUserAttributeValue(userAttributes[prop]);
|
|
@@ -7105,21 +7155,27 @@ var mParticle = (function () {
|
|
|
7105
7155
|
function buildUserAttributeLists(userAttributes, kitBlocker) {
|
|
7106
7156
|
var userAttributesLists = {};
|
|
7107
7157
|
for (var key in userAttributes) {
|
|
7108
|
-
if (!userAttributes
|
|
7158
|
+
if (!hasOwnProp(userAttributes, key) || isReservedStoredPropertyName(key) || !Array.isArray(userAttributes[key]) || !isAttributeKeyAllowed(kitBlocker, key)) {
|
|
7109
7159
|
continue;
|
|
7110
7160
|
}
|
|
7111
7161
|
userAttributesLists[key] = userAttributes[key].slice();
|
|
7112
7162
|
}
|
|
7113
7163
|
return userAttributesLists;
|
|
7114
7164
|
}
|
|
7115
|
-
function buildFilteredUserIdentities(identities, kitBlocker
|
|
7165
|
+
function buildFilteredUserIdentities(identities, kitBlocker) {
|
|
7116
7166
|
var currentUserIdentities = {};
|
|
7117
7167
|
var identitiesByType = identities;
|
|
7118
7168
|
for (var identityType in identitiesByType) {
|
|
7119
|
-
if (!identitiesByType
|
|
7169
|
+
if (!hasOwnProp(identitiesByType, identityType)) {
|
|
7120
7170
|
continue;
|
|
7121
7171
|
}
|
|
7122
|
-
var
|
|
7172
|
+
var storedIdentityType = getIdentityTypeFromStoredKey(identityType);
|
|
7173
|
+
// Must be `=== null`: IdentityType.Other is 0, so a falsy check would
|
|
7174
|
+
// drop a valid stored Other identity.
|
|
7175
|
+
if (storedIdentityType === null) {
|
|
7176
|
+
continue;
|
|
7177
|
+
}
|
|
7178
|
+
var identityName = Types.IdentityType.getIdentityName(storedIdentityType);
|
|
7123
7179
|
if (!isIdentityAllowed(kitBlocker, identityName)) {
|
|
7124
7180
|
continue;
|
|
7125
7181
|
}
|
|
@@ -7134,7 +7190,7 @@ var mParticle = (function () {
|
|
|
7134
7190
|
}
|
|
7135
7191
|
return {
|
|
7136
7192
|
getUserIdentities: function getUserIdentities() {
|
|
7137
|
-
var currentUserIdentities = buildFilteredUserIdentities(mpInstance._Store.getUserIdentities(mpid), kitBlocker
|
|
7193
|
+
var currentUserIdentities = buildFilteredUserIdentities(mpInstance._Store.getUserIdentities(mpid), kitBlocker);
|
|
7138
7194
|
currentUserIdentities = mpInstance._Helpers.filterUserIdentitiesForForwarders(currentUserIdentities, forwarder.userIdentityFilters);
|
|
7139
7195
|
return {
|
|
7140
7196
|
userIdentities: currentUserIdentities
|
|
@@ -7245,7 +7301,7 @@ var mParticle = (function () {
|
|
|
7245
7301
|
}
|
|
7246
7302
|
function userAttributesMatchFilter(userAttributes, filterObject) {
|
|
7247
7303
|
for (var attrName in userAttributes) {
|
|
7248
|
-
if (!userAttributes
|
|
7304
|
+
if (!hasOwnProp(userAttributes, attrName)) {
|
|
7249
7305
|
continue;
|
|
7250
7306
|
}
|
|
7251
7307
|
var attrHash = KitFilterHelper.hashAttributeConditionalForwarding(attrName);
|
|
@@ -8596,9 +8652,16 @@ var mParticle = (function () {
|
|
|
8596
8652
|
var currentUserIdentities = {};
|
|
8597
8653
|
var identities = mpInstance._Store.getUserIdentities(mpid);
|
|
8598
8654
|
for (var identityType in identities) {
|
|
8599
|
-
if (identities
|
|
8600
|
-
|
|
8655
|
+
if (!hasOwnProp(identities, identityType)) {
|
|
8656
|
+
continue;
|
|
8601
8657
|
}
|
|
8658
|
+
var storedIdentityType = getIdentityTypeFromStoredKey(identityType);
|
|
8659
|
+
// Must be `=== null`: IdentityType.Other is 0, so a falsy
|
|
8660
|
+
// check would drop a valid stored Other identity.
|
|
8661
|
+
if (storedIdentityType === null) {
|
|
8662
|
+
continue;
|
|
8663
|
+
}
|
|
8664
|
+
currentUserIdentities[Types.IdentityType.getIdentityName(storedIdentityType)] = identities[identityType];
|
|
8602
8665
|
}
|
|
8603
8666
|
return {
|
|
8604
8667
|
userIdentities: currentUserIdentities
|
|
@@ -8727,7 +8790,7 @@ var mParticle = (function () {
|
|
|
8727
8790
|
}
|
|
8728
8791
|
var deletedUAKeyCopy = userAttributes[key] ? userAttributes[key].toString() : null;
|
|
8729
8792
|
delete userAttributes[key];
|
|
8730
|
-
if (cookies && cookies[mpid]) {
|
|
8793
|
+
if (cookies && isObject(cookies[mpid])) {
|
|
8731
8794
|
cookies[mpid].ua = userAttributes;
|
|
8732
8795
|
mpInstance._Persistence.savePersistence(cookies);
|
|
8733
8796
|
}
|
|
@@ -8810,7 +8873,7 @@ var mParticle = (function () {
|
|
|
8810
8873
|
mpInstance._Forwarders.initForwarders(self.IdentityAPI.getCurrentUser().getUserIdentities().userIdentities, mpInstance._APIClient.prepareForwardingStats);
|
|
8811
8874
|
if (userAttributes) {
|
|
8812
8875
|
for (var prop in userAttributes) {
|
|
8813
|
-
if (userAttributes
|
|
8876
|
+
if (hasOwnProp(userAttributes, prop)) {
|
|
8814
8877
|
mpInstance._Forwarders.handleForwarderUserAttributes('removeUserAttribute', prop, null);
|
|
8815
8878
|
}
|
|
8816
8879
|
this.removeUserAttribute(prop);
|
|
@@ -8828,7 +8891,7 @@ var mParticle = (function () {
|
|
|
8828
8891
|
var userAttributesLists = {};
|
|
8829
8892
|
userAttributes = this.getAllUserAttributes();
|
|
8830
8893
|
for (var key in userAttributes) {
|
|
8831
|
-
if (userAttributes
|
|
8894
|
+
if (hasOwnProp(userAttributes, key) && !isReservedStoredPropertyName(key) && Array.isArray(userAttributes[key])) {
|
|
8832
8895
|
userAttributesLists[key] = userAttributes[key].slice();
|
|
8833
8896
|
}
|
|
8834
8897
|
}
|
|
@@ -8845,7 +8908,7 @@ var mParticle = (function () {
|
|
|
8845
8908
|
var userAttributes = getUserAttributes(mpid);
|
|
8846
8909
|
if (userAttributes) {
|
|
8847
8910
|
for (var prop in userAttributes) {
|
|
8848
|
-
if (userAttributes
|
|
8911
|
+
if (hasOwnProp(userAttributes, prop) && !isReservedStoredPropertyName(prop)) {
|
|
8849
8912
|
var attrValue = userAttributes[prop];
|
|
8850
8913
|
if (Array.isArray(attrValue)) {
|
|
8851
8914
|
userAttributesCopy[prop] = attrValue.slice();
|
|
@@ -9236,14 +9299,14 @@ var mParticle = (function () {
|
|
|
9236
9299
|
var state = self.createConsentState();
|
|
9237
9300
|
if (json.gdpr) {
|
|
9238
9301
|
for (var purpose in json.gdpr) {
|
|
9239
|
-
if (json.gdpr
|
|
9302
|
+
if (hasOwnProp(json.gdpr, purpose)) {
|
|
9240
9303
|
var gdprConsent = self.createPrivacyConsent(json.gdpr[purpose].c, json.gdpr[purpose].ts, json.gdpr[purpose].d, json.gdpr[purpose].l, json.gdpr[purpose].h);
|
|
9241
9304
|
state.addGDPRConsentState(purpose, gdprConsent);
|
|
9242
9305
|
}
|
|
9243
9306
|
}
|
|
9244
9307
|
}
|
|
9245
9308
|
if (json.ccpa) {
|
|
9246
|
-
if (json.ccpa
|
|
9309
|
+
if (hasOwnProp(json.ccpa, CCPAPurpose)) {
|
|
9247
9310
|
var ccpaConsent = self.createPrivacyConsent(json.ccpa[CCPAPurpose].c, json.ccpa[CCPAPurpose].ts, json.ccpa[CCPAPurpose].d, json.ccpa[CCPAPurpose].l, json.ccpa[CCPAPurpose].h);
|
|
9248
9311
|
state.setCCPAConsentState(ccpaConsent);
|
|
9249
9312
|
}
|
|
@@ -10268,6 +10331,17 @@ var mParticle = (function () {
|
|
|
10268
10331
|
mappedKey: 'SnapchatConversions.ClickId',
|
|
10269
10332
|
output: IntegrationOutputs.CUSTOM_FLAGS
|
|
10270
10333
|
},
|
|
10334
|
+
// Pinterest
|
|
10335
|
+
// https://developers.pinterest.com/docs/track-conversions/track-conversions-in-the-api/
|
|
10336
|
+
// https://help.pinterest.com/en/business/article/pinterest-tag-parameters-and-cookies
|
|
10337
|
+
epik: {
|
|
10338
|
+
mappedKey: 'Pinterest.click_id',
|
|
10339
|
+
output: IntegrationOutputs.CUSTOM_FLAGS
|
|
10340
|
+
},
|
|
10341
|
+
_epik: {
|
|
10342
|
+
mappedKey: 'Pinterest.click_id',
|
|
10343
|
+
output: IntegrationOutputs.CUSTOM_FLAGS
|
|
10344
|
+
},
|
|
10271
10345
|
// Snapchat
|
|
10272
10346
|
// https://developers.snap.com/api/marketing-api/Conversions-API/UsingTheAPI#sending-click-id
|
|
10273
10347
|
_scid: {
|
|
@@ -10311,6 +10385,7 @@ var mParticle = (function () {
|
|
|
10311
10385
|
var queryParams = this.captureQueryParams() || {};
|
|
10312
10386
|
var cookies = this.captureCookies() || {};
|
|
10313
10387
|
var localStorage = this.captureLocalStorage() || {};
|
|
10388
|
+
this.applyPinterestRules(queryParams, localStorage, cookies);
|
|
10314
10389
|
// Facebook Rules
|
|
10315
10390
|
// Exclude _fbc if fbclid is present
|
|
10316
10391
|
// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc#retrieve-from-fbclid-url-query-parameter
|
|
@@ -10438,6 +10513,39 @@ var mParticle = (function () {
|
|
|
10438
10513
|
}
|
|
10439
10514
|
return mappedClickIds;
|
|
10440
10515
|
};
|
|
10516
|
+
IntegrationCapture.prototype.normalizePinterestClickId = function (clickIds) {
|
|
10517
|
+
// Deterministic tie-breaker when both aliases are present in the same source:
|
|
10518
|
+
// keep _epik and drop epik.
|
|
10519
|
+
if (!isEmpty(clickIds === null || clickIds === void 0 ? void 0 : clickIds['_epik']) && !isEmpty(clickIds === null || clickIds === void 0 ? void 0 : clickIds['epik'])) {
|
|
10520
|
+
delete clickIds['epik'];
|
|
10521
|
+
}
|
|
10522
|
+
};
|
|
10523
|
+
IntegrationCapture.prototype.hasPinterestAlias = function (clickIds) {
|
|
10524
|
+
return !isEmpty(clickIds === null || clickIds === void 0 ? void 0 : clickIds['epik']) || !isEmpty(clickIds === null || clickIds === void 0 ? void 0 : clickIds['_epik']);
|
|
10525
|
+
};
|
|
10526
|
+
IntegrationCapture.prototype.applyPinterestRules = function (queryParams, localStorage, cookies) {
|
|
10527
|
+
var _a, _b;
|
|
10528
|
+
this.normalizePinterestClickId(queryParams);
|
|
10529
|
+
this.normalizePinterestClickId(localStorage);
|
|
10530
|
+
this.normalizePinterestClickId(cookies);
|
|
10531
|
+
// Cross-source precedence: query params > localStorage > cookies.
|
|
10532
|
+
// Within the same source, prefer _epik when both aliases are present.
|
|
10533
|
+
if (this.hasPinterestAlias(queryParams) || this.hasPinterestAlias(localStorage) || this.hasPinterestAlias(cookies)) {
|
|
10534
|
+
(_a = this.clickIds) === null || _a === void 0 ? true : delete _a['epik'];
|
|
10535
|
+
(_b = this.clickIds) === null || _b === void 0 ? true : delete _b['_epik'];
|
|
10536
|
+
}
|
|
10537
|
+
if (this.hasPinterestAlias(queryParams)) {
|
|
10538
|
+
delete cookies['epik'];
|
|
10539
|
+
delete cookies['_epik'];
|
|
10540
|
+
delete localStorage['epik'];
|
|
10541
|
+
delete localStorage['_epik'];
|
|
10542
|
+
return;
|
|
10543
|
+
}
|
|
10544
|
+
if (this.hasPinterestAlias(localStorage)) {
|
|
10545
|
+
delete cookies['epik'];
|
|
10546
|
+
delete cookies['_epik'];
|
|
10547
|
+
}
|
|
10548
|
+
};
|
|
10441
10549
|
IntegrationCapture.prototype.applyProcessors = function (clickIds, url, timestamp) {
|
|
10442
10550
|
var _a;
|
|
10443
10551
|
var processedClickIds = {};
|
|
@@ -11134,7 +11242,7 @@ var mParticle = (function () {
|
|
|
11134
11242
|
if (!user) return;
|
|
11135
11243
|
if (this.flags.noTargeting) {
|
|
11136
11244
|
user.setUserAttribute(NO_TARGETING_ATTRIBUTE, true);
|
|
11137
|
-
} else if (user.getAllUserAttributes()
|
|
11245
|
+
} else if (hasOwnProp(user.getAllUserAttributes(), NO_TARGETING_ATTRIBUTE)) {
|
|
11138
11246
|
user.removeUserAttribute(NO_TARGETING_ATTRIBUTE);
|
|
11139
11247
|
}
|
|
11140
11248
|
};
|
|
@@ -12175,7 +12283,9 @@ var mParticle = (function () {
|
|
|
12175
12283
|
if (getFeatureFlag(AutoLogPageView)) {
|
|
12176
12284
|
if (!mpInstance._PageViewTracker) {
|
|
12177
12285
|
mpInstance.Logger.verbose('mParticle APV: [sdk-init] creating new PageViewTracker for this instance');
|
|
12178
|
-
mpInstance._PageViewTracker = new PageViewTracker(mpInstance
|
|
12286
|
+
mpInstance._PageViewTracker = new PageViewTracker(mpInstance, {
|
|
12287
|
+
isAutoPageView: true
|
|
12288
|
+
});
|
|
12179
12289
|
}
|
|
12180
12290
|
// The initial page view fires once per hard page load, not once per
|
|
12181
12291
|
// init(): the window flag survives the module re-evaluation Next.js
|
|
@@ -12185,7 +12295,9 @@ var mParticle = (function () {
|
|
|
12185
12295
|
mpInstance.Logger.verbose('mParticle APV: [sdk-init] initial page view already logged this page load, skipping');
|
|
12186
12296
|
} else {
|
|
12187
12297
|
markInitialPageViewFired();
|
|
12188
|
-
mpInstance._Events.logPageView(
|
|
12298
|
+
mpInstance._Events.logPageView({
|
|
12299
|
+
isAutoPageView: true
|
|
12300
|
+
});
|
|
12189
12301
|
}
|
|
12190
12302
|
mpInstance._PageViewTracker.init();
|
|
12191
12303
|
} else if (mpInstance._PageViewTracker) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Callback, SDKEventAttrs, SDKEventOptions, TransactionAttributes } from '@mparticle/web-sdk';
|
|
2
2
|
import { BaseEvent, SDKEvent, SDKEventCustomFlags, SDKImpression, SDKProduct, SDKPromotion } from './sdkRuntimeModels';
|
|
3
|
+
import { IPageViewOptions } from './pageViewTracker';
|
|
3
4
|
import { valueof } from './utils';
|
|
4
5
|
import { EventType, ProductActionType, PromotionActionType } from './types';
|
|
5
6
|
type EventHandlerFunction<T> = (element: HTMLLinkElement | HTMLFormElement) => T;
|
|
@@ -10,7 +11,7 @@ export interface IEvents {
|
|
|
10
11
|
logEvent(event: BaseEvent, eventOptions?: SDKEventOptions): void;
|
|
11
12
|
logImpressionEvent(impression: SDKImpression | SDKImpression[], attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags, eventOptions?: SDKEventOptions): void;
|
|
12
13
|
logOptOut(): void;
|
|
13
|
-
logPageView(): void;
|
|
14
|
+
logPageView(options?: IPageViewOptions): void;
|
|
14
15
|
logProductActionEvent(productActionType: valueof<typeof ProductActionType>, product: SDKProduct | SDKProduct[], attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags, transactionAttributes?: TransactionAttributes, eventOptions?: SDKEventOptions): void;
|
|
15
16
|
logPromotionEvent(promotionType: valueof<typeof PromotionActionType>, promotion: SDKPromotion | SDKPromotion[], attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags, eventOptions?: SDKEventOptions): void;
|
|
16
17
|
logPurchaseEvent(transactionAttributes: TransactionAttributes, product: SDKProduct | SDKProduct[], attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags): void;
|
|
@@ -65,6 +65,9 @@ export default class IntegrationCapture {
|
|
|
65
65
|
*/
|
|
66
66
|
getClickIdsAsIntegrationAttributes(): IntegrationAttributes;
|
|
67
67
|
private getClickIds;
|
|
68
|
+
private normalizePinterestClickId;
|
|
69
|
+
private hasPinterestAlias;
|
|
70
|
+
private applyPinterestRules;
|
|
68
71
|
private applyProcessors;
|
|
69
72
|
private filterMappings;
|
|
70
73
|
/**
|
|
@@ -12,12 +12,18 @@ interface IPageSnapshot {
|
|
|
12
12
|
interface IPageViewData extends IPageSnapshot {
|
|
13
13
|
hostname: string;
|
|
14
14
|
title: string;
|
|
15
|
+
isAutoPageView?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface IPageViewOptions {
|
|
18
|
+
isAutoPageView?: boolean;
|
|
15
19
|
}
|
|
16
20
|
export declare const allowedQueryParams: (href: string) => Dictionary<string>;
|
|
21
|
+
export declare const AUTO_PAGE_VIEW_ATTRIBUTE = "is_auto_page_view";
|
|
22
|
+
export declare const autoPageViewAttribute: (isAutoPageView?: boolean) => Dictionary<boolean>;
|
|
17
23
|
export declare const pageKey: (page: IPageSnapshot) => string;
|
|
18
24
|
export declare const isNewPage: (lastKey: string | null, candidateKey: string) => boolean;
|
|
19
25
|
export declare const supportsHistoryTracking: (win: Window | null) => boolean;
|
|
20
|
-
export declare const buildPageViewEvent: ({ params, hostname, title, path, }: IPageViewData) => BaseEvent;
|
|
26
|
+
export declare const buildPageViewEvent: ({ params, hostname, title, path, isAutoPageView, }: IPageViewData) => BaseEvent;
|
|
21
27
|
export declare const getActiveTracker: () => PageViewTracker | undefined;
|
|
22
28
|
export declare const hasInitialPageViewFired: () => boolean;
|
|
23
29
|
export declare const markInitialPageViewFired: () => void;
|
|
@@ -30,7 +36,8 @@ export declare class PageViewTracker {
|
|
|
30
36
|
private pendingNavigations;
|
|
31
37
|
private undoHistoryPatch;
|
|
32
38
|
private popStateListener;
|
|
33
|
-
|
|
39
|
+
private readonly isAutoPageView;
|
|
40
|
+
constructor(mpInstance: IMParticleWebSDKInstance, options?: IPageViewOptions);
|
|
34
41
|
get isActive(): boolean;
|
|
35
42
|
init(): void;
|
|
36
43
|
teardown(): void;
|
|
@@ -99,6 +99,7 @@ export declare const PerformanceMarkType: {
|
|
|
99
99
|
};
|
|
100
100
|
export declare function getMessageTypeFromEventType(eventType: string): number;
|
|
101
101
|
export declare function getEventCategoryFromCustomEventType(customEventType: string): number;
|
|
102
|
+
export declare function getIdentityTypeFromStoredKey(key: string): number | null;
|
|
102
103
|
export declare function getIdentityTypeFromBatchKey(key: string): number;
|
|
103
104
|
declare const _default: {
|
|
104
105
|
readonly MessageType: {
|
|
@@ -28,7 +28,7 @@ declare const replaceQuotesWithApostrophes: (value: string) => string;
|
|
|
28
28
|
declare const replaceMPID: (value: string, mpid: MPID) => string;
|
|
29
29
|
declare const replaceAmpWithAmpersand: (value: string) => string;
|
|
30
30
|
declare const createCookieSyncUrl: (mpid: MPID, pixelUrl: string, redirectUrl?: string, domain?: string, base64Mpid?: string) => string;
|
|
31
|
-
declare const toWebSafeBase64: (value: string) => string;
|
|
31
|
+
declare const toWebSafeBase64: (value: string) => string | undefined;
|
|
32
32
|
declare const returnConvertedBoolean: (data: string | boolean | number) => boolean;
|
|
33
33
|
declare const decoded: (s: string) => string;
|
|
34
34
|
declare const converted: (s: string) => string;
|
|
@@ -43,7 +43,8 @@ declare const isStringOrNumber: (value: any) => boolean;
|
|
|
43
43
|
declare const isEmpty: (value: Dictionary<any> | string | null | undefined) => boolean;
|
|
44
44
|
declare const mergeObjects: <T extends object>(...objects: T[]) => T;
|
|
45
45
|
declare const moveElementToEnd: <T>(array: T[], index: number) => T[];
|
|
46
|
-
declare const hasOwnProp: (obj: object, key:
|
|
46
|
+
declare const hasOwnProp: (obj: object, key: PropertyKey) => boolean;
|
|
47
|
+
declare const isReservedStoredPropertyName: (name: string) => boolean;
|
|
47
48
|
declare const queryStringParser: (url: string, keys?: string[]) => Dictionary<string>;
|
|
48
49
|
declare const getCookies: (keys?: string[]) => Dictionary<string>;
|
|
49
50
|
declare const getHref: () => string;
|
|
@@ -83,4 +84,4 @@ declare const obfuscateData: (value: any) => any;
|
|
|
83
84
|
declare const obfuscateDevData: (data: any, isDevelopmentMode?: boolean) => any;
|
|
84
85
|
declare function extend(...args: any[]): any;
|
|
85
86
|
declare const getErrorMessage: (e: unknown, fallback?: string) => string;
|
|
86
|
-
export { createCookieString, revertCookieString, createCookieSyncUrl, toWebSafeBase64, valueof, AttributeValue, converted, decoded, obfuscateDevData, filterDictionaryWithHash, findKeyInObject, generateDeprecationMessage, generateHash, generateUniqueId, getErrorMessage, getRampNumber, inArray, isObject, isStringOrNumber, obfuscateData, parseConfig, parseNumber, parseSettingsString, parseStringOrNumber, replaceCommasWithPipes, replacePipesWithCommas, replaceApostrophesWithQuotes, replaceQuotesWithApostrophes, returnConvertedBoolean, toDataPlanSlug, isString, isNumber, isFunction, isDataPlanSlug, isEmpty, isValidAttributeValue, isValidCustomFlagProperty, mergeObjects, moveElementToEnd, queryStringParser, hasOwnProp, getCookies, getHref, replaceMPID, replaceAmpWithAmpersand, extend, };
|
|
87
|
+
export { createCookieString, revertCookieString, createCookieSyncUrl, toWebSafeBase64, valueof, AttributeValue, converted, decoded, obfuscateDevData, filterDictionaryWithHash, findKeyInObject, generateDeprecationMessage, generateHash, generateUniqueId, getErrorMessage, getRampNumber, inArray, isObject, isStringOrNumber, obfuscateData, parseConfig, parseNumber, parseSettingsString, parseStringOrNumber, replaceCommasWithPipes, replacePipesWithCommas, replaceApostrophesWithQuotes, replaceQuotesWithApostrophes, returnConvertedBoolean, toDataPlanSlug, isString, isNumber, isFunction, isDataPlanSlug, isEmpty, isValidAttributeValue, isValidCustomFlagProperty, mergeObjects, moveElementToEnd, queryStringParser, hasOwnProp, isReservedStoredPropertyName, getCookies, getHref, replaceMPID, replaceAmpWithAmpersand, extend, };
|