@mparticle/web-sdk 2.50.1 → 2.52.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
@@ -203,7 +203,7 @@ var mParticle = (function () {
203
203
  Base64: Base64$1
204
204
  };
205
205
 
206
- var version = "2.50.1";
206
+ var version = "2.52.0";
207
207
 
208
208
  var Constants = {
209
209
  sdkVersion: version,
@@ -667,12 +667,17 @@ var mParticle = (function () {
667
667
  var replaceAmpWithAmpersand = function replaceAmpWithAmpersand(value) {
668
668
  return value.replace(/&/g, '&');
669
669
  };
670
- var createCookieSyncUrl = function createCookieSyncUrl(mpid, pixelUrl, redirectUrl) {
670
+ var createCookieSyncUrl = function createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain) {
671
671
  var modifiedPixelUrl = replaceAmpWithAmpersand(pixelUrl);
672
672
  var modifiedDirectUrl = redirectUrl ? replaceAmpWithAmpersand(redirectUrl) : null;
673
673
  var url = replaceMPID(modifiedPixelUrl, mpid);
674
674
  var redirect = modifiedDirectUrl ? replaceMPID(modifiedDirectUrl, mpid) : '';
675
- return url + encodeURIComponent(redirect);
675
+ var fullUrl = url + encodeURIComponent(redirect);
676
+ if (domain) {
677
+ var separator = fullUrl.includes('?') ? '&' : '?';
678
+ fullUrl += "".concat(separator, "domain=").concat(domain);
679
+ }
680
+ return fullUrl;
676
681
  };
677
682
  // FIXME: REFACTOR for V3
678
683
  // only used in store.js to sanitize server-side formatting of
@@ -3182,6 +3187,16 @@ var mParticle = (function () {
3182
3187
  if ((options = arguments[i]) != null) {
3183
3188
  // Extend the base object
3184
3189
  for (name in options) {
3190
+ // Prevent prototype pollution
3191
+ // https://github.com/advisories/GHSA-jf85-cpcp-j695
3192
+ if (name === '__proto__' || name === 'constructor' || name === 'prototype') {
3193
+ continue;
3194
+ }
3195
+
3196
+ // Only copy own properties
3197
+ if (!Object.prototype.hasOwnProperty.call(options, name)) {
3198
+ continue;
3199
+ }
3185
3200
  src = target[name];
3186
3201
  copy = options[name];
3187
3202
 
@@ -3464,6 +3479,15 @@ var mParticle = (function () {
3464
3479
  var Messages$7 = Constants.Messages;
3465
3480
  var InformationMessages = Messages$7.InformationMessages;
3466
3481
  var DAYS_IN_MILLISECONDS = 1000 * 60 * 60 * 24;
3482
+ // Partner module IDs for cookie sync configurations
3483
+ var PARTNER_MODULE_IDS = {
3484
+ AdobeEventForwarder: 11,
3485
+ DoubleclickDFP: 41,
3486
+ AppNexus: 50,
3487
+ Lotame: 58,
3488
+ TradeDesk: 103,
3489
+ VerizonMedia: 155
3490
+ };
3467
3491
  function CookieSyncManager(mpInstance) {
3468
3492
  var self = this;
3469
3493
  // Public
@@ -3512,8 +3536,12 @@ var mParticle = (function () {
3512
3536
  if (!isLastSyncDateExpired(frequencyCap, lastSyncDateForModule)) {
3513
3537
  return;
3514
3538
  }
3515
- // Url for cookie sync pixel
3516
- var fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl);
3539
+ // The Trade Desk requires a URL parameter for GDPR enabled users.
3540
+ // It is optional but to simplify the code, we add it for all Trade
3541
+ // // Desk cookie syncs.
3542
+ var domain = moduleId === PARTNER_MODULE_IDS.TradeDesk ? window.location.hostname : undefined;
3543
+ // Add domain parameter for Trade Desk
3544
+ var fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain);
3517
3545
  self.performCookieSync(fullUrl, moduleId.toString(), mpid, cookieSyncDates);
3518
3546
  });
3519
3547
  };
@@ -3700,17 +3728,20 @@ var mParticle = (function () {
3700
3728
  var self = this;
3701
3729
  this.initialize = function () {
3702
3730
  if (mpInstance._Store.sessionId) {
3703
- var sessionTimeoutInMilliseconds = mpInstance._Store.SDKConfig.sessionTimeout * 60000;
3704
- if (new Date() > new Date(mpInstance._Store.dateLastEventSent.getTime() + sessionTimeoutInMilliseconds)) {
3731
+ var _a = mpInstance._Store,
3732
+ dateLastEventSent = _a.dateLastEventSent,
3733
+ SDKConfig = _a.SDKConfig;
3734
+ var sessionTimeout = SDKConfig.sessionTimeout;
3735
+ if (hasSessionTimedOut(dateLastEventSent === null || dateLastEventSent === void 0 ? void 0 : dateLastEventSent.getTime(), sessionTimeout)) {
3705
3736
  self.endSession();
3706
3737
  self.startNewSession();
3707
3738
  } else {
3708
3739
  // https://go.mparticle.com/work/SQDSDKS-6045
3709
3740
  // https://go.mparticle.com/work/SQDSDKS-6323
3710
3741
  var currentUser = mpInstance.Identity.getCurrentUser();
3711
- var sdkIdentityRequest = mpInstance._Store.SDKConfig.identifyRequest;
3742
+ var sdkIdentityRequest = SDKConfig.identifyRequest;
3712
3743
  if (hasIdentityRequestChanged(currentUser, sdkIdentityRequest)) {
3713
- mpInstance.Identity.identify(mpInstance._Store.SDKConfig.identifyRequest, mpInstance._Store.SDKConfig.identityCallback);
3744
+ mpInstance.Identity.identify(sdkIdentityRequest, SDKConfig.identityCallback);
3714
3745
  mpInstance._Store.identifyCalled = true;
3715
3746
  mpInstance._Store.SDKConfig.identityCallback = null;
3716
3747
  }
@@ -3754,14 +3785,10 @@ var mParticle = (function () {
3754
3785
  }
3755
3786
  };
3756
3787
  this.endSession = function (override) {
3757
- var _a, _b, _c, _d, _e;
3788
+ var _a, _b, _c, _d;
3758
3789
  mpInstance.Logger.verbose(Messages$6.InformationMessages.StartingEndSession);
3759
3790
  if (override) {
3760
- mpInstance._Events.logEvent({
3761
- messageType: Types.MessageType.SessionEnd
3762
- });
3763
- mpInstance._Store.nullifySession();
3764
- (_a = mpInstance._timeOnSiteTimer) === null || _a === void 0 ? void 0 : _a.resetTimer();
3791
+ performSessionEnd();
3765
3792
  return;
3766
3793
  }
3767
3794
  if (!mpInstance._Helpers.canLog()) {
@@ -3770,36 +3797,28 @@ var mParticle = (function () {
3770
3797
  // - the devToken is undefined
3771
3798
  // - webviewBridgeEnabled is set to false
3772
3799
  mpInstance.Logger.verbose(Messages$6.InformationMessages.AbandonEndSession);
3773
- (_b = mpInstance._timeOnSiteTimer) === null || _b === void 0 ? void 0 : _b.resetTimer();
3800
+ (_a = mpInstance._timeOnSiteTimer) === null || _a === void 0 ? void 0 : _a.resetTimer();
3774
3801
  return;
3775
3802
  }
3776
- var sessionTimeoutInMilliseconds;
3777
- var timeSinceLastEventSent;
3778
3803
  var cookies = mpInstance._Persistence.getPersistence();
3779
3804
  if (!cookies || cookies.gs && !cookies.gs.sid) {
3780
3805
  mpInstance.Logger.verbose(Messages$6.InformationMessages.NoSessionToEnd);
3781
- (_c = mpInstance._timeOnSiteTimer) === null || _c === void 0 ? void 0 : _c.resetTimer();
3806
+ (_b = mpInstance._timeOnSiteTimer) === null || _b === void 0 ? void 0 : _b.resetTimer();
3782
3807
  return;
3783
3808
  }
3784
3809
  // sessionId is not equal to cookies.sid if cookies.sid is changed in another tab
3785
3810
  if (cookies.gs.sid && mpInstance._Store.sessionId !== cookies.gs.sid) {
3786
3811
  mpInstance._Store.sessionId = cookies.gs.sid;
3787
3812
  }
3788
- if ((_d = cookies === null || cookies === void 0 ? void 0 : cookies.gs) === null || _d === void 0 ? void 0 : _d.les) {
3789
- sessionTimeoutInMilliseconds = mpInstance._Store.SDKConfig.sessionTimeout * 60000;
3790
- var newDate = new Date().getTime();
3791
- timeSinceLastEventSent = newDate - cookies.gs.les;
3792
- if (timeSinceLastEventSent < sessionTimeoutInMilliseconds) {
3793
- self.setSessionTimer();
3813
+ if ((_c = cookies === null || cookies === void 0 ? void 0 : cookies.gs) === null || _c === void 0 ? void 0 : _c.les) {
3814
+ var sessionTimeout = mpInstance._Store.SDKConfig.sessionTimeout;
3815
+ if (hasSessionTimedOut(cookies.gs.les, sessionTimeout)) {
3816
+ performSessionEnd();
3794
3817
  } else {
3795
- mpInstance._Events.logEvent({
3796
- messageType: Types.MessageType.SessionEnd
3797
- });
3798
- mpInstance._Store.sessionStartDate = null;
3799
- mpInstance._Store.nullifySession();
3818
+ self.setSessionTimer();
3819
+ (_d = mpInstance._timeOnSiteTimer) === null || _d === void 0 ? void 0 : _d.resetTimer();
3800
3820
  }
3801
3821
  }
3802
- (_e = mpInstance._timeOnSiteTimer) === null || _e === void 0 ? void 0 : _e.resetTimer();
3803
3822
  };
3804
3823
  this.setSessionTimer = function () {
3805
3824
  var sessionTimeoutInMilliseconds = mpInstance._Store.SDKConfig.sessionTimeout * 60000;
@@ -3832,6 +3851,34 @@ var mParticle = (function () {
3832
3851
  }
3833
3852
  }
3834
3853
  };
3854
+ /**
3855
+ * Checks if the session has expired based on the last event timestamp
3856
+ * @param lastEventTimestamp - Unix timestamp in milliseconds of the last event
3857
+ * @param sessionTimeout - Session timeout in minutes
3858
+ * @returns true if the session has expired, false otherwise
3859
+ */
3860
+ function hasSessionTimedOut(lastEventTimestamp, sessionTimeout) {
3861
+ if (!lastEventTimestamp || !sessionTimeout || sessionTimeout <= 0) {
3862
+ return false;
3863
+ }
3864
+ var sessionTimeoutInMilliseconds = sessionTimeout * 60000;
3865
+ var timeSinceLastEvent = Date.now() - lastEventTimestamp;
3866
+ return timeSinceLastEvent >= sessionTimeoutInMilliseconds;
3867
+ }
3868
+ /**
3869
+ * Performs session end operations:
3870
+ * - Logs a SessionEnd event
3871
+ * - Nullifies the session ID and related data
3872
+ * - Resets the time-on-site timer
3873
+ */
3874
+ function performSessionEnd() {
3875
+ var _a;
3876
+ mpInstance._Events.logEvent({
3877
+ messageType: Types.MessageType.SessionEnd
3878
+ });
3879
+ mpInstance._Store.nullifySession();
3880
+ (_a = mpInstance._timeOnSiteTimer) === null || _a === void 0 ? void 0 : _a.resetTimer();
3881
+ }
3835
3882
  }
3836
3883
 
3837
3884
  var Messages$5 = Constants.Messages;
@@ -4692,6 +4739,7 @@ var mParticle = (function () {
4692
4739
  this.nullifySession = function () {
4693
4740
  _this.sessionId = null;
4694
4741
  _this.dateLastEventSent = null;
4742
+ _this.sessionStartDate = null;
4695
4743
  _this.sessionAttributes = {};
4696
4744
  _this.localSessionAttributes = {};
4697
4745
  mpInstance._Persistence.update();
@@ -7352,7 +7400,8 @@ var mParticle = (function () {
7352
7400
  DestinationMpid: aliasRequest.destinationMpid,
7353
7401
  SourceMpid: aliasRequest.sourceMpid,
7354
7402
  StartUnixtimeMs: aliasRequest.startTime,
7355
- EndUnixtimeMs: aliasRequest.endTime
7403
+ EndUnixtimeMs: aliasRequest.endTime,
7404
+ Scope: aliasRequest.scope
7356
7405
  };
7357
7406
  },
7358
7407
  convertToNative: function convertToNative(identityApiData) {
@@ -7652,7 +7701,7 @@ var mParticle = (function () {
7652
7701
  after applying this adjustment it will be impossible to create an aliasRequest passes the aliasUsers()
7653
7702
  validation that the startTime must be less than the endTime
7654
7703
  */
7655
- createAliasRequest: function createAliasRequest(sourceUser, destinationUser) {
7704
+ createAliasRequest: function createAliasRequest(sourceUser, destinationUser, scope) {
7656
7705
  try {
7657
7706
  if (!destinationUser || !sourceUser) {
7658
7707
  mpInstance.Logger.error("'destinationUser' and 'sourceUser' must both be present");
@@ -7679,7 +7728,8 @@ var mParticle = (function () {
7679
7728
  destinationMpid: destinationUser.getMPID(),
7680
7729
  sourceMpid: sourceUser.getMPID(),
7681
7730
  startTime: startTime,
7682
- endTime: endTime
7731
+ endTime: endTime,
7732
+ scope: scope || 'device'
7683
7733
  };
7684
7734
  } catch (e) {
7685
7735
  mpInstance.Logger.error('There was a problem with creating an alias request: ' + e);
@@ -9399,6 +9449,12 @@ var mParticle = (function () {
9399
9449
  ScCid: {
9400
9450
  mappedKey: 'SnapchatConversions.ClickId',
9401
9451
  output: IntegrationOutputs.CUSTOM_FLAGS
9452
+ },
9453
+ // Snapchat
9454
+ // https://developers.snap.com/api/marketing-api/Conversions-API/UsingTheAPI#sending-click-id
9455
+ _scid: {
9456
+ mappedKey: 'SnapchatConversions.Cookie1',
9457
+ output: IntegrationOutputs.CUSTOM_FLAGS
9402
9458
  }
9403
9459
  };
9404
9460
  var integrationMappingRokt = {
@@ -9774,17 +9830,73 @@ var mParticle = (function () {
9774
9830
  });
9775
9831
  });
9776
9832
  };
9777
-
9833
+ /**
9834
+ * Hashes attributes and returns both original and hashed versions
9835
+ * with Rokt-compatible key names (like emailsha256, mobilesha256)
9836
+ *
9837
+ *
9838
+ * @param {IRoktPartnerAttributes} attributes - Attributes to hash
9839
+ * @returns {Promise<IRoktPartnerAttributes>} Object with both original and hashed attributes
9840
+ *
9841
+ */
9778
9842
  RoktManager.prototype.hashAttributes = function (attributes) {
9779
- if (!this.isReady()) {
9780
- return this.deferredCall('hashAttributes', attributes);
9781
- }
9782
- try {
9783
- return this.kit.hashAttributes(attributes);
9784
- } catch (error) {
9785
- return Promise.reject(error instanceof Error ? error : new Error('Unknown error occurred'));
9786
- }
9843
+ return __awaiter(this, void 0, void 0, function () {
9844
+ var keys, hashPromises, results, hashedAttributes, _i, results_1, _a, key, attributeValue, hashedValue, error_3, errorMessage;
9845
+ var _this = this;
9846
+ return __generator(this, function (_b) {
9847
+ switch (_b.label) {
9848
+ case 0:
9849
+ _b.trys.push([0, 2,, 3]);
9850
+ if (!attributes || _typeof$1(attributes) !== 'object') {
9851
+ return [2 /*return*/, {}];
9852
+ }
9853
+ keys = Object.keys(attributes);
9854
+ if (keys.length === 0) {
9855
+ return [2 /*return*/, {}];
9856
+ }
9857
+ hashPromises = keys.map(function (key) {
9858
+ return __awaiter(_this, void 0, void 0, function () {
9859
+ var attributeValue, hashedValue;
9860
+ return __generator(this, function (_a) {
9861
+ switch (_a.label) {
9862
+ case 0:
9863
+ attributeValue = attributes[key];
9864
+ return [4 /*yield*/, this.hashSha256(attributeValue)];
9865
+ case 1:
9866
+ hashedValue = _a.sent();
9867
+ return [2 /*return*/, {
9868
+ key: key,
9869
+ attributeValue: attributeValue,
9870
+ hashedValue: hashedValue
9871
+ }];
9872
+ }
9873
+ });
9874
+ });
9875
+ });
9876
+ return [4 /*yield*/, Promise.all(hashPromises)];
9877
+ case 1:
9878
+ results = _b.sent();
9879
+ hashedAttributes = {};
9880
+ for (_i = 0, results_1 = results; _i < results_1.length; _i++) {
9881
+ _a = results_1[_i], key = _a.key, attributeValue = _a.attributeValue, hashedValue = _a.hashedValue;
9882
+ hashedAttributes[key] = attributeValue;
9883
+ if (hashedValue) {
9884
+ hashedAttributes["".concat(key, "sha256")] = hashedValue;
9885
+ }
9886
+ }
9887
+ return [2 /*return*/, hashedAttributes];
9888
+ case 2:
9889
+ error_3 = _b.sent();
9890
+ errorMessage = error_3 instanceof Error ? error_3.message : String(error_3);
9891
+ this.logger.error("Failed to hashAttributes, returning an empty object: ".concat(errorMessage));
9892
+ return [2 /*return*/, {}];
9893
+ case 3:
9894
+ return [2 /*return*/];
9895
+ }
9896
+ });
9897
+ });
9787
9898
  };
9899
+
9788
9900
  RoktManager.prototype.setExtensionData = function (extensionData) {
9789
9901
  if (!this.isReady()) {
9790
9902
  this.deferredCall('setExtensionData', extensionData);
@@ -9807,6 +9919,42 @@ var mParticle = (function () {
9807
9919
  return Promise.reject(error instanceof Error ? error : new Error('Error using extension: ' + name));
9808
9920
  }
9809
9921
  };
9922
+ /**
9923
+ * Hashes an attribute using SHA-256
9924
+ *
9925
+ * @param {string | number | boolean | undefined | null} attribute - The value to hash
9926
+ * @returns {Promise<string | undefined | null>} SHA-256 hashed value or undefined/null
9927
+ *
9928
+ */
9929
+ RoktManager.prototype.hashSha256 = function (attribute) {
9930
+ return __awaiter(this, void 0, void 0, function () {
9931
+ var normalizedValue, error_4, errorMessage;
9932
+ return __generator(this, function (_a) {
9933
+ switch (_a.label) {
9934
+ case 0:
9935
+ if (attribute === null || attribute === undefined) {
9936
+ this.logger.warning("hashSha256 received null/undefined as input");
9937
+ return [2 /*return*/, attribute];
9938
+ }
9939
+ _a.label = 1;
9940
+ case 1:
9941
+ _a.trys.push([1, 3,, 4]);
9942
+ normalizedValue = String(attribute).trim().toLocaleLowerCase();
9943
+ return [4 /*yield*/, this.sha256Hex(normalizedValue)];
9944
+ case 2:
9945
+ return [2 /*return*/, _a.sent()];
9946
+ case 3:
9947
+ error_4 = _a.sent();
9948
+ errorMessage = error_4 instanceof Error ? error_4.message : String(error_4);
9949
+ this.logger.error("Failed to hashSha256, returning undefined: ".concat(errorMessage));
9950
+ return [2 /*return*/, undefined];
9951
+ case 4:
9952
+ return [2 /*return*/];
9953
+ }
9954
+ });
9955
+ });
9956
+ };
9957
+
9810
9958
  RoktManager.prototype.getLocalSessionAttributes = function () {
9811
9959
  return this.store.getLocalSessionAttributes();
9812
9960
  };
@@ -9902,6 +10050,45 @@ var mParticle = (function () {
9902
10050
  }
9903
10051
  this.messageQueue["delete"](messageId);
9904
10052
  };
10053
+ /**
10054
+ * Hashes a string input using SHA-256 and returns the hex digest
10055
+ * Uses the Web Crypto API for secure hashing
10056
+ *
10057
+ * @param {string} input - The string to hash
10058
+ * @returns {Promise<string>} The SHA-256 hash as a hexadecimal string
10059
+ */
10060
+ RoktManager.prototype.sha256Hex = function (input) {
10061
+ return __awaiter(this, void 0, void 0, function () {
10062
+ var encoder, encodedInput, digest;
10063
+ return __generator(this, function (_a) {
10064
+ switch (_a.label) {
10065
+ case 0:
10066
+ encoder = new TextEncoder();
10067
+ encodedInput = encoder.encode(input);
10068
+ return [4 /*yield*/, crypto.subtle.digest('SHA-256', encodedInput)];
10069
+ case 1:
10070
+ digest = _a.sent();
10071
+ return [2 /*return*/, this.arrayBufferToHex(digest)];
10072
+ }
10073
+ });
10074
+ });
10075
+ };
10076
+ /**
10077
+ * Converts an ArrayBuffer to a hexadecimal string representation
10078
+ * Each byte is converted to a 2-character hex string with leading zeros
10079
+ *
10080
+ * @param {ArrayBuffer} buffer - The buffer to convert
10081
+ * @returns {string} The hexadecimal string representation
10082
+ */
10083
+ RoktManager.prototype.arrayBufferToHex = function (buffer) {
10084
+ var bytes = new Uint8Array(buffer);
10085
+ var hexString = '';
10086
+ for (var i = 0; i < bytes.length; i++) {
10087
+ var hexByte = bytes[i].toString(16).padStart(2, '0');
10088
+ hexString += hexByte;
10089
+ }
10090
+ return hexString;
10091
+ };
9905
10092
  /**
9906
10093
  * Checks if an identity value has changed by comparing current and new values
9907
10094
  *
@@ -11451,8 +11638,8 @@ var mParticle = (function () {
11451
11638
  aliasUsers: function aliasUsers(aliasRequest, callback) {
11452
11639
  self.getInstance().Identity.aliasUsers(aliasRequest, callback);
11453
11640
  },
11454
- createAliasRequest: function createAliasRequest(sourceUser, destinationUser) {
11455
- return self.getInstance().Identity.createAliasRequest(sourceUser, destinationUser);
11641
+ createAliasRequest: function createAliasRequest(sourceUser, destinationUser, scope) {
11642
+ return self.getInstance().Identity.createAliasRequest(sourceUser, destinationUser, scope);
11456
11643
  },
11457
11644
  getCurrentUser: function getCurrentUser() {
11458
11645
  return self.getInstance().Identity.getCurrentUser();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mparticle/web-sdk",
3
- "version": "2.50.1",
3
+ "version": "2.52.0",
4
4
  "description": "mParticle core SDK for web applications",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -15,7 +15,9 @@
15
15
  "src/"
16
16
  ],
17
17
  "publishConfig": {
18
- "access": "public"
18
+ "access": "public",
19
+ "provenance": true,
20
+ "registry": "https://registry.npmjs.org"
19
21
  },
20
22
  "main": "dist/mparticle.common.js",
21
23
  "module": "dist/mparticle.esm.js",
@@ -97,9 +99,11 @@
97
99
  "@rollup/plugin-json": "^5.0.2",
98
100
  "@rollup/plugin-node-resolve": "15.2.1",
99
101
  "@rollup/plugin-typescript": "^11.1.0",
100
- "@semantic-release/changelog": "^5.0.1",
101
- "@semantic-release/exec": "^5.0.0",
102
- "@semantic-release/git": "^9.0.0",
102
+ "@semantic-release/changelog": "^6.0.3",
103
+ "@semantic-release/exec": "^6.0.3",
104
+ "@semantic-release/git": "^10.0.1",
105
+ "@semantic-release/npm": "^13.1.2",
106
+ "semantic-release": "^24.2.0",
103
107
  "@types/chai": "^4.2.3",
104
108
  "@types/jest": "^29.5.1",
105
109
  "@types/jest-expect-message": "^1.1.0",
@@ -13,6 +13,16 @@ const { InformationMessages } = Messages;
13
13
 
14
14
  export const DAYS_IN_MILLISECONDS = 1000 * 60 * 60 * 24;
15
15
 
16
+ // Partner module IDs for cookie sync configurations
17
+ export const PARTNER_MODULE_IDS = {
18
+ AdobeEventForwarder: 11,
19
+ DoubleclickDFP: 41,
20
+ AppNexus: 50,
21
+ Lotame: 58,
22
+ TradeDesk: 103,
23
+ VerizonMedia: 155,
24
+ } as const;
25
+
16
26
  export type CookieSyncDates = Dictionary<number>;
17
27
 
18
28
  export interface IPixelConfiguration {
@@ -111,8 +121,12 @@ export default function CookieSyncManager(
111
121
  return;
112
122
  }
113
123
 
114
- // Url for cookie sync pixel
115
- const fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl)
124
+ // The Trade Desk requires a URL parameter for GDPR enabled users.
125
+ // It is optional but to simplify the code, we add it for all Trade
126
+ // // Desk cookie syncs.
127
+ const domain = moduleId === PARTNER_MODULE_IDS.TradeDesk ? window.location.hostname : undefined;
128
+ // Add domain parameter for Trade Desk
129
+ const fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain);
116
130
 
117
131
  self.performCookieSync(
118
132
  fullUrl,
package/src/helpers.js CHANGED
@@ -193,6 +193,21 @@ export default function Helpers(mpInstance) {
193
193
  if ((options = arguments[i]) != null) {
194
194
  // Extend the base object
195
195
  for (name in options) {
196
+ // Prevent prototype pollution
197
+ // https://github.com/advisories/GHSA-jf85-cpcp-j695
198
+ if (
199
+ name === '__proto__' ||
200
+ name === 'constructor' ||
201
+ name === 'prototype'
202
+ ) {
203
+ continue;
204
+ }
205
+
206
+ // Only copy own properties
207
+ if (!Object.prototype.hasOwnProperty.call(options, name)) {
208
+ continue;
209
+ }
210
+
196
211
  src = target[name];
197
212
  copy = options[name];
198
213
 
@@ -107,12 +107,14 @@ export interface IIdentityRequest {
107
107
  ): IdentityPreProcessResult;
108
108
  }
109
109
 
110
+ export type AliasRequestScope = 'device' | 'mpid';
111
+
110
112
  export interface IAliasRequest {
111
113
  destinationMpid: MPID;
112
114
  sourceMpid: MPID;
113
115
  startTime: number;
114
116
  endTime: number;
115
- scope?: string;
117
+ scope?: AliasRequestScope;
116
118
  }
117
119
 
118
120
  export interface IAliasCallback {
@@ -151,7 +153,8 @@ export interface SDKIdentityApi {
151
153
  ): void;
152
154
  createAliasRequest?(
153
155
  sourceUser: IMParticleUser,
154
- destinationUser: IMParticleUser
156
+ destinationUser: IMParticleUser,
157
+ scope?: AliasRequestScope
155
158
  ): IAliasRequest;
156
159
  }
157
160
 
package/src/identity.js CHANGED
@@ -195,6 +195,7 @@ export default function Identity(mpInstance) {
195
195
  SourceMpid: aliasRequest.sourceMpid,
196
196
  StartUnixtimeMs: aliasRequest.startTime,
197
197
  EndUnixtimeMs: aliasRequest.endTime,
198
+ Scope: aliasRequest.scope,
198
199
  };
199
200
  },
200
201
 
@@ -744,7 +745,7 @@ export default function Identity(mpInstance) {
744
745
  after applying this adjustment it will be impossible to create an aliasRequest passes the aliasUsers()
745
746
  validation that the startTime must be less than the endTime
746
747
  */
747
- createAliasRequest: function(sourceUser, destinationUser) {
748
+ createAliasRequest: function(sourceUser, destinationUser, scope) {
748
749
  try {
749
750
  if (!destinationUser || !sourceUser) {
750
751
  mpInstance.Logger.error(
@@ -788,6 +789,7 @@ export default function Identity(mpInstance) {
788
789
  sourceMpid: sourceUser.getMPID(),
789
790
  startTime: startTime,
790
791
  endTime: endTime,
792
+ scope: scope || 'device',
791
793
  };
792
794
  } catch (e) {
793
795
  mpInstance.Logger.error(
@@ -120,6 +120,12 @@ const integrationMappingExternal: IntegrationIdMapping = {
120
120
  mappedKey: 'SnapchatConversions.ClickId',
121
121
  output: IntegrationOutputs.CUSTOM_FLAGS,
122
122
  },
123
+ // Snapchat
124
+ // https://developers.snap.com/api/marketing-api/Conversions-API/UsingTheAPI#sending-click-id
125
+ _scid: {
126
+ mappedKey: 'SnapchatConversions.Cookie1',
127
+ output: IntegrationOutputs.CUSTOM_FLAGS,
128
+ },
123
129
  };
124
130
 
125
131
  const integrationMappingRokt: IntegrationIdMapping = {
@@ -368,10 +368,10 @@ function mParticleInstanceManager(this: IMParticleInstanceManager) {
368
368
  aliasUsers: function(aliasRequest, callback) {
369
369
  self.getInstance().Identity.aliasUsers(aliasRequest, callback);
370
370
  },
371
- createAliasRequest: function(sourceUser, destinationUser) {
371
+ createAliasRequest: function(sourceUser, destinationUser, scope) {
372
372
  return self
373
373
  .getInstance()
374
- .Identity.createAliasRequest(sourceUser, destinationUser);
374
+ .Identity.createAliasRequest(sourceUser, destinationUser, scope);
375
375
  },
376
376
  getCurrentUser: function() {
377
377
  return self.getInstance().Identity.getCurrentUser();