@mparticle/web-sdk 2.58.0 → 2.60.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.58.0";
206
+ var version = "2.60.0";
207
207
 
208
208
  var Constants = {
209
209
  sdkVersion: version,
@@ -419,6 +419,16 @@ var mParticle = (function () {
419
419
  var HTTP_BAD_REQUEST = 400;
420
420
  var HTTP_SERVER_ERROR = 500;
421
421
 
422
+ function _typeof$1(o) {
423
+ "@babel/helpers - typeof";
424
+
425
+ return _typeof$1 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
426
+ return typeof o;
427
+ } : function (o) {
428
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
429
+ }, _typeof$1(o);
430
+ }
431
+
422
432
  /******************************************************************************
423
433
  Copyright (c) Microsoft Corporation.
424
434
 
@@ -855,6 +865,63 @@ var mParticle = (function () {
855
865
  return kitConfig.name === moduleName && kitConfig.moduleId === moduleId;
856
866
  })) || null;
857
867
  };
868
+ /**
869
+ * Obfuscates an object by replacing all primitive values with their type names,
870
+ * while preserving the structure of nested objects and arrays.
871
+ * This is useful for logging data structures without exposing PII.
872
+ *
873
+ * @param value - The value to obfuscate
874
+ * @returns The obfuscated value with types instead of actual values
875
+ *
876
+ * @example
877
+ * obfuscateData({ email: 'user@email.com', age: 30 })
878
+ * // Returns: { email: 'string', age: 'number' }
879
+ *
880
+ * obfuscateData({ tags: ['premium', 'verified'] })
881
+ * // Returns: { tags: ['string', 'string'] }
882
+ */
883
+ var obfuscateData = function obfuscateData(value) {
884
+ // Preserve null and undefined
885
+ if (value === null || value === undefined) {
886
+ return value;
887
+ }
888
+ // Handle arrays - recursively obfuscate each element
889
+ if (Array.isArray(value)) {
890
+ return value.map(function (item) {
891
+ return obfuscateData(item);
892
+ });
893
+ }
894
+ // Handle objects - recursively obfuscate each property
895
+ if (isObject(value)) {
896
+ var obfuscated = {};
897
+ for (var key in value) {
898
+ if (value.hasOwnProperty(key)) {
899
+ obfuscated[key] = obfuscateData(value[key]);
900
+ }
901
+ }
902
+ return obfuscated;
903
+ }
904
+ // For primitives and other types, return the type as a string
905
+ return _typeof$1(value);
906
+ };
907
+ /**
908
+ * For verbose logging: returns raw data when isDevelopmentMode is true, else obfuscated data.
909
+ * Used when logging payloads so PII is not exposed in production.
910
+ *
911
+ * @param data - The value to log
912
+ * @param isDevelopmentMode - When true, returns data unchanged, when false or undefined, returns obfuscated data
913
+ * @returns Raw data when isDevelopmentMode is true, otherwise obfuscated structure
914
+ *
915
+ * @example
916
+ * obfuscateDevData({ email: 'user@email.com' }, true)
917
+ * // Returns: { email: 'user@email.com' }
918
+ *
919
+ * obfuscateDevData({ email: 'user@email.com' }, false)
920
+ * // Returns: { email: 'string' }
921
+ */
922
+ var obfuscateDevData = function obfuscateDevData(data, isDevelopmentMode) {
923
+ return isDevelopmentMode ? data : obfuscateData(data);
924
+ };
858
925
 
859
926
  var MessageType$1 = {
860
927
  SessionStart: 1,
@@ -1234,16 +1301,6 @@ var mParticle = (function () {
1234
1301
  Environment: Constants.Environment
1235
1302
  };
1236
1303
 
1237
- function _typeof$1(o) {
1238
- "@babel/helpers - typeof";
1239
-
1240
- return _typeof$1 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
1241
- return typeof o;
1242
- } : function (o) {
1243
- return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
1244
- }, _typeof$1(o);
1245
- }
1246
-
1247
1304
  var SDKProductActionType;
1248
1305
  (function (SDKProductActionType) {
1249
1306
  SDKProductActionType[SDKProductActionType["Unknown"] = 0] = "Unknown";
@@ -2138,18 +2195,11 @@ var mParticle = (function () {
2138
2195
  /**
2139
2196
  *
2140
2197
  * @param {string} storageKey the local storage key string
2141
- * @param {Storage} Web API Storage object that is being used
2142
- * @param {IVaultOptions} options A Dictionary of IVaultOptions
2198
+ * @param {Storage} storageObject Web API Storage object that is being used
2143
2199
  */
2144
- function BaseVault(storageKey, storageObject, options) {
2200
+ function BaseVault(storageKey, storageObject) {
2145
2201
  this._storageKey = storageKey;
2146
2202
  this.storageObject = storageObject;
2147
- // Add a fake logger in case one is not provided or needed
2148
- this.logger = (options === null || options === void 0 ? void 0 : options.logger) || {
2149
- verbose: function verbose() {},
2150
- warning: function warning() {},
2151
- error: function error() {}
2152
- };
2153
2203
  this.contents = this.retrieve();
2154
2204
  }
2155
2205
  /**
@@ -2165,13 +2215,7 @@ var mParticle = (function () {
2165
2215
  } else {
2166
2216
  stringifiedItem = '';
2167
2217
  }
2168
- try {
2169
- this.storageObject.setItem(this._storageKey, stringifiedItem);
2170
- this.logger.verbose("Saving item to Storage: ".concat(stringifiedItem));
2171
- } catch (error) {
2172
- this.logger.error("Cannot Save items to Storage: ".concat(stringifiedItem));
2173
- this.logger.error(error);
2174
- }
2218
+ this.storageObject.setItem(this._storageKey, stringifiedItem);
2175
2219
  };
2176
2220
  /**
2177
2221
  * Retrieve StorableItem from Storage
@@ -2183,7 +2227,6 @@ var mParticle = (function () {
2183
2227
  // https://go.mparticle.com/work/SQDSDKS-5022
2184
2228
  var item = this.storageObject.getItem(this._storageKey);
2185
2229
  this.contents = item ? JSON.parse(item) : null;
2186
- this.logger.verbose("Retrieving item from Storage: ".concat(item));
2187
2230
  return this.contents;
2188
2231
  };
2189
2232
  /**
@@ -2192,7 +2235,6 @@ var mParticle = (function () {
2192
2235
  * @method purge
2193
2236
  */
2194
2237
  BaseVault.prototype.purge = function () {
2195
- this.logger.verbose('Purging Storage');
2196
2238
  this.contents = null;
2197
2239
  this.storageObject.removeItem(this._storageKey);
2198
2240
  };
@@ -2200,18 +2242,38 @@ var mParticle = (function () {
2200
2242
  }();
2201
2243
  var LocalStorageVault = /** @class */function (_super) {
2202
2244
  __extends(LocalStorageVault, _super);
2203
- function LocalStorageVault(storageKey, options) {
2204
- return _super.call(this, storageKey, window.localStorage, options) || this;
2245
+ function LocalStorageVault(storageKey) {
2246
+ return _super.call(this, storageKey, window.localStorage) || this;
2205
2247
  }
2206
2248
  return LocalStorageVault;
2207
2249
  }(BaseVault);
2208
2250
  var SessionStorageVault = /** @class */function (_super) {
2209
2251
  __extends(SessionStorageVault, _super);
2210
- function SessionStorageVault(storageKey, options) {
2211
- return _super.call(this, storageKey, window.sessionStorage, options) || this;
2252
+ function SessionStorageVault(storageKey) {
2253
+ return _super.call(this, storageKey, window.sessionStorage) || this;
2212
2254
  }
2213
2255
  return SessionStorageVault;
2214
2256
  }(BaseVault);
2257
+ // DisabledVault is used when persistence is disabled by privacy flags.
2258
+ var DisabledVault = /** @class */function (_super) {
2259
+ __extends(DisabledVault, _super);
2260
+ function DisabledVault(storageKey) {
2261
+ var _this = _super.call(this, storageKey, window.localStorage) || this;
2262
+ _this.contents = null;
2263
+ _this.storageObject.removeItem(_this._storageKey);
2264
+ return _this;
2265
+ }
2266
+ DisabledVault.prototype.store = function (_item) {
2267
+ this.contents = null;
2268
+ };
2269
+ DisabledVault.prototype.retrieve = function () {
2270
+ return this.contents;
2271
+ };
2272
+ DisabledVault.prototype.purge = function () {
2273
+ this.contents = null;
2274
+ };
2275
+ return DisabledVault;
2276
+ }(BaseVault);
2215
2277
 
2216
2278
  var AsyncUploader = /** @class */function () {
2217
2279
  function AsyncUploader(url) {
@@ -2374,6 +2436,7 @@ var mParticle = (function () {
2374
2436
  */
2375
2437
  function BatchUploader(mpInstance, uploadInterval) {
2376
2438
  var _a;
2439
+ var _b;
2377
2440
  this.offlineStorageEnabled = false;
2378
2441
  this.lastASTEventTime = 0;
2379
2442
  this.AST_DEBOUNCE_MS = 1000; // 1 second debounce
@@ -2392,19 +2455,17 @@ var mParticle = (function () {
2392
2455
  // Cache Offline Storage Availability boolean
2393
2456
  // so that we don't have to check it every time
2394
2457
  this.offlineStorageEnabled = this.isOfflineStorageAvailable();
2395
- if (this.offlineStorageEnabled) {
2396
- this.eventVault = new SessionStorageVault("".concat(mpInstance._Store.storageName, "-events"), {
2397
- logger: mpInstance.Logger
2398
- });
2399
- this.batchVault = new LocalStorageVault("".concat(mpInstance._Store.storageName, "-batches"), {
2400
- logger: mpInstance.Logger
2401
- });
2458
+ // When noFunctional is true, prevent events/batches storage
2459
+ var noFunctional = (_b = mpInstance._CookieConsentManager) === null || _b === void 0 ? void 0 : _b.getNoFunctional();
2460
+ if (this.offlineStorageEnabled && !noFunctional) {
2461
+ this.eventVault = new SessionStorageVault("".concat(mpInstance._Store.storageName, "-events"));
2462
+ this.batchVault = new LocalStorageVault("".concat(mpInstance._Store.storageName, "-batches"));
2402
2463
  // Load Events from Session Storage in case we have any in storage
2403
2464
  (_a = this.eventsQueuedForProcessing).push.apply(_a, this.eventVault.retrieve());
2404
2465
  }
2405
- var _b = this.mpInstance._Store,
2406
- SDKConfig = _b.SDKConfig,
2407
- devToken = _b.devToken;
2466
+ var _c = this.mpInstance._Store,
2467
+ SDKConfig = _c.SDKConfig,
2468
+ devToken = _c.devToken;
2408
2469
  var baseUrl = this.mpInstance._Helpers.createServiceUrl(SDKConfig.v3SecureServiceUrl, devToken);
2409
2470
  this.uploadUrl = "".concat(baseUrl, "/events");
2410
2471
  this.uploader = window.fetch ? new FetchUploader(this.uploadUrl) : new XHRUploader(this.uploadUrl);
@@ -2542,13 +2603,15 @@ var mParticle = (function () {
2542
2603
  if (isEmpty(event)) {
2543
2604
  return;
2544
2605
  }
2545
- var Logger = this.mpInstance.Logger;
2546
2606
  this.eventsQueuedForProcessing.push(event);
2547
2607
  if (this.offlineStorageEnabled && this.eventVault) {
2548
2608
  this.eventVault.store(this.eventsQueuedForProcessing);
2549
2609
  }
2550
- Logger.verbose("Queuing event: ".concat(JSON.stringify(event)));
2551
- Logger.verbose("Queued event count: ".concat(this.eventsQueuedForProcessing.length));
2610
+ if (this.mpInstance.Logger.isVerbose()) {
2611
+ var eventToLog = obfuscateDevData(event, this.mpInstance._Store.SDKConfig.isDevelopmentMode);
2612
+ this.mpInstance.Logger.verbose("Queuing event: ".concat(JSON.stringify(eventToLog)));
2613
+ this.mpInstance.Logger.verbose("Queued event count: ".concat(this.eventsQueuedForProcessing.length));
2614
+ }
2552
2615
  if (this.shouldTriggerImmediateUpload(event.EventDataType)) {
2553
2616
  this.prepareAndUpload(false, false);
2554
2617
  }
@@ -2664,7 +2727,7 @@ var mParticle = (function () {
2664
2727
  }
2665
2728
  batchesToUpload = this.batchesQueuedForProcessing;
2666
2729
  this.batchesQueuedForProcessing = [];
2667
- return [4 /*yield*/, this.uploadBatches(this.mpInstance.Logger, batchesToUpload, useBeacon)];
2730
+ return [4 /*yield*/, this.uploadBatches(batchesToUpload, useBeacon)];
2668
2731
  case 1:
2669
2732
  batchesThatDidNotUpload = _d.sent();
2670
2733
  // Batches that do not successfully upload are added back to the process queue
@@ -2693,11 +2756,10 @@ var mParticle = (function () {
2693
2756
  });
2694
2757
  });
2695
2758
  };
2696
- // TODO: Refactor to use logger as a class method
2697
- // https://go.mparticle.com/work/SQDSDKS-5167
2698
- BatchUploader.prototype.uploadBatches = function (logger, batches, useBeacon) {
2759
+
2760
+ BatchUploader.prototype.uploadBatches = function (batches, useBeacon) {
2699
2761
  return __awaiter(this, void 0, void 0, function () {
2700
- var uploads, i, fetchPayload, blob, response, e_1;
2762
+ var uploads, uploadsToLog, i, fetchPayload, blob, response, e_1;
2701
2763
  return __generator(this, function (_a) {
2702
2764
  switch (_a.label) {
2703
2765
  case 0:
@@ -2707,8 +2769,11 @@ var mParticle = (function () {
2707
2769
  if (isEmpty(uploads)) {
2708
2770
  return [2 /*return*/, null];
2709
2771
  }
2710
- logger.verbose("Uploading batches: ".concat(JSON.stringify(uploads)));
2711
- logger.verbose("Batch count: ".concat(uploads.length));
2772
+ if (this.mpInstance.Logger.isVerbose()) {
2773
+ uploadsToLog = obfuscateDevData(uploads, this.mpInstance._Store.SDKConfig.isDevelopmentMode);
2774
+ this.mpInstance.Logger.verbose("Uploading batches: ".concat(JSON.stringify(uploadsToLog)));
2775
+ this.mpInstance.Logger.verbose("Batch count: ".concat(uploads.length));
2776
+ }
2712
2777
  i = 0;
2713
2778
  _a.label = 1;
2714
2779
  case 1:
@@ -2733,13 +2798,13 @@ var mParticle = (function () {
2733
2798
  case 3:
2734
2799
  response = _a.sent();
2735
2800
  if (response.status >= 200 && response.status < 300) {
2736
- logger.verbose("Upload success for request ID: ".concat(uploads[i].source_request_id));
2801
+ this.mpInstance.Logger.verbose("Upload success for request ID: ".concat(uploads[i].source_request_id));
2737
2802
  } else if (response.status >= 500 || response.status === 429) {
2738
- logger.error("HTTP error status ".concat(response.status, " received"));
2803
+ this.mpInstance.Logger.error("HTTP error status ".concat(response.status, " received"));
2739
2804
  // Server error, add back current batches and try again later
2740
2805
  return [2 /*return*/, uploads.slice(i, uploads.length)];
2741
2806
  } else if (response.status >= 401) {
2742
- logger.error("HTTP error status ".concat(response.status, " while uploading - please verify your API key."));
2807
+ this.mpInstance.Logger.error("HTTP error status ".concat(response.status, " while uploading - please verify your API key."));
2743
2808
  //if we're getting a 401, assume we'll keep getting a 401 and clear the uploads.
2744
2809
  return [2 /*return*/, null];
2745
2810
  } else {
@@ -2750,7 +2815,7 @@ var mParticle = (function () {
2750
2815
  return [3 /*break*/, 5];
2751
2816
  case 4:
2752
2817
  e_1 = _a.sent();
2753
- logger.error("Error sending event to mParticle servers. ".concat(e_1));
2818
+ this.mpInstance.Logger.error("Error sending event to mParticle servers. ".concat(e_1));
2754
2819
  return [2 /*return*/, uploads.slice(i, uploads.length)];
2755
2820
  case 5:
2756
2821
  i++;
@@ -2767,6 +2832,181 @@ var mParticle = (function () {
2767
2832
  return BatchUploader;
2768
2833
  }();
2769
2834
 
2835
+ var _a = Constants.IdentityMethods,
2836
+ Identify$2 = _a.Identify,
2837
+ Modify$4 = _a.Modify,
2838
+ Login$2 = _a.Login,
2839
+ Logout$2 = _a.Logout;
2840
+ var CACHE_HEADER = 'x-mp-max-age';
2841
+ var cacheOrClearIdCache = function cacheOrClearIdCache(method, knownIdentities, idCache, identityResponse, parsingCachedResponse) {
2842
+ // when parsing a response that has already been cached, simply return instead of attempting another cache
2843
+ if (parsingCachedResponse) {
2844
+ return;
2845
+ }
2846
+ // default the expire timestamp to one day in milliseconds unless a header comes back
2847
+ var expireTimestamp = getExpireTimestamp(identityResponse === null || identityResponse === void 0 ? void 0 : identityResponse.cacheMaxAge);
2848
+ switch (method) {
2849
+ case Login$2:
2850
+ case Identify$2:
2851
+ cacheIdentityRequest(method, knownIdentities, expireTimestamp, idCache, identityResponse);
2852
+ break;
2853
+ case Modify$4:
2854
+ case Logout$2:
2855
+ idCache.purge();
2856
+ break;
2857
+ }
2858
+ };
2859
+ var cacheIdentityRequest = function cacheIdentityRequest(method, identities, expireTimestamp, idCache, identityResponse) {
2860
+ var responseText = identityResponse.responseText,
2861
+ status = identityResponse.status;
2862
+ var cache = idCache.retrieve() || {};
2863
+ var cacheKey = concatenateIdentities(method, identities);
2864
+ var hashedKey = generateHash(cacheKey);
2865
+ var mpid = responseText.mpid,
2866
+ is_logged_in = responseText.is_logged_in;
2867
+ var cachedResponseBody = {
2868
+ mpid: mpid,
2869
+ is_logged_in: is_logged_in
2870
+ };
2871
+ cache[hashedKey] = {
2872
+ responseText: JSON.stringify(cachedResponseBody),
2873
+ status: status,
2874
+ expireTimestamp: expireTimestamp
2875
+ };
2876
+ idCache.store(cache);
2877
+ };
2878
+ // We need to ensure that identities are concatenated in a deterministic way, so
2879
+ // we sort the identities based on their enum.
2880
+ // we create an array, set the user identity at the index of the user identity type
2881
+ var concatenateIdentities = function concatenateIdentities(method, userIdentities) {
2882
+ var DEVICE_APPLICATION_STAMP = 'device_application_stamp';
2883
+ // set DAS first since it is not an official identity type
2884
+ var cacheKey = "".concat(method, ":").concat(DEVICE_APPLICATION_STAMP, "=").concat(userIdentities.device_application_stamp, ";");
2885
+ var idLength = Object.keys(userIdentities).length;
2886
+ var concatenatedIdentities = '';
2887
+ if (idLength) {
2888
+ var userIDArray = new Array();
2889
+ // create an array where each index is equal to the user identity type
2890
+ for (var key in userIdentities) {
2891
+ if (key === DEVICE_APPLICATION_STAMP) {
2892
+ continue;
2893
+ } else {
2894
+ userIDArray[Types.IdentityType.getIdentityType(key)] = userIdentities[key];
2895
+ }
2896
+ }
2897
+ concatenatedIdentities = userIDArray.reduce(function (prevValue, currentValue, index) {
2898
+ var idName = Types.IdentityType.getIdentityName(index);
2899
+ return "".concat(prevValue).concat(idName, "=").concat(currentValue, ";");
2900
+ }, cacheKey);
2901
+ }
2902
+ return concatenatedIdentities;
2903
+ };
2904
+ var hasValidCachedIdentity = function hasValidCachedIdentity(method, proposedUserIdentities, idCache) {
2905
+ // There is an edge case where multiple identity calls are taking place
2906
+ // before identify fires, so there may not be a cache. See what happens when
2907
+ // the ? in idCache is removed to the following test
2908
+ // "queued events contain login mpid instead of identify mpid when calling
2909
+ // login immediately after mParticle initializes"
2910
+ var cache = idCache === null || idCache === void 0 ? void 0 : idCache.retrieve();
2911
+ // if there is no cache, then there is no valid cached identity
2912
+ if (!cache) {
2913
+ return false;
2914
+ }
2915
+ var cacheKey = concatenateIdentities(method, proposedUserIdentities);
2916
+ var hashedKey = generateHash(cacheKey);
2917
+ // if cache doesn't have the cacheKey, there is no valid cached identity
2918
+ if (!cache.hasOwnProperty(hashedKey)) {
2919
+ return false;
2920
+ }
2921
+ // If there is a valid cache key, compare the expireTimestamp to the current time.
2922
+ // If the current time is greater than the expireTimestamp, it is not a valid
2923
+ // cached identity.
2924
+ var expireTimestamp = cache[hashedKey].expireTimestamp;
2925
+ if (expireTimestamp < new Date().getTime()) {
2926
+ return false;
2927
+ } else {
2928
+ return true;
2929
+ }
2930
+ };
2931
+ var getCachedIdentity = function getCachedIdentity(method, proposedUserIdentities, idCache) {
2932
+ var cacheKey = concatenateIdentities(method, proposedUserIdentities);
2933
+ var hashedKey = generateHash(cacheKey);
2934
+ var cache = idCache.retrieve();
2935
+ var cachedIdentity = cache ? cache[hashedKey] : null;
2936
+ return {
2937
+ responseText: parseIdentityResponse(cachedIdentity.responseText),
2938
+ expireTimestamp: cachedIdentity.expireTimestamp,
2939
+ status: cachedIdentity.status
2940
+ };
2941
+ };
2942
+ // https://go.mparticle.com/work/SQDSDKS-6079
2943
+ var createKnownIdentities = function createKnownIdentities(identityApiData, deviceId) {
2944
+ var identitiesResult = {};
2945
+ if (isObject(identityApiData === null || identityApiData === void 0 ? void 0 : identityApiData.userIdentities)) {
2946
+ for (var identity in identityApiData.userIdentities) {
2947
+ identitiesResult[identity] = identityApiData.userIdentities[identity];
2948
+ }
2949
+ }
2950
+ identitiesResult.device_application_stamp = deviceId;
2951
+ return identitiesResult;
2952
+ };
2953
+ var removeExpiredIdentityCacheDates = function removeExpiredIdentityCacheDates(idCache) {
2954
+ var cache = idCache.retrieve() || {};
2955
+ var currentTime = new Date().getTime();
2956
+ // Iterate over the cache and remove any key/value pairs that are expired
2957
+ for (var key in cache) {
2958
+ if (cache[key].expireTimestamp < currentTime) {
2959
+ delete cache[key];
2960
+ }
2961
+ }
2962
+ idCache.store(cache);
2963
+ };
2964
+ var tryCacheIdentity = function tryCacheIdentity(knownIdentities, idCache, parseIdentityResponse, mpid, callback, identityApiData, identityMethod) {
2965
+ // https://go.mparticle.com/work/SQDSDKS-6095
2966
+ var shouldReturnCachedIdentity = hasValidCachedIdentity(identityMethod, knownIdentities, idCache);
2967
+ // If Identity is cached, then immediately parse the identity response
2968
+ if (shouldReturnCachedIdentity) {
2969
+ var cachedIdentity = getCachedIdentity(identityMethod, knownIdentities, idCache);
2970
+ parseIdentityResponse(cachedIdentity, mpid, callback, identityApiData, identityMethod, knownIdentities, true);
2971
+ return true;
2972
+ }
2973
+ return false;
2974
+ };
2975
+ var getExpireTimestamp = function getExpireTimestamp(maxAge) {
2976
+ if (maxAge === void 0) {
2977
+ maxAge = ONE_DAY_IN_SECONDS;
2978
+ }
2979
+ return new Date().getTime() + maxAge * MILLIS_IN_ONE_SEC;
2980
+ };
2981
+ var parseIdentityResponse = function parseIdentityResponse(responseText) {
2982
+ return responseText ? JSON.parse(responseText) : {};
2983
+ };
2984
+ var hasIdentityRequestChanged = function hasIdentityRequestChanged(currentUser, newIdentityRequest) {
2985
+ if (!currentUser || !(newIdentityRequest === null || newIdentityRequest === void 0 ? void 0 : newIdentityRequest.userIdentities)) {
2986
+ return false;
2987
+ }
2988
+ var currentUserIdentities = currentUser.getUserIdentities().userIdentities;
2989
+ var newIdentities = newIdentityRequest.userIdentities;
2990
+ return JSON.stringify(currentUserIdentities) !== JSON.stringify(newIdentities);
2991
+ };
2992
+ /**
2993
+ * Checks if deviceId or other user identifiers (like email) were explicitly provided
2994
+ * by the partner via config.deviceId or config.identifyRequest.userIdentities.
2995
+ * When noFunctional is true, then cookies are blocked, so the partner must explicitly
2996
+ * pass deviceId or other identifiers to prevent new users from being created on each page load.
2997
+ *
2998
+ * @param store - The SDK store (provides SDKConfig.deviceId and SDKConfig.identifyRequest.userIdentities)
2999
+ * @returns true if deviceId or other identifiers were explicitly provided in config, false otherwise
3000
+ */
3001
+ var hasExplicitIdentifier = function hasExplicitIdentifier(store) {
3002
+ var _a, _b, _c;
3003
+ var userIdentities = (_b = (_a = store === null || store === void 0 ? void 0 : store.SDKConfig) === null || _a === void 0 ? void 0 : _a.identifyRequest) === null || _b === void 0 ? void 0 : _b.userIdentities;
3004
+ if (userIdentities && isObject(userIdentities) && !isEmpty(userIdentities) && Object.values(userIdentities).some(Boolean)) {
3005
+ return true;
3006
+ }
3007
+ return !!((_c = store === null || store === void 0 ? void 0 : store.SDKConfig) === null || _c === void 0 ? void 0 : _c.deviceId);
3008
+ };
3009
+
2770
3010
  function APIClient(mpInstance, kitBlocker) {
2771
3011
  this.uploader = null;
2772
3012
  var self = this;
@@ -2802,6 +3042,28 @@ var mParticle = (function () {
2802
3042
  }
2803
3043
  });
2804
3044
  };
3045
+ // When noFunctional is set and there are no identities passed, the SDK will not fully initialize.
3046
+ // In this case, there will be no MPID, but we still want kits to initialize and forward the event to kits.
3047
+ // The original event is queued for the MP server upload path so it can be sent once an MPID is returned.
3048
+ // Returns true if the event was handled by this path (caller should return early).
3049
+ var handleNoFunctionalPreMpidEvent = function handleNoFunctionalPreMpidEvent(event, mpid) {
3050
+ var _a;
3051
+ var noFunctionalWithoutId = ((_a = mpInstance._CookieConsentManager) === null || _a === void 0 ? void 0 : _a.getNoFunctional()) && !hasExplicitIdentifier(mpInstance._Store);
3052
+ if (!noFunctionalWithoutId || mpid || !mpInstance._Store.configurationLoaded || mpInstance._Store.requireDelay) {
3053
+ return false;
3054
+ }
3055
+ var forwarderEvent = event;
3056
+ if (kitBlocker === null || kitBlocker === void 0 ? void 0 : kitBlocker.kitBlockingEnabled) {
3057
+ forwarderEvent = kitBlocker.createBlockedEvent(event);
3058
+ }
3059
+ if (forwarderEvent) {
3060
+ mpInstance._Forwarders.sendEventToForwarders(forwarderEvent);
3061
+ event.AlreadySentToForwarders = true;
3062
+ }
3063
+ mpInstance.Logger.verbose('noFunctional event forwarded to kits and queued for MP server upload when MPID is available.');
3064
+ mpInstance._Store.eventQueue.push(event);
3065
+ return true;
3066
+ };
2805
3067
  this.sendEventToServer = function (event, _options) {
2806
3068
  var defaultOptions = {
2807
3069
  shouldUploadEvent: true
@@ -2817,8 +3079,12 @@ var mParticle = (function () {
2817
3079
  mpid = currentUser.getMPID();
2818
3080
  }
2819
3081
  mpInstance._Store.requireDelay = mpInstance._Helpers.isDelayedByIntegration(mpInstance._preInit.integrationDelays, mpInstance._Store.integrationDelayTimeoutStart, Date.now());
2820
- // We queue events if there is no MPID (MPID is null, or === 0), or there are integrations that that require this to stall because integration attributes
2821
- // need to be set, or if we are still fetching the config (self hosted only), and so require delaying events
3082
+ if (handleNoFunctionalPreMpidEvent(event, mpid)) {
3083
+ return;
3084
+ }
3085
+ // We queue events if there is no MPID (MPID is null, or === 0), or there are integrations that
3086
+ // require this to stall because integration attributes need to be set, or if we are still
3087
+ // fetching the config (self hosted only), and so require delaying events
2822
3088
  if (!mpid || mpInstance._Store.requireDelay || !mpInstance._Store.configurationLoaded) {
2823
3089
  mpInstance.Logger.verbose('Event was added to eventQueue. eventQueue will be processed once a valid MPID is returned or there is no more integration imposed delay.');
2824
3090
  mpInstance._Store.eventQueue.push(event);
@@ -2840,8 +3106,10 @@ var mParticle = (function () {
2840
3106
  event = kitBlocker.createBlockedEvent(event);
2841
3107
  }
2842
3108
  // We need to check event again, because kitblocking
2843
- // can nullify the event
2844
- if (event) {
3109
+ // can nullify the event.
3110
+ // Skip if forwarders were already called in the noFunctional pre-MPID path
3111
+ // to prevent double-sending when the event queue is later flushed.
3112
+ if (event && !event.AlreadySentToForwarders) {
2845
3113
  mpInstance._Forwarders.sendEventToForwarders(event);
2846
3114
  }
2847
3115
  }
@@ -2900,7 +3168,7 @@ var mParticle = (function () {
2900
3168
  };
2901
3169
  }
2902
3170
 
2903
- var Modify$4 = Constants.IdentityMethods.Modify;
3171
+ var Modify$3 = Constants.IdentityMethods.Modify;
2904
3172
  var Validators = {
2905
3173
  // From ./utils
2906
3174
  // Utility Functions for backwards compatability
@@ -2940,7 +3208,7 @@ var mParticle = (function () {
2940
3208
  copyUserAttributes: 1
2941
3209
  };
2942
3210
  if (identityApiData) {
2943
- if (method === Modify$4) {
3211
+ if (method === Modify$3) {
2944
3212
  if (isObject(identityApiData.userIdentities) && !Object.keys(identityApiData.userIdentities).length || !isObject(identityApiData.userIdentities)) {
2945
3213
  return {
2946
3214
  valid: false,
@@ -3506,12 +3774,18 @@ var mParticle = (function () {
3506
3774
  var self = this;
3507
3775
  // Public
3508
3776
  this.attemptCookieSync = function (mpid, mpidIsNotInCookies) {
3509
- var _a = mpInstance._Store,
3510
- pixelConfigurations = _a.pixelConfigurations,
3511
- webviewBridgeEnabled = _a.webviewBridgeEnabled;
3777
+ var _a;
3778
+ var _b = mpInstance._Store,
3779
+ pixelConfigurations = _b.pixelConfigurations,
3780
+ webviewBridgeEnabled = _b.webviewBridgeEnabled;
3512
3781
  if (!mpid || webviewBridgeEnabled) {
3513
3782
  return;
3514
3783
  }
3784
+ // When noFunctional is true, persistence is not saved, so we cannot track cookie sync
3785
+ // dates. Skip cookie sync to avoid running it on every page load.
3786
+ if ((_a = mpInstance._CookieConsentManager) === null || _a === void 0 ? void 0 : _a.getNoFunctional()) {
3787
+ return;
3788
+ }
3515
3789
  var persistence = mpInstance._Persistence.getPersistence();
3516
3790
  if (isEmpty(persistence)) {
3517
3791
  return;
@@ -3583,172 +3857,15 @@ var mParticle = (function () {
3583
3857
  return new Date().getTime() > new Date(lastSyncDate).getTime() + frequencyCap * DAYS_IN_MILLISECONDS;
3584
3858
  };
3585
3859
 
3586
- var _a = Constants.IdentityMethods,
3587
- Identify$2 = _a.Identify,
3588
- Modify$3 = _a.Modify,
3589
- Login$2 = _a.Login,
3590
- Logout$2 = _a.Logout;
3591
- var CACHE_HEADER = 'x-mp-max-age';
3592
- var cacheOrClearIdCache = function cacheOrClearIdCache(method, knownIdentities, idCache, identityResponse, parsingCachedResponse) {
3593
- // when parsing a response that has already been cached, simply return instead of attempting another cache
3594
- if (parsingCachedResponse) {
3595
- return;
3596
- }
3597
- // default the expire timestamp to one day in milliseconds unless a header comes back
3598
- var expireTimestamp = getExpireTimestamp(identityResponse === null || identityResponse === void 0 ? void 0 : identityResponse.cacheMaxAge);
3599
- switch (method) {
3600
- case Login$2:
3601
- case Identify$2:
3602
- cacheIdentityRequest(method, knownIdentities, expireTimestamp, idCache, identityResponse);
3603
- break;
3604
- case Modify$3:
3605
- case Logout$2:
3606
- idCache.purge();
3607
- break;
3608
- }
3609
- };
3610
- var cacheIdentityRequest = function cacheIdentityRequest(method, identities, expireTimestamp, idCache, identityResponse) {
3611
- var responseText = identityResponse.responseText,
3612
- status = identityResponse.status;
3613
- var cache = idCache.retrieve() || {};
3614
- var cacheKey = concatenateIdentities(method, identities);
3615
- var hashedKey = generateHash(cacheKey);
3616
- var mpid = responseText.mpid,
3617
- is_logged_in = responseText.is_logged_in;
3618
- var cachedResponseBody = {
3619
- mpid: mpid,
3620
- is_logged_in: is_logged_in
3621
- };
3622
- cache[hashedKey] = {
3623
- responseText: JSON.stringify(cachedResponseBody),
3624
- status: status,
3625
- expireTimestamp: expireTimestamp
3626
- };
3627
- idCache.store(cache);
3628
- };
3629
- // We need to ensure that identities are concatenated in a deterministic way, so
3630
- // we sort the identities based on their enum.
3631
- // we create an array, set the user identity at the index of the user identity type
3632
- var concatenateIdentities = function concatenateIdentities(method, userIdentities) {
3633
- var DEVICE_APPLICATION_STAMP = 'device_application_stamp';
3634
- // set DAS first since it is not an official identity type
3635
- var cacheKey = "".concat(method, ":").concat(DEVICE_APPLICATION_STAMP, "=").concat(userIdentities.device_application_stamp, ";");
3636
- var idLength = Object.keys(userIdentities).length;
3637
- var concatenatedIdentities = '';
3638
- if (idLength) {
3639
- var userIDArray = new Array();
3640
- // create an array where each index is equal to the user identity type
3641
- for (var key in userIdentities) {
3642
- if (key === DEVICE_APPLICATION_STAMP) {
3643
- continue;
3644
- } else {
3645
- userIDArray[Types.IdentityType.getIdentityType(key)] = userIdentities[key];
3646
- }
3647
- }
3648
- concatenatedIdentities = userIDArray.reduce(function (prevValue, currentValue, index) {
3649
- var idName = Types.IdentityType.getIdentityName(index);
3650
- return "".concat(prevValue).concat(idName, "=").concat(currentValue, ";");
3651
- }, cacheKey);
3652
- }
3653
- return concatenatedIdentities;
3654
- };
3655
- var hasValidCachedIdentity = function hasValidCachedIdentity(method, proposedUserIdentities, idCache) {
3656
- // There is an edge case where multiple identity calls are taking place
3657
- // before identify fires, so there may not be a cache. See what happens when
3658
- // the ? in idCache is removed to the following test
3659
- // "queued events contain login mpid instead of identify mpid when calling
3660
- // login immediately after mParticle initializes"
3661
- var cache = idCache === null || idCache === void 0 ? void 0 : idCache.retrieve();
3662
- // if there is no cache, then there is no valid cached identity
3663
- if (!cache) {
3664
- return false;
3665
- }
3666
- var cacheKey = concatenateIdentities(method, proposedUserIdentities);
3667
- var hashedKey = generateHash(cacheKey);
3668
- // if cache doesn't have the cacheKey, there is no valid cached identity
3669
- if (!cache.hasOwnProperty(hashedKey)) {
3670
- return false;
3671
- }
3672
- // If there is a valid cache key, compare the expireTimestamp to the current time.
3673
- // If the current time is greater than the expireTimestamp, it is not a valid
3674
- // cached identity.
3675
- var expireTimestamp = cache[hashedKey].expireTimestamp;
3676
- if (expireTimestamp < new Date().getTime()) {
3677
- return false;
3678
- } else {
3679
- return true;
3680
- }
3681
- };
3682
- var getCachedIdentity = function getCachedIdentity(method, proposedUserIdentities, idCache) {
3683
- var cacheKey = concatenateIdentities(method, proposedUserIdentities);
3684
- var hashedKey = generateHash(cacheKey);
3685
- var cache = idCache.retrieve();
3686
- var cachedIdentity = cache ? cache[hashedKey] : null;
3687
- return {
3688
- responseText: parseIdentityResponse(cachedIdentity.responseText),
3689
- expireTimestamp: cachedIdentity.expireTimestamp,
3690
- status: cachedIdentity.status
3691
- };
3692
- };
3693
- // https://go.mparticle.com/work/SQDSDKS-6079
3694
- var createKnownIdentities = function createKnownIdentities(identityApiData, deviceId) {
3695
- var identitiesResult = {};
3696
- if (isObject(identityApiData === null || identityApiData === void 0 ? void 0 : identityApiData.userIdentities)) {
3697
- for (var identity in identityApiData.userIdentities) {
3698
- identitiesResult[identity] = identityApiData.userIdentities[identity];
3699
- }
3700
- }
3701
- identitiesResult.device_application_stamp = deviceId;
3702
- return identitiesResult;
3703
- };
3704
- var removeExpiredIdentityCacheDates = function removeExpiredIdentityCacheDates(idCache) {
3705
- var cache = idCache.retrieve() || {};
3706
- var currentTime = new Date().getTime();
3707
- // Iterate over the cache and remove any key/value pairs that are expired
3708
- for (var key in cache) {
3709
- if (cache[key].expireTimestamp < currentTime) {
3710
- delete cache[key];
3711
- }
3712
- }
3713
- idCache.store(cache);
3714
- };
3715
- var tryCacheIdentity = function tryCacheIdentity(knownIdentities, idCache, parseIdentityResponse, mpid, callback, identityApiData, identityMethod) {
3716
- // https://go.mparticle.com/work/SQDSDKS-6095
3717
- var shouldReturnCachedIdentity = hasValidCachedIdentity(identityMethod, knownIdentities, idCache);
3718
- // If Identity is cached, then immediately parse the identity response
3719
- if (shouldReturnCachedIdentity) {
3720
- var cachedIdentity = getCachedIdentity(identityMethod, knownIdentities, idCache);
3721
- parseIdentityResponse(cachedIdentity, mpid, callback, identityApiData, identityMethod, knownIdentities, true);
3722
- return true;
3723
- }
3724
- return false;
3725
- };
3726
- var getExpireTimestamp = function getExpireTimestamp(maxAge) {
3727
- if (maxAge === void 0) {
3728
- maxAge = ONE_DAY_IN_SECONDS;
3729
- }
3730
- return new Date().getTime() + maxAge * MILLIS_IN_ONE_SEC;
3731
- };
3732
- var parseIdentityResponse = function parseIdentityResponse(responseText) {
3733
- return responseText ? JSON.parse(responseText) : {};
3734
- };
3735
- var hasIdentityRequestChanged = function hasIdentityRequestChanged(currentUser, newIdentityRequest) {
3736
- if (!currentUser || !(newIdentityRequest === null || newIdentityRequest === void 0 ? void 0 : newIdentityRequest.userIdentities)) {
3737
- return false;
3738
- }
3739
- var currentUserIdentities = currentUser.getUserIdentities().userIdentities;
3740
- var newIdentities = newIdentityRequest.userIdentities;
3741
- return JSON.stringify(currentUserIdentities) !== JSON.stringify(newIdentities);
3742
- };
3743
-
3744
3860
  var Messages$6 = Constants.Messages;
3745
3861
  function SessionManager(mpInstance) {
3746
3862
  var self = this;
3747
3863
  this.initialize = function () {
3864
+ var _a;
3748
3865
  if (mpInstance._Store.sessionId) {
3749
- var _a = mpInstance._Store,
3750
- dateLastEventSent = _a.dateLastEventSent,
3751
- SDKConfig = _a.SDKConfig;
3866
+ var _b = mpInstance._Store,
3867
+ dateLastEventSent = _b.dateLastEventSent,
3868
+ SDKConfig = _b.SDKConfig;
3752
3869
  var sessionTimeout = SDKConfig.sessionTimeout;
3753
3870
  if (hasSessionTimedOut(dateLastEventSent === null || dateLastEventSent === void 0 ? void 0 : dateLastEventSent.getTime(), sessionTimeout)) {
3754
3871
  self.endSession();
@@ -3758,7 +3875,8 @@ var mParticle = (function () {
3758
3875
  // https://go.mparticle.com/work/SQDSDKS-6323
3759
3876
  var currentUser = mpInstance.Identity.getCurrentUser();
3760
3877
  var sdkIdentityRequest = SDKConfig.identifyRequest;
3761
- if (hasIdentityRequestChanged(currentUser, sdkIdentityRequest)) {
3878
+ var shouldSuppressIdentify = ((_a = mpInstance._CookieConsentManager) === null || _a === void 0 ? void 0 : _a.getNoFunctional()) && !hasExplicitIdentifier(mpInstance._Store);
3879
+ if (!shouldSuppressIdentify && hasIdentityRequestChanged(currentUser, sdkIdentityRequest)) {
3762
3880
  mpInstance.Identity.identify(sdkIdentityRequest, SDKConfig.identityCallback);
3763
3881
  mpInstance._Store.identifyCalled = true;
3764
3882
  mpInstance._Store.SDKConfig.identityCallback = null;
@@ -3776,6 +3894,7 @@ var mParticle = (function () {
3776
3894
  return mpInstance._Store.sessionId;
3777
3895
  };
3778
3896
  this.startNewSession = function () {
3897
+ var _a;
3779
3898
  mpInstance.Logger.verbose(Messages$6.InformationMessages.StartingNewSession);
3780
3899
  if (mpInstance._Helpers.canLog()) {
3781
3900
  mpInstance._Store.sessionId = mpInstance._Helpers.generateUniqueId().toUpperCase();
@@ -3790,7 +3909,8 @@ var mParticle = (function () {
3790
3909
  mpInstance._Store.dateLastEventSent = date;
3791
3910
  }
3792
3911
  self.setSessionTimer();
3793
- if (!mpInstance._Store.identifyCalled) {
3912
+ var shouldSuppressIdentify = ((_a = mpInstance._CookieConsentManager) === null || _a === void 0 ? void 0 : _a.getNoFunctional()) && !hasExplicitIdentifier(mpInstance._Store);
3913
+ if (!mpInstance._Store.identifyCalled && !shouldSuppressIdentify) {
3794
3914
  mpInstance.Identity.identify(mpInstance._Store.SDKConfig.identifyRequest, mpInstance._Store.SDKConfig.identityCallback);
3795
3915
  mpInstance._Store.identifyCalled = true;
3796
3916
  mpInstance._Store.SDKConfig.identityCallback = null;
@@ -4316,14 +4436,20 @@ var mParticle = (function () {
4316
4436
  }
4317
4437
 
4318
4438
  var ForegroundTimeTracker = /** @class */function () {
4319
- function ForegroundTimeTracker(timerKey) {
4439
+ function ForegroundTimeTracker(timerKey, noFunctional) {
4440
+ if (noFunctional === void 0) {
4441
+ noFunctional = false;
4442
+ }
4443
+ this.noFunctional = noFunctional;
4320
4444
  this.isTrackerActive = false;
4321
4445
  this.localStorageName = '';
4322
4446
  this.startTime = 0;
4323
4447
  this.totalTime = 0;
4324
4448
  this.localStorageName = "mprtcl-tos-".concat(timerKey);
4325
4449
  this.timerVault = new LocalStorageVault(this.localStorageName);
4326
- this.loadTimeFromStorage();
4450
+ if (!this.noFunctional) {
4451
+ this.loadTimeFromStorage();
4452
+ }
4327
4453
  this.addHandlers();
4328
4454
  if (document.hidden === false) {
4329
4455
  this.startTracking();
@@ -4376,7 +4502,7 @@ var mParticle = (function () {
4376
4502
  }
4377
4503
  };
4378
4504
  ForegroundTimeTracker.prototype.updateTimeInPersistence = function () {
4379
- if (this.isTrackerActive) {
4505
+ if (this.isTrackerActive && !this.noFunctional) {
4380
4506
  this.timerVault.store(Math.round(this.totalTime));
4381
4507
  }
4382
4508
  };
@@ -4774,6 +4900,7 @@ var mParticle = (function () {
4774
4900
  mpInstance._Persistence.update();
4775
4901
  };
4776
4902
  this.processConfig = function (config) {
4903
+ var _a;
4777
4904
  var workspaceToken = config.workspaceToken,
4778
4905
  requiredWebviewBridgeName = config.requiredWebviewBridgeName;
4779
4906
  // We should reprocess the flags and baseUrls in case they have changed when we request an updated config
@@ -4789,7 +4916,8 @@ var mParticle = (function () {
4789
4916
  }
4790
4917
  if (workspaceToken) {
4791
4918
  _this.SDKConfig.workspaceToken = workspaceToken;
4792
- mpInstance._timeOnSiteTimer = new ForegroundTimeTracker(workspaceToken);
4919
+ var noFunctional = ((_a = config === null || config === void 0 ? void 0 : config.launcherOptions) === null || _a === void 0 ? void 0 : _a.noFunctional) === true;
4920
+ mpInstance._timeOnSiteTimer = new ForegroundTimeTracker(workspaceToken, noFunctional);
4793
4921
  } else {
4794
4922
  mpInstance.Logger.warning('You should have a workspaceToken on your config object for security purposes.');
4795
4923
  }
@@ -4925,6 +5053,9 @@ var mParticle = (function () {
4925
5053
  }
4926
5054
  }
4927
5055
  };
5056
+ Logger.prototype.isVerbose = function () {
5057
+ return this.logLevel === LogLevelType.Verbose;
5058
+ };
4928
5059
  Logger.prototype.setLogLevel = function (newLogLevel) {
4929
5060
  this.logLevel = newLogLevel;
4930
5061
  };
@@ -5123,9 +5254,15 @@ var mParticle = (function () {
5123
5254
 
5124
5255
  // https://go.mparticle.com/work/SQDSDKS-6021
5125
5256
  this.setLocalStorage = function () {
5257
+ var _mpInstance$_CookieCo;
5126
5258
  if (!mpInstance._Store.isLocalStorageAvailable) {
5127
5259
  return;
5128
5260
  }
5261
+
5262
+ // Block mprtcl-v4 localStorage when noFunctional is true
5263
+ if ((_mpInstance$_CookieCo = mpInstance._CookieConsentManager) !== null && _mpInstance$_CookieCo !== void 0 && _mpInstance$_CookieCo.getNoFunctional()) {
5264
+ return;
5265
+ }
5129
5266
  var key = mpInstance._Store.storageName,
5130
5267
  localStorageData = self.getLocalStorage() || {},
5131
5268
  currentUser = mpInstance.Identity.getCurrentUser(),
@@ -5251,6 +5388,11 @@ var mParticle = (function () {
5251
5388
  // https://go.mparticle.com/work/SQDSDKS-5022
5252
5389
  // https://go.mparticle.com/work/SQDSDKS-6021
5253
5390
  this.setCookie = function () {
5391
+ var _mpInstance$_CookieCo2;
5392
+ // Block mprtcl-v4 cookies when noFunctional is true
5393
+ if ((_mpInstance$_CookieCo2 = mpInstance._CookieConsentManager) !== null && _mpInstance$_CookieCo2 !== void 0 && _mpInstance$_CookieCo2.getNoFunctional()) {
5394
+ return;
5395
+ }
5254
5396
  var mpid,
5255
5397
  currentUser = mpInstance.Identity.getCurrentUser();
5256
5398
  if (currentUser) {
@@ -5526,6 +5668,11 @@ var mParticle = (function () {
5526
5668
 
5527
5669
  // https://go.mparticle.com/work/SQDSDKS-6021
5528
5670
  this.savePersistence = function (persistence) {
5671
+ var _mpInstance$_CookieCo3;
5672
+ // Block mprtcl-v4 persistence when noFunctional is true
5673
+ if ((_mpInstance$_CookieCo3 = mpInstance._CookieConsentManager) !== null && _mpInstance$_CookieCo3 !== void 0 && _mpInstance$_CookieCo3.getNoFunctional()) {
5674
+ return;
5675
+ }
5529
5676
  var encodedPersistence = self.encodePersistence(JSON.stringify(persistence)),
5530
5677
  date = new Date(),
5531
5678
  key = mpInstance._Store.storageName,
@@ -9295,7 +9442,7 @@ var mParticle = (function () {
9295
9442
  this.sendIdentityRequest = function (identityApiRequest, method, callback, originalIdentityApiData, parseIdentityResponse, mpid, knownIdentities) {
9296
9443
  var _a, _b, _c, _d;
9297
9444
  return __awaiter(this, void 0, void 0, function () {
9298
- var requestCount, invokeCallback, Logger, previousMPID, uploadUrl, uploader, fetchPayload, response, identityResponse, message, _e, responseBody, errorResponse, errorMessage, errorMessage, requestCount, err_1, requestCount, errorMessage;
9445
+ var requestCount, invokeCallback, Logger, previousMPID, uploadUrl, uploader, fetchPayload, response, identityResponse, message, _e, responseBody, errorResponse, errorMessage, responseText, isDevelopmentMode, responseToLog, errorMessage, requestCount, err_1, requestCount, errorMessage;
9299
9446
  return __generator(this, function (_f) {
9300
9447
  switch (_f.label) {
9301
9448
  case 0:
@@ -9369,9 +9516,16 @@ var mParticle = (function () {
9369
9516
  }).join(', ');
9370
9517
  message += ' - ' + errorMessage;
9371
9518
  }
9372
- } else {
9373
- message = 'Received Identity Response from server: ';
9374
- message += JSON.stringify(identityResponse.responseText);
9519
+ } else if (Logger.isVerbose()) {
9520
+ responseText = identityResponse.responseText;
9521
+ isDevelopmentMode = mpInstance._Store.SDKConfig.isDevelopmentMode;
9522
+ responseToLog = responseText;
9523
+ if (!isDevelopmentMode && (responseText === null || responseText === void 0 ? void 0 : responseText.matched_identities)) {
9524
+ responseToLog = __assign(__assign({}, responseText), {
9525
+ matched_identities: obfuscateData(responseText.matched_identities)
9526
+ });
9527
+ }
9528
+ message = 'Received Identity Response from server: ' + JSON.stringify(responseToLog);
9375
9529
  }
9376
9530
  return [3 /*break*/, 8];
9377
9531
  case 7:
@@ -9389,7 +9543,9 @@ var mParticle = (function () {
9389
9543
  case 8:
9390
9544
  mpInstance._Store.identityCallInFlight = false;
9391
9545
  mpInstance._Store.identityCallFailed = false;
9392
- Logger.verbose(message);
9546
+ if (message) {
9547
+ Logger.verbose(message);
9548
+ }
9393
9549
  if ((_b = mpInstance._RoktManager) === null || _b === void 0 ? void 0 : _b.isInitialized) {
9394
9550
  requestCount = mpInstance._Store.identifyRequestCount;
9395
9551
  mpInstance.captureTiming("".concat(requestCount, "-identityRequestEnd"));
@@ -9856,27 +10012,30 @@ var mParticle = (function () {
9856
10012
  * });
9857
10013
  */
9858
10014
  RoktManager.prototype.selectPlacements = function (options) {
9859
- var _a, _b, _c, _d, _e, _f, _g;
10015
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
9860
10016
  return __awaiter(this, void 0, void 0, function () {
9861
- var attributes, sandboxValue, mappedAttributes, currentUserIdentities_1, currentEmail, newEmail, currentHashedEmail, newHashedEmail, isValidHashedEmailIdentityType, emailChanged, hashedEmailChanged, newIdentities_1, error_1, finalUserIdentities, enrichedAttributes, hashedEmail, enrichedOptions, error_2;
10017
+ var attributes, sandboxValue, mappedAttributes, attributesToLog, currentUserIdentities_1, currentEmail, newEmail, currentHashedEmail, newHashedEmail, isValidHashedEmailIdentityType, emailChanged, hashedEmailChanged, newIdentities_1, error_1, errorMessage, finalUserIdentities, enrichedAttributes, hashedEmail, enrichedOptions, error_2;
9862
10018
  var _this = this;
9863
- return __generator(this, function (_h) {
9864
- switch (_h.label) {
10019
+ return __generator(this, function (_k) {
10020
+ switch (_k.label) {
9865
10021
  case 0:
9866
10022
  (_a = this.captureTiming) === null || _a === void 0 ? void 0 : _a.call(this, PerformanceMarkType.JointSdkSelectPlacements);
9867
10023
  // Queue if kit isn't ready OR if identity is in flight
9868
10024
  if (!this.isReady() || ((_b = this.store) === null || _b === void 0 ? void 0 : _b.identityCallInFlight)) {
9869
10025
  return [2 /*return*/, this.deferredCall('selectPlacements', options)];
9870
10026
  }
9871
- _h.label = 1;
10027
+ _k.label = 1;
9872
10028
  case 1:
9873
- _h.trys.push([1, 6,, 7]);
10029
+ _k.trys.push([1, 6,, 7]);
9874
10030
  attributes = options.attributes;
9875
10031
  sandboxValue = (attributes === null || attributes === void 0 ? void 0 : attributes.sandbox) || null;
9876
10032
  mappedAttributes = this.mapPlacementAttributes(attributes, this.placementAttributesMapping);
9877
- (_c = this.logger) === null || _c === void 0 ? void 0 : _c.verbose("mParticle.Rokt selectPlacements called with attributes:\n".concat(JSON.stringify(attributes, null, 2)));
10033
+ if ((_c = this.logger) === null || _c === void 0 ? void 0 : _c.isVerbose()) {
10034
+ attributesToLog = obfuscateDevData(attributes, (_e = (_d = this.store) === null || _d === void 0 ? void 0 : _d.SDKConfig) === null || _e === void 0 ? void 0 : _e.isDevelopmentMode);
10035
+ this.logger.verbose("mParticle.Rokt selectPlacements called with attributes:\n".concat(JSON.stringify(attributesToLog, null, 2)));
10036
+ }
9878
10037
  this.currentUser = this.identityService.getCurrentUser();
9879
- currentUserIdentities_1 = ((_e = (_d = this.currentUser) === null || _d === void 0 ? void 0 : _d.getUserIdentities()) === null || _e === void 0 ? void 0 : _e.userIdentities) || {};
10038
+ currentUserIdentities_1 = ((_g = (_f = this.currentUser) === null || _f === void 0 ? void 0 : _f.getUserIdentities()) === null || _g === void 0 ? void 0 : _g.userIdentities) || {};
9880
10039
  currentEmail = currentUserIdentities_1.email;
9881
10040
  newEmail = mappedAttributes.email;
9882
10041
  currentHashedEmail = void 0;
@@ -9900,9 +10059,9 @@ var mParticle = (function () {
9900
10059
  this.logger.warning("emailsha256 mismatch detected. Current mParticle hashedEmail differs from hashedEmail passed to selectPlacements call. Proceeding to call identify with hashedEmail from selectPlacements call. Please verify your implementation.");
9901
10060
  }
9902
10061
  if (!!isEmpty(newIdentities_1)) return [3 /*break*/, 5];
9903
- _h.label = 2;
10062
+ _k.label = 2;
9904
10063
  case 2:
9905
- _h.trys.push([2, 4,, 5]);
10064
+ _k.trys.push([2, 4,, 5]);
9906
10065
  return [4 /*yield*/, new Promise(function (resolve, reject) {
9907
10066
  _this.identityService.identify({
9908
10067
  userIdentities: __assign(__assign({}, currentUserIdentities_1), newIdentities_1)
@@ -9911,16 +10070,17 @@ var mParticle = (function () {
9911
10070
  });
9912
10071
  })];
9913
10072
  case 3:
9914
- _h.sent();
10073
+ _k.sent();
9915
10074
  return [3 /*break*/, 5];
9916
10075
  case 4:
9917
- error_1 = _h.sent();
9918
- this.logger.error('Failed to identify user with new email: ' + JSON.stringify(error_1));
10076
+ error_1 = _k.sent();
10077
+ errorMessage = error_1 instanceof Error ? error_1.message : JSON.stringify(error_1);
10078
+ this.logger.error('Failed to identify user with updated identities: ' + errorMessage);
9919
10079
  return [3 /*break*/, 5];
9920
10080
  case 5:
9921
10081
  // Refresh current user identities to ensure we have the latest values before building enrichedAttributes
9922
10082
  this.currentUser = this.identityService.getCurrentUser();
9923
- finalUserIdentities = ((_g = (_f = this.currentUser) === null || _f === void 0 ? void 0 : _f.getUserIdentities()) === null || _g === void 0 ? void 0 : _g.userIdentities) || {};
10083
+ finalUserIdentities = ((_j = (_h = this.currentUser) === null || _h === void 0 ? void 0 : _h.getUserIdentities()) === null || _j === void 0 ? void 0 : _j.userIdentities) || {};
9924
10084
  this.setUserAttributes(mappedAttributes);
9925
10085
  enrichedAttributes = __assign(__assign({}, mappedAttributes), sandboxValue !== null ? {
9926
10086
  sandbox: sandboxValue
@@ -9942,7 +10102,7 @@ var mParticle = (function () {
9942
10102
  });
9943
10103
  return [2 /*return*/, this.kit.selectPlacements(enrichedOptions)];
9944
10104
  case 6:
9945
- error_2 = _h.sent();
10105
+ error_2 = _k.sent();
9946
10106
  return [2 /*return*/, Promise.reject(error_2 instanceof Error ? error_2 : new Error('Unknown error occurred'))];
9947
10107
  case 7:
9948
10108
  return [2 /*return*/];
@@ -10133,12 +10293,15 @@ var mParticle = (function () {
10133
10293
  // Clear the queue immediately to prevent re-processing
10134
10294
  this.messageQueue.clear();
10135
10295
  messagesToProcess.forEach(function (message) {
10136
- var _a, _b;
10296
+ var _a, _b, _c, _d;
10137
10297
  if (!(message.methodName in _this) || !isFunction(_this[message.methodName])) {
10138
10298
  (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.error("RoktManager: Method ".concat(message.methodName, " not found"));
10139
10299
  return;
10140
10300
  }
10141
- (_b = _this.logger) === null || _b === void 0 ? void 0 : _b.verbose("RoktManager: Processing queued message: ".concat(message.methodName, " with payload: ").concat(JSON.stringify(message.payload)));
10301
+ if ((_b = _this.logger) === null || _b === void 0 ? void 0 : _b.isVerbose()) {
10302
+ var payloadToLog = obfuscateDevData(message.payload, (_d = (_c = _this.store) === null || _c === void 0 ? void 0 : _c.SDKConfig) === null || _d === void 0 ? void 0 : _d.isDevelopmentMode);
10303
+ _this.logger.verbose("RoktManager: Processing queued message: ".concat(message.methodName, " with payload: ").concat(JSON.stringify(payloadToLog)));
10304
+ }
10142
10305
  // Capture resolve/reject functions before async processing
10143
10306
  var resolve = message.resolve;
10144
10307
  var reject = message.reject;
@@ -10466,6 +10629,19 @@ var mParticle = (function () {
10466
10629
  self._preInit.readyQueue = processReadyQueue(self._preInit.readyQueue);
10467
10630
  }
10468
10631
  };
10632
+ /**
10633
+ * Drains the ready queue for noFunctional sessions with no explicit identity.
10634
+ */
10635
+ this.processQueueOnNoFunctional = function () {
10636
+ var _a, _b;
10637
+ if ((_a = self._Store) === null || _a === void 0 ? void 0 : _a.isInitialized) {
10638
+ return;
10639
+ }
10640
+ var noFunctionalWithoutId = ((_b = self._CookieConsentManager) === null || _b === void 0 ? void 0 : _b.getNoFunctional()) && !hasExplicitIdentifier(self._Store);
10641
+ if (noFunctionalWithoutId) {
10642
+ self._preInit.readyQueue = processReadyQueue(self._preInit.readyQueue);
10643
+ }
10644
+ };
10469
10645
  // required for forwarders once they reference the mparticle instance
10470
10646
  this.IdentityType = IdentityType;
10471
10647
  this.EventType = EventType;
@@ -10563,8 +10739,9 @@ var mParticle = (function () {
10563
10739
  * @param {Function} f Callback to execute
10564
10740
  */
10565
10741
  this.ready = function (f) {
10566
- var _a, _b;
10567
- var shouldExecute = isFunction(f) && (((_a = self._Store) === null || _a === void 0 ? void 0 : _a.isInitialized) || ((_b = self._Store) === null || _b === void 0 ? void 0 : _b.identityCallFailed) && self._RoktManager.isReady());
10742
+ var _a, _b, _c;
10743
+ var noFunctionalWithoutId = ((_a = self._CookieConsentManager) === null || _a === void 0 ? void 0 : _a.getNoFunctional()) && !hasExplicitIdentifier(self._Store);
10744
+ var shouldExecute = isFunction(f) && (((_b = self._Store) === null || _b === void 0 ? void 0 : _b.isInitialized) || ((_c = self._Store) === null || _c === void 0 ? void 0 : _c.identityCallFailed) && self._RoktManager.isReady() || noFunctionalWithoutId);
10568
10745
  if (shouldExecute) {
10569
10746
  f();
10570
10747
  } else {
@@ -11168,10 +11345,14 @@ var mParticle = (function () {
11168
11345
  * @param {String or Number} value value for session attribute
11169
11346
  */
11170
11347
  this.setSessionAttribute = function (key, value) {
11171
- var queued = queueIfNotInitialized(function () {
11172
- self.setSessionAttribute(key, value);
11173
- }, self);
11174
- if (queued) return;
11348
+ var _a;
11349
+ var skipQueue = ((_a = self._CookieConsentManager) === null || _a === void 0 ? void 0 : _a.getNoFunctional()) && !hasExplicitIdentifier(self._Store);
11350
+ if (!skipQueue) {
11351
+ var queued = queueIfNotInitialized(function () {
11352
+ self.setSessionAttribute(key, value);
11353
+ }, self);
11354
+ if (queued) return;
11355
+ }
11175
11356
  // Logs to cookie
11176
11357
  // And logs to in-memory object
11177
11358
  // Example: mParticle.setSessionAttribute('location', '33431');
@@ -11369,7 +11550,7 @@ var mParticle = (function () {
11369
11550
  }
11370
11551
  // Some (server) config settings need to be returned before they are set on SDKConfig in a self hosted environment
11371
11552
  function completeSDKInitialization(apiKey, config, mpInstance) {
11372
- var _a;
11553
+ var _a, _b;
11373
11554
  var kitBlocker = createKitBlocker(config, mpInstance);
11374
11555
  var getFeatureFlag = mpInstance._Helpers.getFeatureFlag;
11375
11556
  mpInstance._APIClient = new APIClient(mpInstance, kitBlocker);
@@ -11443,6 +11624,9 @@ var mParticle = (function () {
11443
11624
  mpInstance._Store.isInitialized = true;
11444
11625
  mpInstance._preInit.readyQueue = processReadyQueue(mpInstance._preInit.readyQueue);
11445
11626
  }
11627
+ // For noFunctional sessions with no identity, drain any pre-init ready callbacks
11628
+ // that were queued before _CookieConsentManager was available to evaluate the condition.
11629
+ (_b = mpInstance.processQueueOnNoFunctional) === null || _b === void 0 ? void 0 : _b.call(mpInstance);
11446
11630
  // https://go.mparticle.com/work/SQDSDKS-6040
11447
11631
  if (mpInstance._Store.isFirstRun) {
11448
11632
  mpInstance._Store.isFirstRun = false;
@@ -11508,9 +11692,13 @@ var mParticle = (function () {
11508
11692
  return kitBlocker;
11509
11693
  }
11510
11694
  function createIdentityCache(mpInstance) {
11511
- return new LocalStorageVault("".concat(mpInstance._Store.storageName, "-id-cache"), {
11512
- logger: mpInstance.Logger
11513
- });
11695
+ var _a;
11696
+ // Identity expects mpInstance._Identity.idCache to always exist. DisabledVault
11697
+ // ensures no identity response data is written to localStorage when noFunctional is true
11698
+ if ((_a = mpInstance._CookieConsentManager) === null || _a === void 0 ? void 0 : _a.getNoFunctional()) {
11699
+ return new DisabledVault("".concat(mpInstance._Store.storageName, "-id-cache"));
11700
+ }
11701
+ return new LocalStorageVault("".concat(mpInstance._Store.storageName, "-id-cache"));
11514
11702
  }
11515
11703
  function runPreConfigFetchInitialization(mpInstance, apiKey, config) {
11516
11704
  var _a;
@@ -11570,18 +11758,21 @@ var mParticle = (function () {
11570
11758
  }
11571
11759
  }
11572
11760
  function queueIfNotInitialized(func, self) {
11573
- var _a;
11574
- // Core SDK methods must wait for Store initialization
11575
- if (!((_a = self._Store) === null || _a === void 0 ? void 0 : _a.isInitialized)) {
11576
- self._preInit.readyQueue.push(function () {
11577
- var _a;
11578
- if ((_a = self._Store) === null || _a === void 0 ? void 0 : _a.isInitialized) {
11579
- func();
11580
- }
11581
- });
11582
- return true;
11761
+ var _a, _b;
11762
+ // When noFunctional is true with no explicit identifier, the SDK will never
11763
+ // receive an MPID. Let these calls through so events can still reach forwarders immediately.
11764
+ // sendEventToServer handles queuing for the MP server upload path separately.
11765
+ var noFunctionalWithoutId = ((_a = self._CookieConsentManager) === null || _a === void 0 ? void 0 : _a.getNoFunctional()) && !hasExplicitIdentifier(self._Store);
11766
+ if (((_b = self._Store) === null || _b === void 0 ? void 0 : _b.isInitialized) || noFunctionalWithoutId) {
11767
+ return false;
11583
11768
  }
11584
- return false;
11769
+ self._preInit.readyQueue.push(function () {
11770
+ var _a;
11771
+ if ((_a = self._Store) === null || _a === void 0 ? void 0 : _a.isInitialized) {
11772
+ func();
11773
+ }
11774
+ });
11775
+ return true;
11585
11776
  }
11586
11777
 
11587
11778
  // This file is used ONLY for the mParticle ESLint plugin. It should NOT be used otherwise!