@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.js CHANGED
@@ -204,7 +204,7 @@ var mParticle = (function () {
204
204
  Base64: Base64$1
205
205
  };
206
206
 
207
- var version = "3.6.2";
207
+ var version = "3.8.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.hasOwnProperty(prop) && prop.toLowerCase() === key.toLowerCase()) {
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.hasOwnProperty(key)) {
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 === '__proto__' || name === 'constructor' || name === 'prototype') {
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
- // if cache doesn't have the cacheKey, there is no valid cached identity
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.
@@ -3925,7 +3956,9 @@ var mParticle = (function () {
3925
3956
  }
3926
3957
  return mostRecentUser || null;
3927
3958
  } else {
3928
- return mpInstance.Identity.getUser(previousMpid);
3959
+ var currentUser = mParticleUser || mpInstance.Identity.getCurrentUser();
3960
+ var userDidNotChange = (currentUser === null || currentUser === void 0 ? void 0 : currentUser.getMPID()) === previousMpid;
3961
+ return userDidNotChange ? null : mpInstance.Identity.getUser(previousMpid);
3929
3962
  }
3930
3963
  }
3931
3964
  });
@@ -4223,57 +4256,65 @@ var mParticle = (function () {
4223
4256
  }
4224
4257
  pixelConfigurations.forEach(function (pixelSettings) {
4225
4258
  var _a, _b, _c;
4226
- // set requiresConsent to false to start each additional pixel configuration
4227
- // set to true only if filteringConsenRuleValues.values.length exists
4228
- var requiresConsent = false;
4229
- // Filtering rules as defined in UI
4230
- var filteringConsentRuleValues = pixelSettings.filteringConsentRuleValues,
4231
- pixelUrl = pixelSettings.pixelUrl,
4232
- redirectUrl = pixelSettings.redirectUrl,
4233
- moduleId = pixelSettings.moduleId,
4234
- settings = pixelSettings.settings,
4235
- // Tells you how often we should do a cookie sync (in days)
4236
- frequencyCap = pixelSettings.frequencyCap;
4237
- var values = (filteringConsentRuleValues || {}).values;
4238
- if (isEmpty(pixelUrl)) {
4239
- return;
4240
- }
4241
- if (!isEmpty(values)) {
4242
- requiresConsent = true;
4243
- }
4244
- // If MPID is new to cookies, we should not try to perform the cookie sync
4245
- // because a cookie sync can only occur once a user either consents or doesn't.
4246
- // we should not check if it's enabled if the user has a blank consent
4247
- if (requiresConsent && mpidIsNotInCookies) {
4248
- return;
4249
- }
4250
- // For Rokt, block cookie sync when noTargeting privacy flag is true
4251
- if (moduleId === PARTNER_MODULE_IDS.Rokt && mpInstance._CookieConsentManager.getNoTargeting()) {
4252
- return;
4253
- }
4254
- var isEnabledForUserConsent = mpInstance._Consent.isEnabledForUserConsent;
4255
- if (!isEnabledForUserConsent(filteringConsentRuleValues, mpInstance.Identity.getCurrentUser())) {
4256
- return;
4257
- }
4258
- var cookieSyncDates = (_b = (_a = persistence[mpid]) === null || _a === void 0 ? void 0 : _a.csd) !== null && _b !== void 0 ? _b : {};
4259
- var lastSyncDateForModule = cookieSyncDates[moduleId] || null;
4260
- if (!isLastSyncDateExpired(frequencyCap, lastSyncDateForModule)) {
4261
- return;
4259
+ try {
4260
+ // set requiresConsent to false to start each additional pixel configuration
4261
+ // set to true only if filteringConsenRuleValues.values.length exists
4262
+ var requiresConsent = false;
4263
+ // Filtering rules as defined in UI
4264
+ var filteringConsentRuleValues = pixelSettings.filteringConsentRuleValues,
4265
+ pixelUrl = pixelSettings.pixelUrl,
4266
+ redirectUrl = pixelSettings.redirectUrl,
4267
+ moduleId = pixelSettings.moduleId,
4268
+ settings = pixelSettings.settings,
4269
+ // Tells you how often we should do a cookie sync (in days)
4270
+ frequencyCap = pixelSettings.frequencyCap;
4271
+ var values = (filteringConsentRuleValues || {}).values;
4272
+ if (isEmpty(pixelUrl)) {
4273
+ return;
4274
+ }
4275
+ if (!isEmpty(values)) {
4276
+ requiresConsent = true;
4277
+ }
4278
+ // If MPID is new to cookies, we should not try to perform the cookie sync
4279
+ // because a cookie sync can only occur once a user either consents or doesn't.
4280
+ // we should not check if it's enabled if the user has a blank consent
4281
+ if (requiresConsent && mpidIsNotInCookies) {
4282
+ return;
4283
+ }
4284
+ // For Rokt, block cookie sync when noTargeting privacy flag is true
4285
+ if (moduleId === PARTNER_MODULE_IDS.Rokt && mpInstance._CookieConsentManager.getNoTargeting()) {
4286
+ return;
4287
+ }
4288
+ var isEnabledForUserConsent = mpInstance._Consent.isEnabledForUserConsent;
4289
+ if (!isEnabledForUserConsent(filteringConsentRuleValues, mpInstance.Identity.getCurrentUser())) {
4290
+ return;
4291
+ }
4292
+ var cookieSyncDates = (_b = (_a = persistence[mpid]) === null || _a === void 0 ? void 0 : _a.csd) !== null && _b !== void 0 ? _b : {};
4293
+ var lastSyncDateForModule = cookieSyncDates[moduleId] || null;
4294
+ if (!isLastSyncDateExpired(frequencyCap, lastSyncDateForModule)) {
4295
+ return;
4296
+ }
4297
+ // The Trade Desk requires a URL parameter for GDPR enabled users.
4298
+ // It is optional but to simplify the code, we add it for all Trade
4299
+ // // Desk cookie syncs.
4300
+ var domain = moduleId === PARTNER_MODULE_IDS.TradeDesk ? window.location.hostname : undefined;
4301
+ // Google Marketing Platform accepts a web-safe base64-encoded MPID via the
4302
+ // `google_hm` query parameter, but only for accounts provisioned for Google
4303
+ // Hosted Matching — Google returns errors otherwise. It is therefore gated
4304
+ // behind the opt-in `enableHmTag` setting (off by default), which the server
4305
+ // delivers as the string 'True' when the UI toggle is enabled.
4306
+ var enableHmTag = ((_c = settings === null || settings === void 0 ? void 0 : settings.enableHmTag) === null || _c === void 0 ? void 0 : _c.toLowerCase()) === 'true';
4307
+ var isDoubleClickModule = moduleId === PARTNER_MODULE_IDS.DoubleclickDFP;
4308
+ var usesHostedMatching = isDoubleClickModule && enableHmTag;
4309
+ var base64Mpid = usesHostedMatching ? toWebSafeBase64(mpid) : undefined;
4310
+ if (usesHostedMatching && !base64Mpid) {
4311
+ mpInstance.Logger.warning('Unable to base64 encode the current MPID; omitting the google_hm parameter from this cookie sync');
4312
+ }
4313
+ var fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain, base64Mpid);
4314
+ self.performCookieSync(fullUrl, moduleId.toString(), mpid, cookieSyncDates);
4315
+ } catch (e) {
4316
+ mpInstance.Logger.error('Error performing cookie sync: ' + e);
4262
4317
  }
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
4318
  });
4278
4319
  };
4279
4320
  // Private
@@ -5259,7 +5300,7 @@ var mParticle = (function () {
5259
5300
  }
5260
5301
  _this.syncPersistenceData();
5261
5302
  if (_this.persistenceData) {
5262
- if (_this.persistenceData[mpid]) {
5303
+ if (isObject(_this.persistenceData[mpid])) {
5263
5304
  _this.persistenceData[mpid][key] = value;
5264
5305
  } else {
5265
5306
  _this.persistenceData[mpid] = (_a = {}, _a[key] = value, _a);
@@ -6237,7 +6278,7 @@ var mParticle = (function () {
6237
6278
  if (csd) {
6238
6279
  var persistence = self.getPersistence();
6239
6280
  if (persistence) {
6240
- if (persistence[mpid]) {
6281
+ if (mpInstance._Helpers.isObject(persistence[mpid])) {
6241
6282
  persistence[mpid].csd = csd;
6242
6283
  } else {
6243
6284
  persistence[mpid] = {
@@ -6318,7 +6359,7 @@ var mParticle = (function () {
6318
6359
  }
6319
6360
  var persistence = self.getPersistence();
6320
6361
  if (persistence) {
6321
- if (!persistence[mpid]) {
6362
+ if (!mpInstance._Helpers.isObject(persistence[mpid])) {
6322
6363
  persistence[mpid] = {};
6323
6364
  }
6324
6365
  if (!persistence[mpid].fst) {
@@ -6356,7 +6397,7 @@ var mParticle = (function () {
6356
6397
  time = new Date().getTime();
6357
6398
  }
6358
6399
  var persistence = self.getPersistence();
6359
- if (persistence && persistence[mpid]) {
6400
+ if (persistence && mpInstance._Helpers.isObject(persistence[mpid])) {
6360
6401
  persistence[mpid].lst = time;
6361
6402
  self.savePersistence(persistence);
6362
6403
  }
@@ -6445,6 +6486,14 @@ var mParticle = (function () {
6445
6486
  var allowedQueryParams = function allowedQueryParams(href) {
6446
6487
  return queryStringParser(href, ALLOWED_QUERY_PARAMS);
6447
6488
  };
6489
+ var AUTO_PAGE_VIEW_ATTRIBUTE = 'is_auto_page_view';
6490
+ // Absent rather than false on a manual page view, so the attribute is only ever
6491
+ // added by the automatic emitters. Shared by both of them so the key and that
6492
+ // rule have one definition instead of two that can drift.
6493
+ var autoPageViewAttribute = function autoPageViewAttribute(isAutoPageView) {
6494
+ var _a;
6495
+ return isAutoPageView ? (_a = {}, _a[AUTO_PAGE_VIEW_ATTRIBUTE] = true, _a) : {};
6496
+ };
6448
6497
  // The captured params, in allowlist order. Ordering comes from the constant
6449
6498
  // rather than a sort: it is deterministic without needing a comparator, and it
6450
6499
  // does not depend on the object's insertion order, so reordering the query string
@@ -6492,18 +6541,19 @@ var mParticle = (function () {
6492
6541
  var params = _a.params,
6493
6542
  hostname = _a.hostname,
6494
6543
  title = _a.title,
6495
- path = _a.path;
6544
+ path = _a.path,
6545
+ isAutoPageView = _a.isAutoPageView;
6496
6546
  return {
6497
6547
  messageType: MessageType$1.PageView,
6498
6548
  name: 'PageView',
6499
6549
  // Params spread first, then the core fields by name, so a core field always
6500
6550
  // wins. No allowlist entry collides with hostname/title/path today; naming
6501
6551
  // them here is what keeps a later addition from silently overwriting one.
6502
- data: __assign(__assign({}, params), {
6552
+ data: __assign(__assign(__assign({}, params), {
6503
6553
  hostname: hostname,
6504
6554
  title: title,
6505
6555
  path: path
6506
- }),
6556
+ }), autoPageViewAttribute(isAutoPageView)),
6507
6557
  eventType: EventType.Unknown
6508
6558
  };
6509
6559
  };
@@ -6663,13 +6713,14 @@ var mParticle = (function () {
6663
6713
  // Tracker
6664
6714
  // ---------------------------------------------------------------------------
6665
6715
  var PageViewTracker = /** @class */function () {
6666
- function PageViewTracker(mpInstance) {
6716
+ function PageViewTracker(mpInstance, options) {
6667
6717
  this.lastPage = null;
6668
6718
  this.active = false;
6669
6719
  this.pendingNavigations = [];
6670
6720
  this.undoHistoryPatch = null;
6671
6721
  this.popStateListener = null;
6672
6722
  this.mpInstance = mpInstance;
6723
+ this.isAutoPageView = !!(options && options.isAutoPageView);
6673
6724
  }
6674
6725
  Object.defineProperty(PageViewTracker.prototype, "isActive", {
6675
6726
  // True while this tracker owns the history patch and is listening for
@@ -6812,7 +6863,8 @@ var mParticle = (function () {
6812
6863
  var title = window.document.title;
6813
6864
  var event = buildPageViewEvent(__assign(__assign({}, page), {
6814
6865
  hostname: window.location.hostname,
6815
- title: title
6866
+ title: title,
6867
+ isAutoPageView: this.isAutoPageView
6816
6868
  }));
6817
6869
  this.log("[fire] deferred flush -> _Events.logEvent(PageView) (page: ".concat(describePage(page), ", title: ").concat(title, ")"));
6818
6870
  this.mpInstance._Events.logEvent(event);
@@ -6904,14 +6956,14 @@ var mParticle = (function () {
6904
6956
  // come from PageViewTracker instead, so both emitters attach the same
6905
6957
  // allowlisted query params — and this is the one that matters for campaign
6906
6958
  // attribution, since utm_*/gclid live on the entry URL.
6907
- this.logPageView = function () {
6959
+ this.logPageView = function (options) {
6908
6960
  self.logEvent({
6909
6961
  messageType: Types.MessageType.PageView,
6910
6962
  name: 'PageView',
6911
- data: __assign(__assign({}, allowedQueryParams(getHref())), {
6963
+ data: __assign(__assign(__assign({}, allowedQueryParams(getHref())), {
6912
6964
  hostname: window.location.hostname,
6913
6965
  title: window.document.title
6914
- }),
6966
+ }), autoPageViewAttribute(options && options.isAutoPageView)),
6915
6967
  eventType: Types.EventType.Unknown
6916
6968
  });
6917
6969
  };
@@ -7095,7 +7147,7 @@ var mParticle = (function () {
7095
7147
  return userAttributesCopy;
7096
7148
  }
7097
7149
  for (var prop in userAttributes) {
7098
- if (!userAttributes.hasOwnProperty(prop) || !isAttributeKeyAllowed(kitBlocker, prop)) {
7150
+ if (!hasOwnProp(userAttributes, prop) || isReservedStoredPropertyName(prop) || !isAttributeKeyAllowed(kitBlocker, prop)) {
7099
7151
  continue;
7100
7152
  }
7101
7153
  userAttributesCopy[prop] = copyUserAttributeValue(userAttributes[prop]);
@@ -7105,21 +7157,27 @@ var mParticle = (function () {
7105
7157
  function buildUserAttributeLists(userAttributes, kitBlocker) {
7106
7158
  var userAttributesLists = {};
7107
7159
  for (var key in userAttributes) {
7108
- if (!userAttributes.hasOwnProperty(key) || !Array.isArray(userAttributes[key]) || !isAttributeKeyAllowed(kitBlocker, key)) {
7160
+ if (!hasOwnProp(userAttributes, key) || isReservedStoredPropertyName(key) || !Array.isArray(userAttributes[key]) || !isAttributeKeyAllowed(kitBlocker, key)) {
7109
7161
  continue;
7110
7162
  }
7111
7163
  userAttributesLists[key] = userAttributes[key].slice();
7112
7164
  }
7113
7165
  return userAttributesLists;
7114
7166
  }
7115
- function buildFilteredUserIdentities(identities, kitBlocker, parseNumber) {
7167
+ function buildFilteredUserIdentities(identities, kitBlocker) {
7116
7168
  var currentUserIdentities = {};
7117
7169
  var identitiesByType = identities;
7118
7170
  for (var identityType in identitiesByType) {
7119
- if (!identitiesByType.hasOwnProperty(identityType)) {
7171
+ if (!hasOwnProp(identitiesByType, identityType)) {
7172
+ continue;
7173
+ }
7174
+ var storedIdentityType = getIdentityTypeFromStoredKey(identityType);
7175
+ // Must be `=== null`: IdentityType.Other is 0, so a falsy check would
7176
+ // drop a valid stored Other identity.
7177
+ if (storedIdentityType === null) {
7120
7178
  continue;
7121
7179
  }
7122
- var identityName = Types.IdentityType.getIdentityName(parseNumber(identityType));
7180
+ var identityName = Types.IdentityType.getIdentityName(storedIdentityType);
7123
7181
  if (!isIdentityAllowed(kitBlocker, identityName)) {
7124
7182
  continue;
7125
7183
  }
@@ -7134,7 +7192,7 @@ var mParticle = (function () {
7134
7192
  }
7135
7193
  return {
7136
7194
  getUserIdentities: function getUserIdentities() {
7137
- var currentUserIdentities = buildFilteredUserIdentities(mpInstance._Store.getUserIdentities(mpid), kitBlocker, mpInstance._Helpers.parseNumber);
7195
+ var currentUserIdentities = buildFilteredUserIdentities(mpInstance._Store.getUserIdentities(mpid), kitBlocker);
7138
7196
  currentUserIdentities = mpInstance._Helpers.filterUserIdentitiesForForwarders(currentUserIdentities, forwarder.userIdentityFilters);
7139
7197
  return {
7140
7198
  userIdentities: currentUserIdentities
@@ -7245,7 +7303,7 @@ var mParticle = (function () {
7245
7303
  }
7246
7304
  function userAttributesMatchFilter(userAttributes, filterObject) {
7247
7305
  for (var attrName in userAttributes) {
7248
- if (!userAttributes.hasOwnProperty(attrName)) {
7306
+ if (!hasOwnProp(userAttributes, attrName)) {
7249
7307
  continue;
7250
7308
  }
7251
7309
  var attrHash = KitFilterHelper.hashAttributeConditionalForwarding(attrName);
@@ -8596,9 +8654,16 @@ var mParticle = (function () {
8596
8654
  var currentUserIdentities = {};
8597
8655
  var identities = mpInstance._Store.getUserIdentities(mpid);
8598
8656
  for (var identityType in identities) {
8599
- if (identities.hasOwnProperty(identityType)) {
8600
- currentUserIdentities[Types.IdentityType.getIdentityName(mpInstance._Helpers.parseNumber(identityType))] = identities[identityType];
8657
+ if (!hasOwnProp(identities, identityType)) {
8658
+ continue;
8601
8659
  }
8660
+ var storedIdentityType = getIdentityTypeFromStoredKey(identityType);
8661
+ // Must be `=== null`: IdentityType.Other is 0, so a falsy
8662
+ // check would drop a valid stored Other identity.
8663
+ if (storedIdentityType === null) {
8664
+ continue;
8665
+ }
8666
+ currentUserIdentities[Types.IdentityType.getIdentityName(storedIdentityType)] = identities[identityType];
8602
8667
  }
8603
8668
  return {
8604
8669
  userIdentities: currentUserIdentities
@@ -8727,7 +8792,7 @@ var mParticle = (function () {
8727
8792
  }
8728
8793
  var deletedUAKeyCopy = userAttributes[key] ? userAttributes[key].toString() : null;
8729
8794
  delete userAttributes[key];
8730
- if (cookies && cookies[mpid]) {
8795
+ if (cookies && isObject(cookies[mpid])) {
8731
8796
  cookies[mpid].ua = userAttributes;
8732
8797
  mpInstance._Persistence.savePersistence(cookies);
8733
8798
  }
@@ -8810,7 +8875,7 @@ var mParticle = (function () {
8810
8875
  mpInstance._Forwarders.initForwarders(self.IdentityAPI.getCurrentUser().getUserIdentities().userIdentities, mpInstance._APIClient.prepareForwardingStats);
8811
8876
  if (userAttributes) {
8812
8877
  for (var prop in userAttributes) {
8813
- if (userAttributes.hasOwnProperty(prop)) {
8878
+ if (hasOwnProp(userAttributes, prop)) {
8814
8879
  mpInstance._Forwarders.handleForwarderUserAttributes('removeUserAttribute', prop, null);
8815
8880
  }
8816
8881
  this.removeUserAttribute(prop);
@@ -8828,7 +8893,7 @@ var mParticle = (function () {
8828
8893
  var userAttributesLists = {};
8829
8894
  userAttributes = this.getAllUserAttributes();
8830
8895
  for (var key in userAttributes) {
8831
- if (userAttributes.hasOwnProperty(key) && Array.isArray(userAttributes[key])) {
8896
+ if (hasOwnProp(userAttributes, key) && !isReservedStoredPropertyName(key) && Array.isArray(userAttributes[key])) {
8832
8897
  userAttributesLists[key] = userAttributes[key].slice();
8833
8898
  }
8834
8899
  }
@@ -8845,7 +8910,7 @@ var mParticle = (function () {
8845
8910
  var userAttributes = getUserAttributes(mpid);
8846
8911
  if (userAttributes) {
8847
8912
  for (var prop in userAttributes) {
8848
- if (userAttributes.hasOwnProperty(prop)) {
8913
+ if (hasOwnProp(userAttributes, prop) && !isReservedStoredPropertyName(prop)) {
8849
8914
  var attrValue = userAttributes[prop];
8850
8915
  if (Array.isArray(attrValue)) {
8851
8916
  userAttributesCopy[prop] = attrValue.slice();
@@ -8984,7 +9049,7 @@ var mParticle = (function () {
8984
9049
  }
8985
9050
  if (callback) {
8986
9051
  var callbackCode = identityResponse.status === 0 ? HTTPCodes$2.noHttpCoverage : identityResponse.status;
8987
- mpInstance._Helpers.invokeCallback(callback, callbackCode, identityApiResult || null, newUser);
9052
+ mpInstance._Helpers.invokeCallback(callback, callbackCode, identityApiResult || null, newUser, previousMPID);
8988
9053
  } else if (identityApiResult && !isEmpty(identityApiResult.errors)) {
8989
9054
  // https://go.mparticle.com/work/SQDSDKS-6500
8990
9055
  mpInstance.Logger.error('Received HTTP response code of ' + identityResponse.status + ' - ' + identityApiResult.errors[0].message);
@@ -9236,14 +9301,14 @@ var mParticle = (function () {
9236
9301
  var state = self.createConsentState();
9237
9302
  if (json.gdpr) {
9238
9303
  for (var purpose in json.gdpr) {
9239
- if (json.gdpr.hasOwnProperty(purpose)) {
9304
+ if (hasOwnProp(json.gdpr, purpose)) {
9240
9305
  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
9306
  state.addGDPRConsentState(purpose, gdprConsent);
9242
9307
  }
9243
9308
  }
9244
9309
  }
9245
9310
  if (json.ccpa) {
9246
- if (json.ccpa.hasOwnProperty(CCPAPurpose)) {
9311
+ if (hasOwnProp(json.ccpa, CCPAPurpose)) {
9247
9312
  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
9313
  state.setCCPAConsentState(ccpaConsent);
9249
9314
  }
@@ -10268,6 +10333,17 @@ var mParticle = (function () {
10268
10333
  mappedKey: 'SnapchatConversions.ClickId',
10269
10334
  output: IntegrationOutputs.CUSTOM_FLAGS
10270
10335
  },
10336
+ // Pinterest
10337
+ // https://developers.pinterest.com/docs/track-conversions/track-conversions-in-the-api/
10338
+ // https://help.pinterest.com/en/business/article/pinterest-tag-parameters-and-cookies
10339
+ epik: {
10340
+ mappedKey: 'Pinterest.click_id',
10341
+ output: IntegrationOutputs.CUSTOM_FLAGS
10342
+ },
10343
+ _epik: {
10344
+ mappedKey: 'Pinterest.click_id',
10345
+ output: IntegrationOutputs.CUSTOM_FLAGS
10346
+ },
10271
10347
  // Snapchat
10272
10348
  // https://developers.snap.com/api/marketing-api/Conversions-API/UsingTheAPI#sending-click-id
10273
10349
  _scid: {
@@ -10311,6 +10387,7 @@ var mParticle = (function () {
10311
10387
  var queryParams = this.captureQueryParams() || {};
10312
10388
  var cookies = this.captureCookies() || {};
10313
10389
  var localStorage = this.captureLocalStorage() || {};
10390
+ this.applyPinterestRules(queryParams, localStorage, cookies);
10314
10391
  // Facebook Rules
10315
10392
  // Exclude _fbc if fbclid is present
10316
10393
  // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc#retrieve-from-fbclid-url-query-parameter
@@ -10438,6 +10515,39 @@ var mParticle = (function () {
10438
10515
  }
10439
10516
  return mappedClickIds;
10440
10517
  };
10518
+ IntegrationCapture.prototype.normalizePinterestClickId = function (clickIds) {
10519
+ // Deterministic tie-breaker when both aliases are present in the same source:
10520
+ // keep _epik and drop epik.
10521
+ if (!isEmpty(clickIds === null || clickIds === void 0 ? void 0 : clickIds['_epik']) && !isEmpty(clickIds === null || clickIds === void 0 ? void 0 : clickIds['epik'])) {
10522
+ delete clickIds['epik'];
10523
+ }
10524
+ };
10525
+ IntegrationCapture.prototype.hasPinterestAlias = function (clickIds) {
10526
+ return !isEmpty(clickIds === null || clickIds === void 0 ? void 0 : clickIds['epik']) || !isEmpty(clickIds === null || clickIds === void 0 ? void 0 : clickIds['_epik']);
10527
+ };
10528
+ IntegrationCapture.prototype.applyPinterestRules = function (queryParams, localStorage, cookies) {
10529
+ var _a, _b;
10530
+ this.normalizePinterestClickId(queryParams);
10531
+ this.normalizePinterestClickId(localStorage);
10532
+ this.normalizePinterestClickId(cookies);
10533
+ // Cross-source precedence: query params > localStorage > cookies.
10534
+ // Within the same source, prefer _epik when both aliases are present.
10535
+ if (this.hasPinterestAlias(queryParams) || this.hasPinterestAlias(localStorage) || this.hasPinterestAlias(cookies)) {
10536
+ (_a = this.clickIds) === null || _a === void 0 ? true : delete _a['epik'];
10537
+ (_b = this.clickIds) === null || _b === void 0 ? true : delete _b['_epik'];
10538
+ }
10539
+ if (this.hasPinterestAlias(queryParams)) {
10540
+ delete cookies['epik'];
10541
+ delete cookies['_epik'];
10542
+ delete localStorage['epik'];
10543
+ delete localStorage['_epik'];
10544
+ return;
10545
+ }
10546
+ if (this.hasPinterestAlias(localStorage)) {
10547
+ delete cookies['epik'];
10548
+ delete cookies['_epik'];
10549
+ }
10550
+ };
10441
10551
  IntegrationCapture.prototype.applyProcessors = function (clickIds, url, timestamp) {
10442
10552
  var _a;
10443
10553
  var processedClickIds = {};
@@ -11134,7 +11244,7 @@ var mParticle = (function () {
11134
11244
  if (!user) return;
11135
11245
  if (this.flags.noTargeting) {
11136
11246
  user.setUserAttribute(NO_TARGETING_ATTRIBUTE, true);
11137
- } else if (user.getAllUserAttributes().hasOwnProperty(NO_TARGETING_ATTRIBUTE)) {
11247
+ } else if (hasOwnProp(user.getAllUserAttributes(), NO_TARGETING_ATTRIBUTE)) {
11138
11248
  user.removeUserAttribute(NO_TARGETING_ATTRIBUTE);
11139
11249
  }
11140
11250
  };
@@ -12175,7 +12285,9 @@ var mParticle = (function () {
12175
12285
  if (getFeatureFlag(AutoLogPageView)) {
12176
12286
  if (!mpInstance._PageViewTracker) {
12177
12287
  mpInstance.Logger.verbose('mParticle APV: [sdk-init] creating new PageViewTracker for this instance');
12178
- mpInstance._PageViewTracker = new PageViewTracker(mpInstance);
12288
+ mpInstance._PageViewTracker = new PageViewTracker(mpInstance, {
12289
+ isAutoPageView: true
12290
+ });
12179
12291
  }
12180
12292
  // The initial page view fires once per hard page load, not once per
12181
12293
  // init(): the window flag survives the module re-evaluation Next.js
@@ -12185,7 +12297,9 @@ var mParticle = (function () {
12185
12297
  mpInstance.Logger.verbose('mParticle APV: [sdk-init] initial page view already logged this page load, skipping');
12186
12298
  } else {
12187
12299
  markInitialPageViewFired();
12188
- mpInstance._Events.logPageView();
12300
+ mpInstance._Events.logPageView({
12301
+ isAutoPageView: true
12302
+ });
12189
12303
  }
12190
12304
  mpInstance._PageViewTracker.init();
12191
12305
  } 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
- constructor(mpInstance: IMParticleWebSDKInstance);
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: {