@mparticle/web-sdk 2.73.0 → 2.74.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.73.0";
206
+ var version = "2.74.0";
207
207
 
208
208
  var Constants = {
209
209
  sdkVersion: version,
@@ -383,7 +383,8 @@ var mParticle = (function () {
383
383
  // - 'none' → capture none
384
384
  // - 'roktonly' → capture only Rokt-related IDs
385
385
  CaptureIntegrationSpecificIdsV2: 'captureIntegrationSpecificIds.V2',
386
- AstBackgroundEvents: 'astBackgroundEvents'
386
+ AstBackgroundEvents: 'astBackgroundEvents',
387
+ AutoLogPageView: 'autoLogPageView'
387
388
  },
388
389
  DefaultInstance: 'default_instance',
389
390
  CCPAPurpose: 'data_sale_opt_out',
@@ -1013,6 +1014,22 @@ var mParticle = (function () {
1013
1014
  }
1014
1015
  return target;
1015
1016
  }
1017
+ var getErrorMessage = function getErrorMessage(e, fallback) {
1018
+ if (fallback === void 0) {
1019
+ fallback = 'unknown error';
1020
+ }
1021
+ if (e instanceof Error) {
1022
+ return e.message;
1023
+ }
1024
+ if (typeof e === 'string') {
1025
+ return e;
1026
+ }
1027
+ // fetch-mock and some network libs reject with { message } rather than Error
1028
+ if (e && _typeof$1(e) === 'object' && typeof e.message === 'string') {
1029
+ return e.message;
1030
+ }
1031
+ return fallback;
1032
+ };
1016
1033
 
1017
1034
  var MessageType$1 = {
1018
1035
  SessionStart: 1,
@@ -3234,7 +3251,7 @@ var mParticle = (function () {
3234
3251
  try {
3235
3252
  callback(result);
3236
3253
  } catch (e) {
3237
- logger.error('Error invoking search callback: ' + ((e === null || e === void 0 ? void 0 : e.message) || String(e)));
3254
+ logger.error('Error invoking search callback: ' + getErrorMessage(e));
3238
3255
  }
3239
3256
  };
3240
3257
  cleanedKnownIdentities = Validators.removeFalsyIdentityValues({
@@ -3323,7 +3340,7 @@ var mParticle = (function () {
3323
3340
  return [3 /*break*/, 10];
3324
3341
  case 9:
3325
3342
  e_2 = _a.sent();
3326
- message = (e_2 === null || e_2 === void 0 ? void 0 : e_2.message) || String(e_2);
3343
+ message = getErrorMessage(e_2);
3327
3344
  reportMessage = 'Error sending search request: ' + message;
3328
3345
  logger.error(reportMessage);
3329
3346
  // Mirror the identity-route pattern in identityApiClient.ts: log to
@@ -3589,7 +3606,7 @@ var mParticle = (function () {
3589
3606
  httpCode: HTTPCodes$3.loggingDisabledOrMissingAPIKey
3590
3607
  });
3591
3608
  } catch (e) {
3592
- Logger.error('Error invoking search callback: ' + ((e === null || e === void 0 ? void 0 : e.message) || String(e)));
3609
+ Logger.error('Error invoking search callback: ' + getErrorMessage(e));
3593
3610
  }
3594
3611
  }
3595
3612
  return;
@@ -5387,7 +5404,8 @@ var mParticle = (function () {
5387
5404
  AudienceAPI = _a.AudienceAPI,
5388
5405
  CaptureIntegrationSpecificIds = _a.CaptureIntegrationSpecificIds,
5389
5406
  CaptureIntegrationSpecificIdsV2 = _a.CaptureIntegrationSpecificIdsV2,
5390
- AstBackgroundEvents = _a.AstBackgroundEvents;
5407
+ AstBackgroundEvents = _a.AstBackgroundEvents,
5408
+ AutoLogPageView = _a.AutoLogPageView;
5391
5409
  if (!config.flags) {
5392
5410
  return {};
5393
5411
  }
@@ -5403,6 +5421,7 @@ var mParticle = (function () {
5403
5421
  flags[CaptureIntegrationSpecificIds] = config.flags[CaptureIntegrationSpecificIds] === 'True';
5404
5422
  flags[CaptureIntegrationSpecificIdsV2] = config.flags[CaptureIntegrationSpecificIdsV2] || 'none';
5405
5423
  flags[AstBackgroundEvents] = config.flags[AstBackgroundEvents] === 'True';
5424
+ flags[AutoLogPageView] = config.flags[AutoLogPageView] === 'True';
5406
5425
  return flags;
5407
5426
  }
5408
5427
  function processBaseUrls(config, flags, apiKey) {
@@ -6325,6 +6344,17 @@ var mParticle = (function () {
6325
6344
  messageType: Types.MessageType.AppStateTransition
6326
6345
  });
6327
6346
  };
6347
+ this.logPageView = function () {
6348
+ self.logEvent({
6349
+ messageType: Types.MessageType.PageView,
6350
+ name: 'PageView',
6351
+ data: {
6352
+ hostname: window.location.hostname,
6353
+ title: window.document.title
6354
+ },
6355
+ eventType: Types.EventType.Unknown
6356
+ });
6357
+ };
6328
6358
  this.logCheckoutEvent = function (step, option, attrs, customFlags) {
6329
6359
  var event = mpInstance._Ecommerce.createCommerceEventObject(customFlags);
6330
6360
  if (event) {
@@ -7911,25 +7941,36 @@ var mParticle = (function () {
7911
7941
  return AudienceManager;
7912
7942
  }();
7913
7943
 
7914
- var processReadyQueue = function processReadyQueue(readyQueue) {
7915
- if (!isEmpty(readyQueue)) {
7916
- readyQueue.forEach(function (readyQueueItem) {
7944
+ var processReadyQueue = function processReadyQueue(readyQueue, logger) {
7945
+ if (isEmpty(readyQueue)) {
7946
+ return [];
7947
+ }
7948
+ // Without draining first, sync re-entry (cache-hit identify →
7949
+ // parseIdentityResponse → processReadyQueue) re-iterates the same array:
7950
+ // callers only replace `_preInit.readyQueue` with [] after we return, so the
7951
+ // nested call still sees every entry. That duplicates Identity/event calls
7952
+ // and can nest "Unable to compute proper mParticle function" wraps.
7953
+ // Splice the queue empty up front so a nested call observes [].
7954
+ var items = readyQueue.splice(0, readyQueue.length);
7955
+ // Isolate each item so one throw cannot abort the rest of this pass.
7956
+ // Drain-first already removed siblings from the shared queue; without a
7957
+ // per-item catch they would be lost forever when forEach aborts.
7958
+ items.forEach(function (readyQueueItem) {
7959
+ try {
7917
7960
  if (isFunction(readyQueueItem)) {
7918
7961
  readyQueueItem();
7919
7962
  } else if (Array.isArray(readyQueueItem)) {
7920
7963
  processPreloadedItem(readyQueueItem);
7921
7964
  }
7922
- });
7923
- }
7965
+ } catch (e) {
7966
+ logger.error('Error processing ready queue item: ' + getErrorMessage(e));
7967
+ }
7968
+ });
7924
7969
  return [];
7925
7970
  };
7926
7971
  var processPreloadedItem = function processPreloadedItem(readyQueueItem) {
7927
- // Operate on a copy of the queued item. The ready queue can be drained more
7928
- // than once (e.g. a synchronous cache-hit identify re-enters processReadyQueue
7929
- // before the outer drain resets the queue). Splicing the shared item array in
7930
- // place would corrupt it on the second pass — ["Identity.login", opts] becomes
7931
- // [opts] — so `method` turns into a non-string/undefined and `method.split('.')`
7932
- // throws. Copying keeps the original item intact for any repeat pass.
7972
+ // Operate on a copy so processPreloadedItem never mutates the caller's
7973
+ // queued item array (defensive; the queue itself is drained above).
7933
7974
  var args = readyQueueItem.slice();
7934
7975
  var method = args.splice(0, 1)[0];
7935
7976
  // Skip malformed queue entries (empty array or non-string method) instead of
@@ -8949,7 +8990,7 @@ var mParticle = (function () {
8949
8990
  }
8950
8991
  mpInstance._Store.isInitialized = true;
8951
8992
  mpInstance._RoktManager.onIdentityComplete();
8952
- mpInstance._preInit.readyQueue = processReadyQueue(mpInstance._preInit.readyQueue);
8993
+ mpInstance._preInit.readyQueue = processReadyQueue(mpInstance._preInit.readyQueue, mpInstance.Logger);
8953
8994
  };
8954
8995
 
8955
8996
  // send a user identity change request on identify, login, logout, modify when any values change.
@@ -9975,7 +10016,7 @@ var mParticle = (function () {
9975
10016
  return [3 /*break*/, 14];
9976
10017
  case 13:
9977
10018
  e_2 = _b.sent();
9978
- errorMessage = e_2.message || e_2.toString();
10019
+ errorMessage = getErrorMessage(e_2);
9979
10020
  Logger.error('Error sending alias request to mParticle servers. ' + errorMessage);
9980
10021
  invokeAliasCallback(aliasCallback, HTTPCodes$1.noHttpCoverage, errorMessage);
9981
10022
  return [3 /*break*/, 14];
@@ -10107,7 +10148,7 @@ var mParticle = (function () {
10107
10148
  requestCount = mpInstance._Store.identifyRequestCount;
10108
10149
  mpInstance.captureTiming("".concat(requestCount, "-identityRequestEnd"));
10109
10150
  }
10110
- errorMessage = err_1.message || err_1.toString();
10151
+ errorMessage = getErrorMessage(err_1);
10111
10152
  msg = 'Error sending identity request to servers' + ' - ' + errorMessage;
10112
10153
  Logger.error(msg);
10113
10154
  errorReporter === null || errorReporter === void 0 ? void 0 : errorReporter.report({
@@ -10576,7 +10617,7 @@ var mParticle = (function () {
10576
10617
  RoktManager.prototype.selectPlacements = function (options) {
10577
10618
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
10578
10619
  return __awaiter(this, void 0, void 0, function () {
10579
- var attributes, sandboxValue, mappedAttributes, attributesToLog, currentUserIdentities, currentEmail, newEmail, currentHashedEmail, newHashedEmail, isValidHashedEmailIdentityType, emailChanged, hashedEmailChanged, newIdentities, msg, msg, errorMessage, finalUserIdentities, enrichedAttributes, hashedEmail, capturedAttrs, passbackId, enrichedOptions;
10620
+ var attributes, sandboxValue, mappedAttributes, attributesToLog, currentUserIdentities, currentEmail, newEmail, currentHashedEmail, newHashedEmail, isValidHashedEmailIdentityType, emailChanged, hashedEmailChanged, newIdentities, msg, msg, finalUserIdentities, enrichedAttributes, hashedEmail, capturedAttrs, passbackId, enrichedOptions;
10580
10621
  var _this = this;
10581
10622
  return __generator(this, function (_o) {
10582
10623
  (_a = this.captureTiming) === null || _a === void 0 ? void 0 : _a.call(this, PerformanceMarkType.JointSdkSelectPlacements);
@@ -10644,8 +10685,7 @@ var mParticle = (function () {
10644
10685
  _this.processMessageQueue();
10645
10686
  });
10646
10687
  } catch (error) {
10647
- errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
10648
- this.logger.error('Background identify threw an error: ' + errorMessage);
10688
+ this.logger.error('Background identify threw an error: ' + getErrorMessage(error));
10649
10689
  }
10650
10690
  }
10651
10691
  finalUserIdentities = __assign(__assign({}, currentUserIdentities), newIdentities);
@@ -10695,7 +10735,7 @@ var mParticle = (function () {
10695
10735
  */
10696
10736
  RoktManager.prototype.hashAttributes = function (attributes) {
10697
10737
  return __awaiter(this, void 0, void 0, function () {
10698
- var keys, hashPromises, results, hashedAttributes, _i, results_1, _a, key, attributeValue, hashedValue, error_1, errorMessage;
10738
+ var keys, hashPromises, results, hashedAttributes, _i, results_1, _a, key, attributeValue, hashedValue, error_1;
10699
10739
  var _this = this;
10700
10740
  return __generator(this, function (_b) {
10701
10741
  switch (_b.label) {
@@ -10741,8 +10781,7 @@ var mParticle = (function () {
10741
10781
  return [2 /*return*/, hashedAttributes];
10742
10782
  case 2:
10743
10783
  error_1 = _b.sent();
10744
- errorMessage = error_1 instanceof Error ? error_1.message : String(error_1);
10745
- this.logger.error("Failed to hashAttributes, returning an empty object: ".concat(errorMessage));
10784
+ this.logger.error("Failed to hashAttributes, returning an empty object: ".concat(getErrorMessage(error_1)));
10746
10785
  return [2 /*return*/, {}];
10747
10786
  case 3:
10748
10787
  return [2 /*return*/];
@@ -10759,8 +10798,7 @@ var mParticle = (function () {
10759
10798
  try {
10760
10799
  this.kit.setExtensionData(extensionData);
10761
10800
  } catch (error) {
10762
- var errorMessage = error instanceof Error ? error.message : String(error);
10763
- throw new Error('Error setting extension data: ' + errorMessage);
10801
+ throw new Error('Error setting extension data: ' + getErrorMessage(error));
10764
10802
  }
10765
10803
  };
10766
10804
  RoktManager.prototype.use = function (name) {
@@ -10781,8 +10819,7 @@ var mParticle = (function () {
10781
10819
  try {
10782
10820
  this.kit.onShoppableAdsReady(callback);
10783
10821
  } catch (error) {
10784
- var errorMessage = error instanceof Error ? error.message : String(error);
10785
- this.logger.error("Failed to register onShoppableAdsReady callback: ".concat(errorMessage));
10822
+ this.logger.error("Failed to register onShoppableAdsReady callback: ".concat(getErrorMessage(error)));
10786
10823
  }
10787
10824
  };
10788
10825
  RoktManager.prototype.flushOnShoppableAdsReadyMessageQueue = function (kit) {
@@ -10810,7 +10847,7 @@ var mParticle = (function () {
10810
10847
  */
10811
10848
  RoktManager.prototype.hashSha256 = function (attribute) {
10812
10849
  return __awaiter(this, void 0, void 0, function () {
10813
- var normalizedValue, error_2, errorMessage;
10850
+ var normalizedValue, error_2;
10814
10851
  return __generator(this, function (_a) {
10815
10852
  switch (_a.label) {
10816
10853
  case 0:
@@ -10827,8 +10864,7 @@ var mParticle = (function () {
10827
10864
  return [2 /*return*/, _a.sent()];
10828
10865
  case 3:
10829
10866
  error_2 = _a.sent();
10830
- errorMessage = error_2 instanceof Error ? error_2.message : String(error_2);
10831
- this.logger.error("Failed to hashSha256, returning undefined: ".concat(errorMessage));
10867
+ this.logger.error("Failed to hashSha256, returning undefined: ".concat(getErrorMessage(error_2)));
10832
10868
  return [2 /*return*/, undefined];
10833
10869
  case 4:
10834
10870
  return [2 /*return*/];
@@ -10909,8 +10945,7 @@ var mParticle = (function () {
10909
10945
  var reject = message.reject;
10910
10946
  var handleError = function handleError(error) {
10911
10947
  var _a;
10912
- var errorMessage = error instanceof Error ? error.message : String(error);
10913
- (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.error("RoktManager: Error processing message '".concat(message.methodName, "': ").concat(errorMessage));
10948
+ (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.error("RoktManager: Error processing message '".concat(message.methodName, "': ").concat(getErrorMessage(error)));
10914
10949
  if (reject) {
10915
10950
  reject(error);
10916
10951
  }
@@ -11148,7 +11183,7 @@ var mParticle = (function () {
11148
11183
  }
11149
11184
  if (((_b = self._Store) === null || _b === void 0 ? void 0 : _b.identityCallFailed) && ((_c = self._RoktManager) === null || _c === void 0 ? void 0 : _c.isReady())) {
11150
11185
  self._RoktManager.processMessageQueue();
11151
- self._preInit.readyQueue = processReadyQueue(self._preInit.readyQueue);
11186
+ self._preInit.readyQueue = processReadyQueue(self._preInit.readyQueue, self.Logger);
11152
11187
  }
11153
11188
  };
11154
11189
  /**
@@ -11161,7 +11196,7 @@ var mParticle = (function () {
11161
11196
  }
11162
11197
  var noFunctionalWithoutId = ((_b = self._CookieConsentManager) === null || _b === void 0 ? void 0 : _b.getNoFunctional()) && !hasExplicitIdentifier(self._Store);
11163
11198
  if (noFunctionalWithoutId) {
11164
- self._preInit.readyQueue = processReadyQueue(self._preInit.readyQueue);
11199
+ self._preInit.readyQueue = processReadyQueue(self._preInit.readyQueue, self.Logger);
11165
11200
  }
11166
11201
  };
11167
11202
  // required for forwarders once they reference the mparticle instance
@@ -12102,6 +12137,7 @@ var mParticle = (function () {
12102
12137
  var _a, _b, _c, _d;
12103
12138
  var kitBlocker = createKitBlocker(config, mpInstance);
12104
12139
  var getFeatureFlag = mpInstance._Helpers.getFeatureFlag;
12140
+ var AutoLogPageView = Constants.FeatureFlags.AutoLogPageView;
12105
12141
  // Destroy previous batch uploader to prevent leaked timers and event listeners
12106
12142
  if ((_a = mpInstance._APIClient) === null || _a === void 0 ? void 0 : _a.uploader) {
12107
12143
  mpInstance._APIClient.uploader.destroy();
@@ -12169,6 +12205,9 @@ var mParticle = (function () {
12169
12205
  // Logs a session start or session end event accordingly
12170
12206
  mpInstance._SessionManager.initialize();
12171
12207
  mpInstance._Events.logAST();
12208
+ if (getFeatureFlag(AutoLogPageView)) {
12209
+ mpInstance._Events.logPageView();
12210
+ }
12172
12211
  processIdentityCallback(mpInstance, currentUser, currentUserMPID, currentUserIdentities);
12173
12212
  }
12174
12213
  // We will continue to clear out the ready queue as part of the initial init flow
@@ -12178,7 +12217,7 @@ var mParticle = (function () {
12178
12217
  // Sync $NoTargeting user attribute on re-init when no identity call is made
12179
12218
  // if for some reason there was a change in boolean between init calls
12180
12219
  (_c = mpInstance._CookieConsentManager) === null || _c === void 0 ? void 0 : _c.syncNoTargetingAttribute(mpInstance.Identity.getCurrentUser());
12181
- mpInstance._preInit.readyQueue = processReadyQueue(mpInstance._preInit.readyQueue);
12220
+ mpInstance._preInit.readyQueue = processReadyQueue(mpInstance._preInit.readyQueue, mpInstance.Logger);
12182
12221
  }
12183
12222
  // For noFunctional sessions with no identity, drain any pre-init ready callbacks
12184
12223
  // that were queued before _CookieConsentManager was available to evaluate the condition.
@@ -167,6 +167,7 @@ declare const Constants: {
167
167
  readonly CaptureIntegrationSpecificIds: "captureIntegrationSpecificIds";
168
168
  readonly CaptureIntegrationSpecificIdsV2: "captureIntegrationSpecificIds.V2";
169
169
  readonly AstBackgroundEvents: "astBackgroundEvents";
170
+ readonly AutoLogPageView: "autoLogPageView";
170
171
  };
171
172
  readonly DefaultInstance: "default_instance";
172
173
  readonly CCPAPurpose: "data_sale_opt_out";
@@ -6,6 +6,7 @@ export default class Events {
6
6
  stopTracking: () => void;
7
7
  logOptOut: () => void;
8
8
  logAST: () => void;
9
+ logPageView: () => void;
9
10
  logCheckoutEvent: (step: any, option: any, attrs: any, customFlags: any) => void;
10
11
  logProductActionEvent: (productActionType: any, product: any, customAttrs: any, customFlags: any, transactionAttributes: any, options: any) => void;
11
12
  logPurchaseEvent: (transactionAttributes: any, product: any, attrs: any, customFlags: any) => void;
@@ -11,6 +11,7 @@ export interface IEvents {
11
11
  logEvent(event: BaseEvent, eventOptions?: SDKEventOptions): void;
12
12
  logImpressionEvent(impression: SDKProductImpression, attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags, eventOptions?: SDKEventOptions): any;
13
13
  logOptOut(): void;
14
+ logPageView(): 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, attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags, eventOptions?: SDKEventOptions): void;
16
17
  logPurchaseEvent(transactionAttributes: TransactionAttributes, product: SDKProduct | SDKProduct[], attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags): void;
@@ -1,6 +1,7 @@
1
1
  import { IPixelConfiguration } from './cookieSyncManager';
2
2
  import { MPForwarder } from './forwarders.interfaces';
3
3
  import { IntegrationDelays } from './mp-instance';
4
+ import { SDKLoggerApi } from './sdkRuntimeModels';
4
5
  export interface IPreInit {
5
6
  readyQueue: Function[] | any[];
6
7
  integrationDelays: IntegrationDelays;
@@ -8,4 +9,4 @@ export interface IPreInit {
8
9
  pixelConfigurations?: IPixelConfiguration[];
9
10
  isDevelopmentMode?: boolean;
10
11
  }
11
- export declare const processReadyQueue: (readyQueue: any) => Function[];
12
+ export declare const processReadyQueue: (readyQueue: any, logger: SDKLoggerApi) => Function[];
@@ -77,6 +77,7 @@ export interface IFeatureFlags {
77
77
  captureIntegrationSpecificIds?: boolean;
78
78
  'captureIntegrationSpecificIds.V2'?: string;
79
79
  astBackgroundEvents?: boolean;
80
+ autoLogPageView?: boolean;
80
81
  }
81
82
  export interface IStore {
82
83
  isEnabled: boolean;
@@ -80,4 +80,5 @@ declare const obfuscateData: (value: any) => any;
80
80
  */
81
81
  declare const obfuscateDevData: (data: any, isDevelopmentMode?: boolean) => any;
82
82
  declare function extend(...args: any[]): any;
83
- export { createCookieString, revertCookieString, createCookieSyncUrl, valueof, AttributeValue, converted, decoded, obfuscateDevData, filterDictionaryWithHash, findKeyInObject, generateDeprecationMessage, generateHash, generateUniqueId, getRampNumber, inArray, isObject, isStringOrNumber, obfuscateData, parseConfig, parseNumber, parseSettingsString, parseStringOrNumber, replaceCommasWithPipes, replacePipesWithCommas, replaceApostrophesWithQuotes, replaceQuotesWithApostrophes, returnConvertedBoolean, toDataPlanSlug, isString, isNumber, isFunction, isDataPlanSlug, isEmpty, isValidAttributeValue, isValidCustomFlagProperty, mergeObjects, moveElementToEnd, queryStringParser, getCookies, getHref, replaceMPID, replaceAmpWithAmpersand, extend, };
83
+ declare const getErrorMessage: (e: unknown, fallback?: string) => string;
84
+ export { createCookieString, revertCookieString, createCookieSyncUrl, valueof, AttributeValue, converted, decoded, obfuscateDevData, filterDictionaryWithHash, findKeyInObject, generateDeprecationMessage, generateHash, generateUniqueId, getErrorMessage, getRampNumber, inArray, isObject, isStringOrNumber, obfuscateData, parseConfig, parseNumber, parseSettingsString, parseStringOrNumber, replaceCommasWithPipes, replacePipesWithCommas, replaceApostrophesWithQuotes, replaceQuotesWithApostrophes, returnConvertedBoolean, toDataPlanSlug, isString, isNumber, isFunction, isDataPlanSlug, isEmpty, isValidAttributeValue, isValidCustomFlagProperty, mergeObjects, moveElementToEnd, queryStringParser, getCookies, getHref, replaceMPID, replaceAmpWithAmpersand, extend, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mparticle/web-sdk",
3
- "version": "2.73.0",
3
+ "version": "2.74.0",
4
4
  "description": "mParticle core SDK for web applications",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
package/src/constants.ts CHANGED
@@ -195,6 +195,7 @@ const Constants = {
195
195
  // - 'roktonly' → capture only Rokt-related IDs
196
196
  CaptureIntegrationSpecificIdsV2: 'captureIntegrationSpecificIds.V2',
197
197
  AstBackgroundEvents: 'astBackgroundEvents',
198
+ AutoLogPageView: 'autoLogPageView',
198
199
  },
199
200
  DefaultInstance: 'default_instance',
200
201
  CCPAPurpose: 'data_sale_opt_out',
@@ -51,6 +51,7 @@ export interface IEvents {
51
51
  eventOptions?: SDKEventOptions
52
52
  );
53
53
  logOptOut(): void;
54
+ logPageView(): void;
54
55
  logProductActionEvent(
55
56
  productActionType: valueof<typeof ProductActionType>,
56
57
  product: SDKProduct | SDKProduct[],
package/src/events.js CHANGED
@@ -99,6 +99,18 @@ export default function Events(mpInstance) {
99
99
  self.logEvent({ messageType: Types.MessageType.AppStateTransition });
100
100
  };
101
101
 
102
+ this.logPageView = function() {
103
+ self.logEvent({
104
+ messageType: Types.MessageType.PageView,
105
+ name: 'PageView',
106
+ data: {
107
+ hostname: window.location.hostname,
108
+ title: window.document.title,
109
+ },
110
+ eventType: Types.EventType.Unknown,
111
+ });
112
+ };
113
+
102
114
  this.logCheckoutEvent = function(step, option, attrs, customFlags) {
103
115
  var event = mpInstance._Ecommerce.createCommerceEventObject(
104
116
  customFlags
@@ -1,6 +1,6 @@
1
1
  import Constants, { HTTP_OK, HTTP_NOT_FOUND } from '../constants';
2
2
  import { SDKLoggerApi } from '../sdkRuntimeModels';
3
- import { Environment, isFunction } from '../utils';
3
+ import { Environment, isFunction, getErrorMessage } from '../utils';
4
4
  import {
5
5
  AsyncUploader,
6
6
  FetchUploader,
@@ -111,8 +111,7 @@ export const sendSearchRequest = async (
111
111
  callback(result);
112
112
  } catch (e) {
113
113
  logger.error(
114
- 'Error invoking search callback: ' +
115
- ((e as Error)?.message || String(e)),
114
+ 'Error invoking search callback: ' + getErrorMessage(e),
116
115
  );
117
116
  }
118
117
  };
@@ -216,7 +215,7 @@ export const sendSearchRequest = async (
216
215
 
217
216
  safeInvoke({ httpCode: response.status, body });
218
217
  } catch (e) {
219
- const message = (e as Error)?.message || String(e);
218
+ const message = getErrorMessage(e);
220
219
  const reportMessage = 'Error sending search request: ' + message;
221
220
  logger.error(reportMessage);
222
221
  // Mirror the identity-route pattern in identityApiClient.ts: log to
@@ -1,5 +1,5 @@
1
1
  import Constants, { ONE_DAY_IN_SECONDS, MILLIS_IN_ONE_SEC } from './constants';
2
- import { Dictionary, Environment, parseNumber, isObject, generateHash, generateUniqueId, isEmpty, isFunction } from './utils';
2
+ import { Dictionary, Environment, parseNumber, isObject, generateHash, generateUniqueId, isEmpty, isFunction, getErrorMessage } from './utils';
3
3
  import { BaseVault } from './vault';
4
4
  import Types from './types';
5
5
  import {
@@ -414,8 +414,7 @@ export const executeSearchRequest = (
414
414
  });
415
415
  } catch (e) {
416
416
  Logger.error(
417
- 'Error invoking search callback: ' +
418
- ((e as Error)?.message || String(e)),
417
+ 'Error invoking search callback: ' + getErrorMessage(e),
419
418
  );
420
419
  }
421
420
  }
package/src/identity.js CHANGED
@@ -1657,7 +1657,8 @@ export default function Identity(mpInstance) {
1657
1657
  mpInstance._RoktManager.onIdentityComplete();
1658
1658
 
1659
1659
  mpInstance._preInit.readyQueue = processReadyQueue(
1660
- mpInstance._preInit.readyQueue
1660
+ mpInstance._preInit.readyQueue,
1661
+ mpInstance.Logger
1661
1662
  );
1662
1663
  };
1663
1664
 
@@ -6,7 +6,7 @@ import {
6
6
  IFetchPayload,
7
7
  } from './uploaders';
8
8
  import { CACHE_HEADER } from './identity-utils';
9
- import { obfuscateData, parseNumber, valueof } from './utils';
9
+ import { obfuscateData, parseNumber, valueof, getErrorMessage } from './utils';
10
10
  import {
11
11
  IAliasCallback,
12
12
  IAliasRequest,
@@ -175,7 +175,7 @@ export default function IdentityAPIClient(
175
175
  Logger.verbose(message);
176
176
  invokeAliasCallback(aliasCallback, response.status, errorMessage);
177
177
  } catch (e) {
178
- const errorMessage = (e as Error).message || e.toString();
178
+ const errorMessage = getErrorMessage(e);
179
179
  Logger.error('Error sending alias request to mParticle servers. ' + errorMessage);
180
180
  invokeAliasCallback(
181
181
  aliasCallback,
@@ -338,7 +338,7 @@ export default function IdentityAPIClient(
338
338
  mpInstance.captureTiming(`${requestCount}-identityRequestEnd`);
339
339
  }
340
340
 
341
- const errorMessage = (err as Error).message || err.toString();
341
+ const errorMessage = getErrorMessage(err);
342
342
  const msg = 'Error sending identity request to servers' + ' - ' + errorMessage;
343
343
  Logger.error(msg);
344
344
  errorReporter?.report({
@@ -162,7 +162,10 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan
162
162
 
163
163
  if (self._Store?.identityCallFailed && self._RoktManager?.isReady()) {
164
164
  self._RoktManager.processMessageQueue();
165
- self._preInit.readyQueue = processReadyQueue(self._preInit.readyQueue);
165
+ self._preInit.readyQueue = processReadyQueue(
166
+ self._preInit.readyQueue,
167
+ self.Logger
168
+ );
166
169
  }
167
170
  };
168
171
 
@@ -179,7 +182,10 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan
179
182
  !hasExplicitIdentifier(self._Store);
180
183
 
181
184
  if (noFunctionalWithoutId) {
182
- self._preInit.readyQueue = processReadyQueue(self._preInit.readyQueue);
185
+ self._preInit.readyQueue = processReadyQueue(
186
+ self._preInit.readyQueue,
187
+ self.Logger
188
+ );
183
189
  }
184
190
  };
185
191
 
@@ -1478,6 +1484,7 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan
1478
1484
  function completeSDKInitialization(apiKey, config, mpInstance) {
1479
1485
  const kitBlocker = createKitBlocker(config, mpInstance);
1480
1486
  const { getFeatureFlag } = mpInstance._Helpers;
1487
+ const { AutoLogPageView } = Constants.FeatureFlags;
1481
1488
 
1482
1489
  // Destroy previous batch uploader to prevent leaked timers and event listeners
1483
1490
  if (mpInstance._APIClient?.uploader) {
@@ -1576,6 +1583,10 @@ function completeSDKInitialization(apiKey, config, mpInstance) {
1576
1583
  mpInstance._SessionManager.initialize();
1577
1584
  mpInstance._Events.logAST();
1578
1585
 
1586
+ if (getFeatureFlag(AutoLogPageView)) {
1587
+ mpInstance._Events.logPageView();
1588
+ }
1589
+
1579
1590
  processIdentityCallback(
1580
1591
  mpInstance,
1581
1592
  currentUser,
@@ -1599,7 +1610,8 @@ function completeSDKInitialization(apiKey, config, mpInstance) {
1599
1610
  );
1600
1611
 
1601
1612
  mpInstance._preInit.readyQueue = processReadyQueue(
1602
- mpInstance._preInit.readyQueue
1613
+ mpInstance._preInit.readyQueue,
1614
+ mpInstance.Logger
1603
1615
  );
1604
1616
  }
1605
1617
 
@@ -1,7 +1,8 @@
1
1
  import { IPixelConfiguration } from './cookieSyncManager';
2
2
  import { MPForwarder } from './forwarders.interfaces';
3
3
  import { IntegrationDelays } from './mp-instance';
4
- import { isEmpty, isFunction } from './utils';
4
+ import { SDKLoggerApi } from './sdkRuntimeModels';
5
+ import { isEmpty, isFunction, getErrorMessage } from './utils';
5
6
 
6
7
  export interface IPreInit {
7
8
  readyQueue: Function[] | any[];
@@ -11,26 +12,45 @@ export interface IPreInit {
11
12
  isDevelopmentMode?: boolean;
12
13
  }
13
14
 
14
- export const processReadyQueue = (readyQueue): Function[] => {
15
- if (!isEmpty(readyQueue)) {
16
- readyQueue.forEach(readyQueueItem => {
15
+ export const processReadyQueue = (
16
+ readyQueue,
17
+ logger: SDKLoggerApi
18
+ ): Function[] => {
19
+ if (isEmpty(readyQueue)) {
20
+ return [];
21
+ }
22
+
23
+ // Without draining first, sync re-entry (cache-hit identify →
24
+ // parseIdentityResponse → processReadyQueue) re-iterates the same array:
25
+ // callers only replace `_preInit.readyQueue` with [] after we return, so the
26
+ // nested call still sees every entry. That duplicates Identity/event calls
27
+ // and can nest "Unable to compute proper mParticle function" wraps.
28
+ // Splice the queue empty up front so a nested call observes [].
29
+ const items = readyQueue.splice(0, readyQueue.length);
30
+
31
+ // Isolate each item so one throw cannot abort the rest of this pass.
32
+ // Drain-first already removed siblings from the shared queue; without a
33
+ // per-item catch they would be lost forever when forEach aborts.
34
+ items.forEach(readyQueueItem => {
35
+ try {
17
36
  if (isFunction(readyQueueItem)) {
18
37
  readyQueueItem();
19
38
  } else if (Array.isArray(readyQueueItem)) {
20
39
  processPreloadedItem(readyQueueItem);
21
40
  }
22
- });
23
- }
41
+ } catch (e) {
42
+ logger.error(
43
+ 'Error processing ready queue item: ' + getErrorMessage(e)
44
+ );
45
+ }
46
+ });
47
+
24
48
  return [];
25
49
  };
26
50
 
27
51
  const processPreloadedItem = (readyQueueItem): void => {
28
- // Operate on a copy of the queued item. The ready queue can be drained more
29
- // than once (e.g. a synchronous cache-hit identify re-enters processReadyQueue
30
- // before the outer drain resets the queue). Splicing the shared item array in
31
- // place would corrupt it on the second pass — ["Identity.login", opts] becomes
32
- // [opts] — so `method` turns into a non-string/undefined and `method.split('.')`
33
- // throws. Copying keeps the original item intact for any repeat pass.
52
+ // Operate on a copy so processPreloadedItem never mutates the caller's
53
+ // queued item array (defensive; the queue itself is drained above).
34
54
  const args = readyQueueItem.slice();
35
55
  const method = args.splice(0, 1)[0];
36
56