@mparticle/web-sdk 2.64.0 → 2.65.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.
@@ -15,7 +15,7 @@ map:function map(a,b){var c,d,e;if(null===this)throw new TypeError(" this is nul
15
15
  filter:function filter(a/*, thisArg*/){if(void 0===this||null===this)throw new TypeError;var b=Object(this),c=b.length>>>0;if("function"!=typeof a)throw new TypeError;for(var d=[],e=2<=arguments.length?arguments[1]:void 0,f=0;f<c;f++)if(f in b){var g=b[f];a.call(e,g,f,b)&&d.push(g);}return d},// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
16
16
  isArray:function isArray(a){return "[object Array]"===Object.prototype.toString.call(a)},Base64:Base64$1};
17
17
 
18
- var version = "2.64.0";
18
+ var version = "2.65.0";
19
19
 
20
20
  var Constants={sdkVersion:version,sdkVendor:"mparticle",platform:"web",Messages:{DeprecationMessages:{MethodHasBeenDeprecated:"has been deprecated.",MethodMarkedForDeprecationPostfix:"is a deprecated method and will be removed in future releases.",AlternativeMethodPrefix:"Please use the alternate method:"},ErrorMessages:{NoToken:"A token must be specified.",EventNameInvalidType:"Event name must be a valid string value.",EventDataInvalidType:"Event data must be a valid object hash.",LoggingDisabled:"Event logging is currently disabled.",CookieParseError:"Could not parse cookie",EventEmpty:"Event object is null or undefined, cancelling send",APIRequestEmpty:"APIRequest is null or undefined, cancelling send",NoEventType:"Event type must be specified.",TransactionIdRequired:"Transaction ID is required",TransactionRequired:"A transaction attributes object is required",PromotionIdRequired:"Promotion ID is required",BadAttribute:"Attribute value cannot be object or array",BadKey:"Key value cannot be object or array",BadLogPurchase:"Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions",AudienceAPINotEnabled:"Your workspace is not enabled to retrieve user audiences."},InformationMessages:{CookieSearch:"Searching for cookie",CookieFound:"Cookie found, parsing values",CookieNotFound:"Cookies not found",CookieSet:"Setting cookie",CookieSync:"Performing cookie sync",SendBegin:"Starting to send event",SendIdentityBegin:"Starting to send event to identity server",SendWindowsPhone:"Sending event to Windows Phone container",SendIOS:"Calling iOS path: ",SendAndroid:"Calling Android JS interface method: ",SendHttp:"Sending event to mParticle HTTP service",SendAliasHttp:"Sending alias request to mParticle HTTP service",SendIdentityHttp:"Sending event to mParticle HTTP service",StartingNewSession:"Starting new Session",StartingLogEvent:"Starting to log event",StartingLogOptOut:"Starting to log user opt in/out",StartingEndSession:"Starting to end session",StartingInitialization:"Starting to initialize",StartingLogCommerceEvent:"Starting to log commerce event",StartingAliasRequest:"Starting to Alias MPIDs",LoadingConfig:"Loading configuration options",AbandonLogEvent:"Cannot log event, logging disabled or developer token not set",AbandonAliasUsers:"Cannot Alias Users, logging disabled or developer token not set",AbandonStartSession:"Cannot start session, logging disabled or developer token not set",AbandonEndSession:"Cannot end session, logging disabled or developer token not set",NoSessionToEnd:"Cannot end session, no active session found"},ValidationMessages:{ModifyIdentityRequestUserIdentitiesPresent:"identityRequests to modify require userIdentities to be present. Request not sent to server. Please fix and try again",IdentityRequesetInvalidKey:"There is an invalid key on your identityRequest object. It can only contain a `userIdentities` object and a `onUserAlias` function. Request not sent to server. Please fix and try again.",OnUserAliasType:"The onUserAlias value must be a function.",UserIdentities:"The userIdentities key must be an object with keys of identityTypes and values of strings. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidKey:"There is an invalid identity key on your `userIdentities` object within the identityRequest. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidValues:"All user identity values must be strings or null. Request not sent to server. Please fix and try again.",AliasMissingMpid:"Alias Request must contain both a destinationMpid and a sourceMpid",AliasNonUniqueMpid:"Alias Request's destinationMpid and sourceMpid must be unique",AliasMissingTime:"Alias Request must have both a startTime and an endTime",AliasStartBeforeEndTime:"Alias Request's endTime must be later than its startTime"}},NativeSdkPaths:{LogEvent:"logEvent",SetUserTag:"setUserTag",RemoveUserTag:"removeUserTag",SetUserAttribute:"setUserAttribute",RemoveUserAttribute:"removeUserAttribute",SetSessionAttribute:"setSessionAttribute",AddToCart:"addToCart",RemoveFromCart:"removeFromCart",ClearCart:"clearCart",LogOut:"logOut",SetUserAttributeList:"setUserAttributeList",RemoveAllUserAttributes:"removeAllUserAttributes",GetUserAttributesLists:"getUserAttributesLists",GetAllUserAttributes:"getAllUserAttributes",Identify:"identify",Logout:"logout",Login:"login",Modify:"modify",Alias:"aliasUsers",Upload:"upload"},StorageNames:{localStorageName:"mprtcl-api",localStorageNameV3:"mprtcl-v3",cookieName:"mprtcl-api",cookieNameV2:"mprtcl-v2",cookieNameV3:"mprtcl-v3",localStorageNameV4:"mprtcl-v4",localStorageProductsV4:"mprtcl-prodv4",cookieNameV4:"mprtcl-v4",currentStorageName:"mprtcl-v4",currentStorageProductsName:"mprtcl-prodv4"},DefaultConfig:{cookieDomain:null,cookieExpiration:365,logLevel:null,timeout:300,sessionTimeout:30,maxProducts:20,forwarderStatsTimeout:5e3,integrationDelayTimeout:5e3,maxCookieSize:3e3,aliasMaxWindow:90,uploadInterval:0// Maximum milliseconds in between batch uploads, below 500 will mean immediate upload. The server returns this as a string, but we are using it as a number internally
21
21
  },DefaultBaseUrls:{v1SecureServiceUrl:"jssdks.mparticle.com/v1/JS/",v2SecureServiceUrl:"jssdks.mparticle.com/v2/JS/",v3SecureServiceUrl:"jssdks.mparticle.com/v3/JS/",configUrl:"jssdkcdns.mparticle.com/JS/v2/",identityUrl:"identity.mparticle.com/v1/",aliasUrl:"jssdks.mparticle.com/v1/identity/",userAudienceUrl:"nativesdks.mparticle.com/v1/"},// These are the paths that are used to construct the CNAME urls
@@ -27,7 +27,10 @@ CaptureIntegrationSpecificIds:"captureIntegrationSpecificIds",// CaptureIntegrat
27
27
  // - 'all' → capture all IDs
28
28
  // - 'none' → capture none
29
29
  // - 'roktonly' → capture only Rokt-related IDs
30
- CaptureIntegrationSpecificIdsV2:"captureIntegrationSpecificIdsV2",AstBackgroundEvents:"astBackgroundEvents"},DefaultInstance:"default_instance",CCPAPurpose:"data_sale_opt_out",IdentityMethods:{Modify:"modify",Logout:"logout",Login:"login",Identify:"identify"},Environment:{Development:"development",Production:"production"},CaptureIntegrationSpecificIdsV2Modes:{All:"all",None:"none",RoktOnly:"roktonly"},Rokt:{LauncherInstanceGuidKey:"__rokt_li_guid__"}};var ONE_DAY_IN_SECONDS=86400;var MILLIS_IN_ONE_SEC=1e3;// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
30
+ CaptureIntegrationSpecificIdsV2:"captureIntegrationSpecificIds.V2",AstBackgroundEvents:"astBackgroundEvents"},DefaultInstance:"default_instance",CCPAPurpose:"data_sale_opt_out",IdentityMethods:{Modify:"modify",Logout:"logout",Login:"login",Identify:"identify"},Environment:{Development:"development",Production:"production"},CaptureIntegrationSpecificIdsV2Modes:{All:"all",None:"none",RoktOnly:"roktonly"},Rokt:{LauncherInstanceGuidKey:"__rokt_li_guid__"}};var ONE_DAY_IN_SECONDS=86400;var MILLIS_IN_ONE_SEC=1e3;// User attribute set when the end user opts out of ad targeting via
31
+ // launcherOptions.noTargeting. Server-side systems use this attribute
32
+ // to exclude the user from retargeting audiences.
33
+ var NO_TARGETING_ATTRIBUTE="$NoTargeting";// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
31
34
  var HTTP_OK=200;var HTTP_ACCEPTED=202;var HTTP_BAD_REQUEST=400;var HTTP_SERVER_ERROR=500;
32
35
 
33
36
  function _typeof$1(o) {
@@ -487,8 +490,11 @@ function appendUserInfo(a,b){if(b){if(!a)return b.MPID=null,b.ConsentState=null,
487
490
  * Creates an instance of a BatchUploader
488
491
  * @param {IMParticleWebSDKInstance} mpInstance - the mParticle SDK instance
489
492
  * @param {number} uploadInterval - the desired upload interval in milliseconds
490
- */function a(b,c){var d,e;this.offlineStorageEnabled=!1,this.lastASTEventTime=0,this.AST_DEBOUNCE_MS=1e3,this.mpInstance=b,this.uploadIntervalMillis=c,this.batchingEnabled=c>=a.MINIMUM_INTERVAL_MILLIS,this.uploadIntervalMillis<a.MINIMUM_INTERVAL_MILLIS&&(this.uploadIntervalMillis=a.MINIMUM_INTERVAL_MILLIS),this.eventsQueuedForProcessing=[],this.batchesQueuedForProcessing=[],this.offlineStorageEnabled=this.isOfflineStorageAvailable();// When noFunctional is true, prevent events/batches storage
491
- var f=null===(e=b._CookieConsentManager)||void 0===e?void 0:e.getNoFunctional();this.offlineStorageEnabled&&!f&&(this.eventVault=new SessionStorageVault("".concat(b._Store.storageName,"-events")),this.batchVault=new LocalStorageVault("".concat(b._Store.storageName,"-batches")),(d=this.eventsQueuedForProcessing).push.apply(d,this.eventVault.retrieve()));var g=this.mpInstance._Store,h=g.SDKConfig,i=g.devToken,j=this.mpInstance._Helpers.createServiceUrl(h.v3SecureServiceUrl,i);this.uploadUrl="".concat(j,"/events"),this.uploader=window.fetch?new FetchUploader(this.uploadUrl):new XHRUploader(this.uploadUrl),this.triggerUploadInterval(!0,!1),this.addEventListeners();}return a.prototype.isOfflineStorageAvailable=function(){var a=this.mpInstance,b=a._Helpers.getFeatureFlag,c=a._Store.deviceId,d=b(Constants.FeatureFlags.OfflineStorage),e=parseInt(d,10),f=getRampNumber(c);// https://go.mparticle.com/work/SQDSDKS-6317
493
+ */function a(b,c){var d,e;this.offlineStorageEnabled=!1,this.lastASTEventTime=0,this.AST_DEBOUNCE_MS=1e3,this.uploadIntervalTimerId=null,this.exitHandler=null,this.visibilityChangeHandler=null,this.destroyed=!1,this.mpInstance=b,this.uploadIntervalMillis=c,this.batchingEnabled=c>=a.MINIMUM_INTERVAL_MILLIS,this.uploadIntervalMillis<a.MINIMUM_INTERVAL_MILLIS&&(this.uploadIntervalMillis=a.MINIMUM_INTERVAL_MILLIS),this.eventsQueuedForProcessing=[],this.batchesQueuedForProcessing=[],this.offlineStorageEnabled=this.isOfflineStorageAvailable();// When noFunctional is true, prevent events/batches storage
494
+ var f=null===(e=b._CookieConsentManager)||void 0===e?void 0:e.getNoFunctional();this.offlineStorageEnabled&&!f&&(this.eventVault=new SessionStorageVault("".concat(b._Store.storageName,"-events")),this.batchVault=new LocalStorageVault("".concat(b._Store.storageName,"-batches")),(d=this.eventsQueuedForProcessing).push.apply(d,this.eventVault.retrieve()));var g=this.mpInstance._Store,h=g.SDKConfig,i=g.devToken,j=this.mpInstance._Helpers.createServiceUrl(h.v3SecureServiceUrl,i);this.uploadUrl="".concat(j,"/events"),this.uploader=window.fetch?new FetchUploader(this.uploadUrl):new XHRUploader(this.uploadUrl),this.triggerUploadInterval(!0,!1),this.addEventListeners();}/**
495
+ * Cleans up timers and event listeners to prevent leaks when the SDK
496
+ * is re-initialized (e.g. between tests or on repeated init calls).
497
+ */return a.prototype.destroy=function(){this.destroyed=!0,null!==this.uploadIntervalTimerId&&(clearTimeout(this.uploadIntervalTimerId),this.uploadIntervalTimerId=null),this.visibilityChangeHandler&&document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.exitHandler&&(window.removeEventListener("beforeunload",this.exitHandler),window.removeEventListener("pagehide",this.exitHandler)),this.exitHandler=null,this.visibilityChangeHandler=null;},a.prototype.isOfflineStorageAvailable=function(){var a=this.mpInstance,b=a._Helpers.getFeatureFlag,c=a._Store.deviceId,d=b(Constants.FeatureFlags.OfflineStorage),e=parseInt(d,10),f=getRampNumber(c);// https://go.mparticle.com/work/SQDSDKS-6317
492
498
  // TODO: Handle cases where Local Storage is unavailable
493
499
  // Potentially shared between Vault and Persistence as well
494
500
  // https://go.mparticle.com/work/SQDSDKS-5022
@@ -496,9 +502,9 @@ return e>=f},a.prototype.shouldDebounceAndUpdateLastASTTime=function(){var a=Dat
496
502
  if(s){this.mpInstance._IntegrationCapture.capture();var t=this.mpInstance._IntegrationCapture.getClickIdsAsCustomFlags();o=__assign(__assign({},t),o);var u=this.mpInstance._IntegrationCapture.getClickIdsAsIntegrationAttributes();p=__assign(__assign({},u),p);}return n.CustomFlags=o,n.IntegrationAttributes=p,appendUserInfo(m(),n),n},a.prototype.addEventListeners=function(){var a=this,b=this,c=function(){// Check for debounce before creating and queueing event
497
503
  var c=a.mpInstance._Helpers.getFeatureFlag,d=Constants.FeatureFlags.AstBackgroundEvents;if(c(d)){if(b.shouldDebounceAndUpdateLastASTTime())return;// Add application state transition event to queue
498
504
  var e=b.createBackgroundASTEvent();b.queueEvent(e);}// Then trigger the upload with beacon
499
- b.prepareAndUpload(!1,b.isBeaconAvailable());};document.addEventListener("visibilitychange",function(){"hidden"===document.visibilityState&&c();}),window.addEventListener("beforeunload",c),window.addEventListener("pagehide",c);},a.prototype.isBeaconAvailable=function(){return !!navigator.sendBeacon},a.prototype.triggerUploadInterval=function(a,b){var c=this;void 0===a&&(a=!1),void 0===b&&(b=!1),setTimeout(function(){c.prepareAndUpload(a,b);},this.uploadIntervalMillis);},a.prototype.queueEvent=function(a){if(!isEmpty(a)){if(this.eventsQueuedForProcessing.push(a),this.offlineStorageEnabled&&this.eventVault&&this.eventVault.store(this.eventsQueuedForProcessing),this.mpInstance.Logger.isVerbose()){var b=obfuscateDevData(a,this.mpInstance._Store.SDKConfig.isDevelopmentMode);this.mpInstance.Logger.verbose("Queuing event: ".concat(JSON.stringify(b))),this.mpInstance.Logger.verbose("Queued event count: ".concat(this.eventsQueuedForProcessing.length));}this.shouldTriggerImmediateUpload(a.EventDataType)&&this.prepareAndUpload(!1,!1);}},a.prototype.shouldTriggerImmediateUpload=function(a){var b=[MessageType$1.Commerce,MessageType$1.UserIdentityChange];return !this.batchingEnabled||b.includes(a)},(a.createNewBatches=function(a,b,c){if(!b||!a||!a.length)return null;//bucket by MPID, and then by session, ordered by timestamp
505
+ b.prepareAndUpload(!1,b.isBeaconAvailable());};this.exitHandler=c,this.visibilityChangeHandler=function(){"hidden"===document.visibilityState&&c();},document.addEventListener("visibilitychange",this.visibilityChangeHandler),window.addEventListener("beforeunload",c),window.addEventListener("pagehide",c);},a.prototype.isBeaconAvailable=function(){return !!navigator.sendBeacon},a.prototype.triggerUploadInterval=function(a,b){var c=this;void 0===a&&(a=!1),void 0===b&&(b=!1),this.uploadIntervalTimerId=setTimeout(function(){c.prepareAndUpload(a,b);},this.uploadIntervalMillis);},a.prototype.queueEvent=function(a){if(!isEmpty(a)){if(this.eventsQueuedForProcessing.push(a),this.offlineStorageEnabled&&this.eventVault&&this.eventVault.store(this.eventsQueuedForProcessing),this.mpInstance.Logger.isVerbose()){var b=obfuscateDevData(a,this.mpInstance._Store.SDKConfig.isDevelopmentMode);this.mpInstance.Logger.verbose("Queuing event: ".concat(JSON.stringify(b))),this.mpInstance.Logger.verbose("Queued event count: ".concat(this.eventsQueuedForProcessing.length));}this.shouldTriggerImmediateUpload(a.EventDataType)&&this.prepareAndUpload(!1,!1);}},a.prototype.shouldTriggerImmediateUpload=function(a){var b=[MessageType$1.Commerce,MessageType$1.UserIdentityChange];return !this.batchingEnabled||b.includes(a)},(a.createNewBatches=function(a,b,c){if(!b||!a||!a.length)return null;//bucket by MPID, and then by session, ordered by timestamp
500
506
  for(var d,e=[],f=new Map,g=0,h=a;g<h.length;g++){//on initial startup, there may be events logged without an mpid.
501
- if(d=h[g],!d.MPID){var i=b.getMPID();d.MPID=i;}var j=f.get(d.MPID);j||(j=[]),j.push(d),f.set(d.MPID,j);}for(var k=0,l=Array.from(f.entries());k<l.length;k++){for(var m=l[k],i=m[0],n=m[1],o=new Map,p=0,q=n;p<q.length;p++){var d=q[p],j=o.get(d.SessionId);j||(j=[]),j.push(d),o.set(d.SessionId,j);}for(var r=0,s=Array.from(o.entries());r<s.length;r++){var t=s[r],u=convertEvents(i,t[1],c);if(u)try{c._Forwarders.sendBatchToForwarders(u);}catch(a){c.Logger.error("Error forwarding batch to kits. ".concat(a));}var v=c._Store.SDKConfig.onCreateBatch;v&&(u=v(u),u?u.modified=!0:c.Logger.warning("Skiping batch upload because no batch was returned from onCreateBatch callback")),u&&e.push(u);}}return e},a.prototype.prepareAndUpload=function(b,c){return void 0===b&&(b=!1),void 0===c&&(c=!1),__awaiter(this,void 0,void 0,function(){var d,e,f,g,h,i,j,k;return __generator(this,function(l){switch(l.label){case 0:return d=this.mpInstance.Identity.getCurrentUser(),e=this.eventsQueuedForProcessing,this.eventsQueuedForProcessing=[],this.offlineStorageEnabled&&this.eventVault&&this.eventVault.store([]),f=[],isEmpty(e)||(f=a.createNewBatches(e,d,this.mpInstance)),this.offlineStorageEnabled&&this.batchVault&&((i=this.batchesQueuedForProcessing).unshift.apply(i,this.batchVault.retrieve()),this.batchVault.purge()),isEmpty(f)||(j=this.batchesQueuedForProcessing).push.apply(j,f),g=this.batchesQueuedForProcessing,this.batchesQueuedForProcessing=[],[4/*yield*/,this.uploadBatches(g,c)];case 1:return h=l.sent(),isEmpty(h)||(k=this.batchesQueuedForProcessing).unshift.apply(k,h),!c&&this.offlineStorageEnabled&&this.batchVault&&(this.batchVault.store(this.batchesQueuedForProcessing),this.batchesQueuedForProcessing=[]),b&&this.triggerUploadInterval(b,!1),[2/*return*/]}})})},a.prototype.uploadBatches=function(b,c){return __awaiter(this,void 0,void 0,function(){var d,e,f,g,h,j,k;return __generator(this,function(i){switch(i.label){case 0:if(d=b.filter(function(a){return !isEmpty(a.events)}),isEmpty(d))return [2/*return*/,null];this.mpInstance.Logger.isVerbose()&&(e=obfuscateDevData(d,this.mpInstance._Store.SDKConfig.isDevelopmentMode),this.mpInstance.Logger.verbose("Uploading batches: ".concat(JSON.stringify(e))),this.mpInstance.Logger.verbose("Batch count: ".concat(d.length))),f=0,i.label=1;case 1:return f<d.length?(g={method:"POST",headers:{Accept:a.CONTENT_TYPE,"Content-Type":"text/plain;charset=UTF-8"},body:JSON.stringify(d[f])},!(c&&this.isBeaconAvailable()))?[3/*break*/,2]:(h=new Blob([g.body],{type:"text/plain;charset=UTF-8"}),navigator.sendBeacon(this.uploadUrl,h),[3/*break*/,5]):[3/*break*/,6];case 2:return i.trys.push([2,4,,5]),[4/*yield*/,this.uploader.upload(g)];case 3:if(j=i.sent(),200<=j.status&&300>j.status)this.mpInstance.Logger.verbose("Upload success for request ID: ".concat(d[f].source_request_id));else {if(500<=j.status||429===j.status)// Server error, add back current batches and try again later
507
+ if(d=h[g],!d.MPID){var i=b.getMPID();d.MPID=i;}var j=f.get(d.MPID);j||(j=[]),j.push(d),f.set(d.MPID,j);}for(var k=0,l=Array.from(f.entries());k<l.length;k++){for(var m=l[k],i=m[0],n=m[1],o=new Map,p=0,q=n;p<q.length;p++){var d=q[p],j=o.get(d.SessionId);j||(j=[]),j.push(d),o.set(d.SessionId,j);}for(var r=0,s=Array.from(o.entries());r<s.length;r++){var t=s[r],u=convertEvents(i,t[1],c);if(u)try{c._Forwarders.sendBatchToForwarders(u);}catch(a){c.Logger.error("Error forwarding batch to kits. ".concat(a));}var v=c._Store.SDKConfig.onCreateBatch;v&&(u=v(u),u?u.modified=!0:c.Logger.warning("Skiping batch upload because no batch was returned from onCreateBatch callback")),u&&e.push(u);}}return e},a.prototype.prepareAndUpload=function(b,c){return void 0===b&&(b=!1),void 0===c&&(c=!1),__awaiter(this,void 0,void 0,function(){var d,e,f,g,h,i,j,k;return __generator(this,function(l){switch(l.label){case 0:return d=this.mpInstance.Identity.getCurrentUser(),e=this.eventsQueuedForProcessing,this.eventsQueuedForProcessing=[],this.offlineStorageEnabled&&this.eventVault&&this.eventVault.store([]),f=[],isEmpty(e)||(f=a.createNewBatches(e,d,this.mpInstance)),this.offlineStorageEnabled&&this.batchVault&&((i=this.batchesQueuedForProcessing).unshift.apply(i,this.batchVault.retrieve()),this.batchVault.purge()),isEmpty(f)||(j=this.batchesQueuedForProcessing).push.apply(j,f),g=this.batchesQueuedForProcessing,this.batchesQueuedForProcessing=[],[4/*yield*/,this.uploadBatches(g,c)];case 1:return h=l.sent(),isEmpty(h)||(k=this.batchesQueuedForProcessing).unshift.apply(k,h),!c&&this.offlineStorageEnabled&&this.batchVault&&(this.batchVault.store(this.batchesQueuedForProcessing),this.batchesQueuedForProcessing=[]),b&&!this.destroyed&&this.triggerUploadInterval(b,!1),[2/*return*/]}})})},a.prototype.uploadBatches=function(b,c){return __awaiter(this,void 0,void 0,function(){var d,e,f,g,h,j,k;return __generator(this,function(i){switch(i.label){case 0:if(d=b.filter(function(a){return !isEmpty(a.events)}),isEmpty(d))return [2/*return*/,null];this.mpInstance.Logger.isVerbose()&&(e=obfuscateDevData(d,this.mpInstance._Store.SDKConfig.isDevelopmentMode),this.mpInstance.Logger.verbose("Uploading batches: ".concat(JSON.stringify(e))),this.mpInstance.Logger.verbose("Batch count: ".concat(d.length))),f=0,i.label=1;case 1:return f<d.length?(g={method:"POST",headers:{Accept:a.CONTENT_TYPE,"Content-Type":"text/plain;charset=UTF-8"},body:JSON.stringify(d[f])},!(c&&this.isBeaconAvailable()))?[3/*break*/,2]:(h=new Blob([g.body],{type:"text/plain;charset=UTF-8"}),navigator.sendBeacon(this.uploadUrl,h),[3/*break*/,5]):[3/*break*/,6];case 2:return i.trys.push([2,4,,5]),[4/*yield*/,this.uploader.upload(g)];case 3:if(j=i.sent(),200<=j.status&&300>j.status)this.mpInstance.Logger.verbose("Upload success for request ID: ".concat(d[f].source_request_id));else {if(500<=j.status||429===j.status)// Server error, add back current batches and try again later
502
508
  return this.mpInstance.Logger.error("HTTP error status ".concat(j.status," received")),[2/*return*/,d.slice(f,d.length)];if(401<=j.status)//if we're getting a 401, assume we'll keep getting a 401 and clear the uploads.
503
509
  return this.mpInstance.Logger.error("HTTP error status ".concat(j.status," while uploading - please verify your API key.")),[2/*return*/,null];throw console.error("HTTP error status ".concat(j.status," while uploading events."),j),new Error("Uncaught HTTP Error ".concat(j.status,". Batch upload will be re-attempted."))}return [3/*break*/,5];case 4:return k=i.sent(),this.mpInstance.Logger.error("Error sending event to mParticle servers. ".concat(k)),[2/*return*/,d.slice(f,d.length)];case 5:return f++,[3/*break*/,1];case 6:return [2/*return*/,null]}})})},a.CONTENT_TYPE="text/plain;charset=UTF-8",a.MINIMUM_INTERVAL_MILLIS=500,a)}();
504
510
 
@@ -632,9 +638,12 @@ function processFlags(a){var b={},c=Constants.FeatureFlags,d=c.ReportBatching,e=
632
638
  // Passed in config flags take priority over defaults
633
639
  }function processBaseUrls(a,b,c){// an API key is not present in a webview only mode. In this case, no baseUrls are needed
634
640
  if(!c)return {};// Set default baseUrls
635
- // When direct URL routing is false, update baseUrls based custom urls
641
+ // A CNAME (config.domain, e.g. set by the snippet v2.6+) takes precedence
642
+ // over direct URL routing so that customer-configured first-party domains
643
+ // and the snippet's fallback domain are always honored.
644
+ return isEmpty(a.domain)?b.directURLRouting?processDirectBaseUrls(a,c):processCustomBaseUrls(a):processCustomBaseUrls(a);// When direct URL routing is false, update baseUrls based custom urls
636
645
  // passed to the config
637
- return b.directURLRouting?processDirectBaseUrls(a,c):processCustomBaseUrls(a)}function processCustomBaseUrls(a){var b=Constants.DefaultBaseUrls,c=Constants.CNAMEUrlPaths,d={};// newBaseUrls are default if the customer is not using a CNAME
646
+ }function processCustomBaseUrls(a){var b=Constants.DefaultBaseUrls,c=Constants.CNAMEUrlPaths,d={};// newBaseUrls are default if the customer is not using a CNAME
638
647
  // If a customer passes either config.domain or config.v3SecureServiceUrl,
639
648
  // config.identityUrl, etc, the customer is using a CNAME.
640
649
  // config.domain will take priority if a customer passes both.
@@ -1334,8 +1343,12 @@ return a._Helpers.getFeatureFlag(FeatureFlags$1.AudienceAPI)?void(null===d.audie
1334
1343
  * @method getCartProducts
1335
1344
  * @return {Array} array of cart products
1336
1345
  * @deprecated
1337
- */getCartProducts:function getCartProducts(){return a.Logger.warning(generateDeprecationMessage("Identity.getCurrentUser().getCart().getCartProducts()",!0,"eCommerce.logProductAction()","https://docs.mparticle.com/developers/sdk/web/commerce-tracking")),[]}}},this.parseIdentityResponse=function(b,d,f,g,h,i,j){var k,l,m,n=a.Identity.getUser(d),o=n?n.getMPID():null,p=n?n.getUserIdentities().userIdentities:{},q={};a._Store.identityCallInFlight=!1;try{var r,s,t;if(a.Logger.verbose("Parsing \""+h+"\" identity response from server"),l=null!==(r=b.responseText)&&void 0!==r?r:null,a._Store.isLoggedIn=(null===(s=l)||void 0===s?void 0:s.is_logged_in)||!1,hasMPIDChanged(n,l)&&(a._Store.mpid=l.mpid,n&&a._Persistence.setLastSeenTime(d),k=!a._Persistence.getFirstSeenTime(l.mpid),a._Persistence.setFirstSeenTime(l.mpid)),b.status===HTTP_OK){c(CacheIdentity)&&cacheOrClearIdCache(h,i,e.idCache,b,j);var u=e.IdentityAPI.getUser(l.mpid),v=u?u.getUserIdentities().userIdentities:{};h===Modify$1?(q=a._Identity.IdentityRequest.combineUserIdentities(p,g.userIdentities),a._Store.setUserIdentities(d,q)):(h===Identify&&n&&l.mpid===o&&a._Persistence.setFirstSeenTime(l.mpid),a._Store.addMpidToSessionHistory(l.mpid,d),a._CookieSyncManager.attemptCookieSync(l.mpid,k),a._Persistence.swapCurrentUser(d,l.mpid,a._Store.currentSessionMPIDs),g&&!isEmpty(g.userIdentities)&&(q=e.IdentityRequest.combineUserIdentities(v,g.userIdentities)),a._Store.setUserIdentities(l.mpid,q),a._Persistence.update(),a._Store.syncPersistenceData(),a._Persistence.findPrevCookiesBasedOnUI(g),a._Store.context=l.context||a._Store.context),m=a.Identity.getCurrentUser(),tryOnUserAlias(n,m,g,a.Logger);var w=a._Persistence.getPersistence();m&&(a._Persistence.storeDataInMemory(w,m.getMPID()),e.reinitForwardersOnUserChange(n,m),e.setForwarderCallbacks(m,h));var x=IdentityType.getNewIdentitiesByName(q),y=h===Modify$1?p:v;// https://go.mparticle.com/work/SQDSDKS-6501
1338
- e.sendUserIdentityChangeEvent(x,h,l.mpid,y);}if(f){var z=0===b.status?HTTPCodes$2.noHttpCoverage:b.status;a._Helpers.invokeCallback(f,z,l||null,m);}else l&&!isEmpty(l.errors)&&// https://go.mparticle.com/work/SQDSDKS-6500
1346
+ */getCartProducts:function getCartProducts(){return a.Logger.warning(generateDeprecationMessage("Identity.getCurrentUser().getCart().getCartProducts()",!0,"eCommerce.logProductAction()","https://docs.mparticle.com/developers/sdk/web/commerce-tracking")),[]}}},this.parseIdentityResponse=function(b,d,f,g,h,i,j){var k,l,m,n=a.Identity.getUser(d),o=n?n.getMPID():null,p=n?n.getUserIdentities().userIdentities:{},q={};a._Store.identityCallInFlight=!1;try{var r,s,t;if(a.Logger.verbose("Parsing \""+h+"\" identity response from server"),l=null!==(r=b.responseText)&&void 0!==r?r:null,a._Store.isLoggedIn=(null===(s=l)||void 0===s?void 0:s.is_logged_in)||!1,hasMPIDChanged(n,l)&&(a._Store.mpid=l.mpid,n&&a._Persistence.setLastSeenTime(d),k=!a._Persistence.getFirstSeenTime(l.mpid),a._Persistence.setFirstSeenTime(l.mpid)),b.status===HTTP_OK){var u;c(CacheIdentity)&&cacheOrClearIdCache(h,i,e.idCache,b,j);var v=e.IdentityAPI.getUser(l.mpid),w=v?v.getUserIdentities().userIdentities:{};h===Modify$1?(q=a._Identity.IdentityRequest.combineUserIdentities(p,g.userIdentities),a._Store.setUserIdentities(d,q)):(h===Identify&&n&&l.mpid===o&&a._Persistence.setFirstSeenTime(l.mpid),a._Store.addMpidToSessionHistory(l.mpid,d),a._CookieSyncManager.attemptCookieSync(l.mpid,k),a._Persistence.swapCurrentUser(d,l.mpid,a._Store.currentSessionMPIDs),g&&!isEmpty(g.userIdentities)&&(q=e.IdentityRequest.combineUserIdentities(w,g.userIdentities)),a._Store.setUserIdentities(l.mpid,q),a._Persistence.update(),a._Store.syncPersistenceData(),a._Persistence.findPrevCookiesBasedOnUI(g),a._Store.context=l.context||a._Store.context),m=a.Identity.getCurrentUser(),tryOnUserAlias(n,m,g,a.Logger);var x=a._Persistence.getPersistence();m&&(a._Persistence.storeDataInMemory(x,m.getMPID()),e.reinitForwardersOnUserChange(n,m),e.setForwarderCallbacks(m,h));var y=IdentityType.getNewIdentitiesByName(q),z=h===Modify$1?p:w;// Sync $NoTargeting before sendUserIdentityChangeEvent
1347
+ // because UIC events call sendEventToServer which triggers
1348
+ // processQueuedEvents, draining the event queue. The
1349
+ // attribute must be in the store before that happens so
1350
+ // appendUserInfo picks it up.
1351
+ null===(u=a._CookieConsentManager)||void 0===u||u.syncNoTargetingAttribute(m),e.sendUserIdentityChangeEvent(y,h,l.mpid,z);}if(f){var A=0===b.status?HTTPCodes$2.noHttpCoverage:b.status;a._Helpers.invokeCallback(f,A,l||null,m);}else l&&!isEmpty(l.errors)&&// https://go.mparticle.com/work/SQDSDKS-6500
1339
1352
  a.Logger.error("Received HTTP response code of "+b.status+" - "+l.errors[0].message);a.Logger.verbose("Successfully parsed Identity Response"),null===(t=a._APIClient)||void 0===t||t.processQueuedEvents();}catch(c){f&&a._Helpers.invokeCallback(f,b.status,l||null),a.Logger.error("Error parsing JSON response from Identity server: "+c);}a._Store.isInitialized=!0,a._RoktManager.onIdentityComplete(),a._preInit.readyQueue=processReadyQueue(a._preInit.readyQueue);},this.sendUserIdentityChangeEvent=function(b,c,d,f){if(d||c===Modify$1)// https://go.mparticle.com/work/SQDSDKS-6501
1340
1353
  {// https://go.mparticle.com/work/SQDSDKS-6354
1341
1354
  var g=this.IdentityAPI.getUser(d);for(var h in b)// Verifies a change actually happened
@@ -1520,7 +1533,7 @@ Promise.resolve(k).then(function(a){h&&h(a);})["catch"](j);}catch(a){j(a);}});}}
1520
1533
  */var CookieConsentManager=/** @class */function(){function a(a){this.flags=a,this.flags={noFunctional:!0===a.noFunctional,noTargeting:!0===a.noTargeting};}/**
1521
1534
  * Returns true if third-party targeting is disabled.
1522
1535
  * Targeting is allowed when noTargeting is false (default).
1523
- */return a.prototype.getNoTargeting=function(){return this.flags.noTargeting},a.prototype.getNoFunctional=function(){return this.flags.noFunctional},a}();
1536
+ */return a.prototype.getNoTargeting=function(){return this.flags.noTargeting},a.prototype.getNoFunctional=function(){return this.flags.noFunctional},a.prototype.syncNoTargetingAttribute=function(a){a&&(this.flags.noTargeting?a.setUserAttribute(NO_TARGETING_ATTRIBUTE,!0):a.getAllUserAttributes().hasOwnProperty(NO_TARGETING_ATTRIBUTE)&&a.removeUserAttribute(NO_TARGETING_ATTRIBUTE));},a}();
1524
1537
 
1525
1538
  var ErrorReportingDispatcher=/** @class */function(){function a(){this.services=[];}return a.prototype.register=function(a){this.services.push(a);},a.prototype.report=function(a){var b=this;this.services.forEach(function(c){var d;try{c.report(a);}catch(a){null===(d=b.logger)||void 0===d?void 0:d.error("Error in ErrorReportingService: "+a);}});},a}();
1526
1539
 
@@ -1694,17 +1707,18 @@ if(b._Helpers.canLog()){if(!b._Helpers.Validators.isValidAttributeValue(c))retur
1694
1707
  if(b._preInit.integrationDelays[a]=c,!0!==c){// If the integration delay is set to false, check to see if there are any
1695
1708
  // other integration delays set to true. It not, process the queued events/.
1696
1709
  var d=Object.keys(b._preInit.integrationDelays);if(0!==d.length){var e=d.some(function(a){return !0===b._preInit.integrationDelays[a]});e||b._APIClient.processQueuedEvents();}}},this._setWrapperSDKInfo=function(a,c){var d=queueIfNotInitialized(function(){b._setWrapperSDKInfo(a,c);},b);d||(b._Store.wrapperSDKInfo===void 0||!b._Store.wrapperSDKInfo.isInfoSet)&&(b._Store.wrapperSDKInfo={name:a,version:c,isInfoSet:!0});},this._registerErrorReportingService=function(a){b._ErrorReportingDispatcher.register(a);},this._registerLoggingService=function(a){b._LoggingDispatcher.register(a);};var c=Constants.Rokt.LauncherInstanceGuidKey;this.setLauncherInstanceGuid=function(){window[c]&&"string"==typeof window[c]||(window[c]=b._Helpers.generateUniqueId());},this.getLauncherInstanceGuid=function(){return window[c]},this.captureTiming=function(a){var b;"undefined"!=typeof window&&(null===(b=window.performance)||void 0===b?void 0:b.mark)&&window.performance.mark(a);};}// Some (server) config settings need to be returned before they are set on SDKConfig in a self hosted environment
1697
- function completeSDKInitialization(a,b,c){var d,e,f=createKitBlocker(b,c),g=c._Helpers.getFeatureFlag;// Web View Bridge is used for cases where the Web SDK is loaded within an iOS or Android device's
1710
+ function completeSDKInitialization(a,b,c){var d,e,f,g,h=createKitBlocker(b,c),i=c._Helpers.getFeatureFlag;// Destroy previous batch uploader to prevent leaked timers and event listeners
1711
+ // Web View Bridge is used for cases where the Web SDK is loaded within an iOS or Android device's
1698
1712
  // Web View. The Web SDK simply acts as a passthrough to the mParticle Native SDK. It is not
1699
1713
  // responsible for sending events directly to mParticle's servers. The Web SDK will not initialize
1700
1714
  // persistence or Identity directly.
1701
- if(c._APIClient=new APIClient(c,f),c._Forwarders=new Forwarders(c,f),c._Store.processConfig(b),c._Identity.idCache=createIdentityCache(c),removeExpiredIdentityCacheDates(c._Identity.idCache),c._Store.webviewBridgeEnabled)c._NativeSdkHelpers.initializeSessionAttributes(a);else {c._Persistence.initializeStorage(),c._Store.syncPersistenceData();// Set up user identitiy variables for later use
1702
- var h=c.Identity.getCurrentUser(),i=h?h.getMPID():null,j=h?h.getUserIdentities().userIdentities:{};c._Store.SDKConfig.identifyRequest=c._Store.hasInvalidIdentifyRequest()?{userIdentities:j}:c._Store.SDKConfig.identifyRequest,g(ReportBatching)&&c._ForwardingStatsUploader.startForwardingStatsTimer();// https://go.mparticle.com/work/SQDSDKS-7639
1703
- var k=g(CaptureIntegrationSpecificIds),l=g(CaptureIntegrationSpecificIdsV2),m=l&&l!==CaptureIntegrationSpecificIdsV2Modes.None||!0===k;if(m){var n;k||l===CaptureIntegrationSpecificIdsV2Modes.All?n="all":l===CaptureIntegrationSpecificIdsV2Modes.RoktOnly&&(n="roktonly"),c._IntegrationCapture=new IntegrationCapture(n),c._IntegrationCapture.capture();}// Configure Rokt Manager with user and filtered user
1704
- var o=parseConfig(b,"Rokt",181);if(o){var p=null===(d=o.settings)||void 0===d?void 0:d.accountId;c._Store.setRoktAccountId(p);var q=o.userAttributeFilters,r=filteredMparticleUser(i,{userAttributeFilters:q},c),s={sandbox:null===b||void 0===b?void 0:b.isDevelopmentMode,launcherOptions:null===b||void 0===b?void 0:b.launcherOptions,domain:null===b||void 0===b?void 0:b.domain};// https://go.mparticle.com/work/SQDSDKS-7339
1705
- c._RoktManager.init(o,r,c.Identity,c._Store,c.Logger,s,c.captureTiming,c._ErrorReportingDispatcher,c._LoggingDispatcher);}c._Forwarders.processForwarders(b,c._APIClient.prepareForwardingStats),c._Forwarders.processPixelConfigs(b),c._SessionManager.initialize(),c._Events.logAST(),processIdentityCallback(c,h,i,j);}// We will continue to clear out the ready queue as part of the initial init flow
1715
+ if((null===(d=c._APIClient)||void 0===d?void 0:d.uploader)&&c._APIClient.uploader.destroy(),c._APIClient=new APIClient(c,h),c._Forwarders=new Forwarders(c,h),c._Store.processConfig(b),c._Identity.idCache=createIdentityCache(c),removeExpiredIdentityCacheDates(c._Identity.idCache),c._Store.webviewBridgeEnabled)c._NativeSdkHelpers.initializeSessionAttributes(a);else {c._Persistence.initializeStorage(),c._Store.syncPersistenceData();// Set up user identitiy variables for later use
1716
+ var j=c.Identity.getCurrentUser(),k=j?j.getMPID():null,l=j?j.getUserIdentities().userIdentities:{};c._Store.SDKConfig.identifyRequest=c._Store.hasInvalidIdentifyRequest()?{userIdentities:l}:c._Store.SDKConfig.identifyRequest,i(ReportBatching)&&c._ForwardingStatsUploader.startForwardingStatsTimer();// https://go.mparticle.com/work/SQDSDKS-7639
1717
+ var m=i(CaptureIntegrationSpecificIds),n=i(CaptureIntegrationSpecificIdsV2),o=n&&n!==CaptureIntegrationSpecificIdsV2Modes.None||!0===m;if(o){var p;m||n===CaptureIntegrationSpecificIdsV2Modes.All?p="all":n===CaptureIntegrationSpecificIdsV2Modes.RoktOnly&&(p="roktonly"),c._IntegrationCapture=new IntegrationCapture(p),c._IntegrationCapture.capture();}// Configure Rokt Manager with user and filtered user
1718
+ var q=parseConfig(b,"Rokt",181);if(q){var r=null===(e=q.settings)||void 0===e?void 0:e.accountId;c._Store.setRoktAccountId(r);var s=q.userAttributeFilters,t=filteredMparticleUser(k,{userAttributeFilters:s},c),u={sandbox:null===b||void 0===b?void 0:b.isDevelopmentMode,launcherOptions:null===b||void 0===b?void 0:b.launcherOptions,domain:null===b||void 0===b?void 0:b.domain};// https://go.mparticle.com/work/SQDSDKS-7339
1719
+ c._RoktManager.init(q,t,c.Identity,c._Store,c.Logger,u,c.captureTiming,c._ErrorReportingDispatcher,c._LoggingDispatcher);}c._Forwarders.processForwarders(b,c._APIClient.prepareForwardingStats),c._Forwarders.processPixelConfigs(b),c._SessionManager.initialize(),c._Events.logAST(),processIdentityCallback(c,j,k,l);}// We will continue to clear out the ready queue as part of the initial init flow
1706
1720
  // if an identify request is unnecessary, such as if there is an existing session
1707
- (c._Store.mpid&&!c._Store.identifyCalled||c._Store.webviewBridgeEnabled)&&(c._Store.isInitialized=!0,c._preInit.readyQueue=processReadyQueue(c._preInit.readyQueue)),null===(e=c.processQueueOnNoFunctional)||void 0===e?void 0:e.call(c),c._Store.isFirstRun&&(c._Store.isFirstRun=!1);}// https://go.mparticle.com/work/SQDSDKS-7061
1721
+ (c._Store.mpid&&!c._Store.identifyCalled||c._Store.webviewBridgeEnabled)&&(c._Store.isInitialized=!0,null===(f=c._CookieConsentManager)||void 0===f?void 0:f.syncNoTargetingAttribute(c.Identity.getCurrentUser()),c._preInit.readyQueue=processReadyQueue(c._preInit.readyQueue)),null===(g=c.processQueueOnNoFunctional)||void 0===g?void 0:g.call(c),c._Store.isFirstRun&&(c._Store.isFirstRun=!1);}// https://go.mparticle.com/work/SQDSDKS-7061
1708
1722
  function createKitBlocker(a,b){var c,d,e,f;/* There are three ways a data plan object for blocking can be passed to the SDK:
1709
1723
  1. Manually via config.dataPlanOptions (this takes priority)
1710
1724
  If not passed in manually, we user the server provided via either
@@ -15,7 +15,7 @@ map:function map(a,b){var c,d,e;if(null===this)throw new TypeError(" this is nul
15
15
  filter:function filter(a/*, thisArg*/){if(void 0===this||null===this)throw new TypeError;var b=Object(this),c=b.length>>>0;if("function"!=typeof a)throw new TypeError;for(var d=[],e=2<=arguments.length?arguments[1]:void 0,f=0;f<c;f++)if(f in b){var g=b[f];a.call(e,g,f,b)&&d.push(g);}return d},// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
16
16
  isArray:function isArray(a){return "[object Array]"===Object.prototype.toString.call(a)},Base64:Base64$1};
17
17
 
18
- var version = "2.64.0";
18
+ var version = "2.65.0";
19
19
 
20
20
  var Constants={sdkVersion:version,sdkVendor:"mparticle",platform:"web",Messages:{DeprecationMessages:{MethodHasBeenDeprecated:"has been deprecated.",MethodMarkedForDeprecationPostfix:"is a deprecated method and will be removed in future releases.",AlternativeMethodPrefix:"Please use the alternate method:"},ErrorMessages:{NoToken:"A token must be specified.",EventNameInvalidType:"Event name must be a valid string value.",EventDataInvalidType:"Event data must be a valid object hash.",LoggingDisabled:"Event logging is currently disabled.",CookieParseError:"Could not parse cookie",EventEmpty:"Event object is null or undefined, cancelling send",APIRequestEmpty:"APIRequest is null or undefined, cancelling send",NoEventType:"Event type must be specified.",TransactionIdRequired:"Transaction ID is required",TransactionRequired:"A transaction attributes object is required",PromotionIdRequired:"Promotion ID is required",BadAttribute:"Attribute value cannot be object or array",BadKey:"Key value cannot be object or array",BadLogPurchase:"Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions",AudienceAPINotEnabled:"Your workspace is not enabled to retrieve user audiences."},InformationMessages:{CookieSearch:"Searching for cookie",CookieFound:"Cookie found, parsing values",CookieNotFound:"Cookies not found",CookieSet:"Setting cookie",CookieSync:"Performing cookie sync",SendBegin:"Starting to send event",SendIdentityBegin:"Starting to send event to identity server",SendWindowsPhone:"Sending event to Windows Phone container",SendIOS:"Calling iOS path: ",SendAndroid:"Calling Android JS interface method: ",SendHttp:"Sending event to mParticle HTTP service",SendAliasHttp:"Sending alias request to mParticle HTTP service",SendIdentityHttp:"Sending event to mParticle HTTP service",StartingNewSession:"Starting new Session",StartingLogEvent:"Starting to log event",StartingLogOptOut:"Starting to log user opt in/out",StartingEndSession:"Starting to end session",StartingInitialization:"Starting to initialize",StartingLogCommerceEvent:"Starting to log commerce event",StartingAliasRequest:"Starting to Alias MPIDs",LoadingConfig:"Loading configuration options",AbandonLogEvent:"Cannot log event, logging disabled or developer token not set",AbandonAliasUsers:"Cannot Alias Users, logging disabled or developer token not set",AbandonStartSession:"Cannot start session, logging disabled or developer token not set",AbandonEndSession:"Cannot end session, logging disabled or developer token not set",NoSessionToEnd:"Cannot end session, no active session found"},ValidationMessages:{ModifyIdentityRequestUserIdentitiesPresent:"identityRequests to modify require userIdentities to be present. Request not sent to server. Please fix and try again",IdentityRequesetInvalidKey:"There is an invalid key on your identityRequest object. It can only contain a `userIdentities` object and a `onUserAlias` function. Request not sent to server. Please fix and try again.",OnUserAliasType:"The onUserAlias value must be a function.",UserIdentities:"The userIdentities key must be an object with keys of identityTypes and values of strings. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidKey:"There is an invalid identity key on your `userIdentities` object within the identityRequest. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidValues:"All user identity values must be strings or null. Request not sent to server. Please fix and try again.",AliasMissingMpid:"Alias Request must contain both a destinationMpid and a sourceMpid",AliasNonUniqueMpid:"Alias Request's destinationMpid and sourceMpid must be unique",AliasMissingTime:"Alias Request must have both a startTime and an endTime",AliasStartBeforeEndTime:"Alias Request's endTime must be later than its startTime"}},NativeSdkPaths:{LogEvent:"logEvent",SetUserTag:"setUserTag",RemoveUserTag:"removeUserTag",SetUserAttribute:"setUserAttribute",RemoveUserAttribute:"removeUserAttribute",SetSessionAttribute:"setSessionAttribute",AddToCart:"addToCart",RemoveFromCart:"removeFromCart",ClearCart:"clearCart",LogOut:"logOut",SetUserAttributeList:"setUserAttributeList",RemoveAllUserAttributes:"removeAllUserAttributes",GetUserAttributesLists:"getUserAttributesLists",GetAllUserAttributes:"getAllUserAttributes",Identify:"identify",Logout:"logout",Login:"login",Modify:"modify",Alias:"aliasUsers",Upload:"upload"},StorageNames:{localStorageName:"mprtcl-api",localStorageNameV3:"mprtcl-v3",cookieName:"mprtcl-api",cookieNameV2:"mprtcl-v2",cookieNameV3:"mprtcl-v3",localStorageNameV4:"mprtcl-v4",localStorageProductsV4:"mprtcl-prodv4",cookieNameV4:"mprtcl-v4",currentStorageName:"mprtcl-v4",currentStorageProductsName:"mprtcl-prodv4"},DefaultConfig:{cookieDomain:null,cookieExpiration:365,logLevel:null,timeout:300,sessionTimeout:30,maxProducts:20,forwarderStatsTimeout:5e3,integrationDelayTimeout:5e3,maxCookieSize:3e3,aliasMaxWindow:90,uploadInterval:0// Maximum milliseconds in between batch uploads, below 500 will mean immediate upload. The server returns this as a string, but we are using it as a number internally
21
21
  },DefaultBaseUrls:{v1SecureServiceUrl:"jssdks.mparticle.com/v1/JS/",v2SecureServiceUrl:"jssdks.mparticle.com/v2/JS/",v3SecureServiceUrl:"jssdks.mparticle.com/v3/JS/",configUrl:"jssdkcdns.mparticle.com/JS/v2/",identityUrl:"identity.mparticle.com/v1/",aliasUrl:"jssdks.mparticle.com/v1/identity/",userAudienceUrl:"nativesdks.mparticle.com/v1/"},// These are the paths that are used to construct the CNAME urls
@@ -27,7 +27,10 @@ CaptureIntegrationSpecificIds:"captureIntegrationSpecificIds",// CaptureIntegrat
27
27
  // - 'all' → capture all IDs
28
28
  // - 'none' → capture none
29
29
  // - 'roktonly' → capture only Rokt-related IDs
30
- CaptureIntegrationSpecificIdsV2:"captureIntegrationSpecificIdsV2",AstBackgroundEvents:"astBackgroundEvents"},DefaultInstance:"default_instance",CCPAPurpose:"data_sale_opt_out",IdentityMethods:{Modify:"modify",Logout:"logout",Login:"login",Identify:"identify"},Environment:{Development:"development",Production:"production"},CaptureIntegrationSpecificIdsV2Modes:{All:"all",None:"none",RoktOnly:"roktonly"},Rokt:{LauncherInstanceGuidKey:"__rokt_li_guid__"}};var ONE_DAY_IN_SECONDS=86400;var MILLIS_IN_ONE_SEC=1e3;// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
30
+ CaptureIntegrationSpecificIdsV2:"captureIntegrationSpecificIds.V2",AstBackgroundEvents:"astBackgroundEvents"},DefaultInstance:"default_instance",CCPAPurpose:"data_sale_opt_out",IdentityMethods:{Modify:"modify",Logout:"logout",Login:"login",Identify:"identify"},Environment:{Development:"development",Production:"production"},CaptureIntegrationSpecificIdsV2Modes:{All:"all",None:"none",RoktOnly:"roktonly"},Rokt:{LauncherInstanceGuidKey:"__rokt_li_guid__"}};var ONE_DAY_IN_SECONDS=86400;var MILLIS_IN_ONE_SEC=1e3;// User attribute set when the end user opts out of ad targeting via
31
+ // launcherOptions.noTargeting. Server-side systems use this attribute
32
+ // to exclude the user from retargeting audiences.
33
+ var NO_TARGETING_ATTRIBUTE="$NoTargeting";// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
31
34
  var HTTP_OK=200;var HTTP_ACCEPTED=202;var HTTP_BAD_REQUEST=400;var HTTP_SERVER_ERROR=500;
32
35
 
33
36
  function _typeof$1(o) {
@@ -487,8 +490,11 @@ function appendUserInfo(a,b){if(b){if(!a)return b.MPID=null,b.ConsentState=null,
487
490
  * Creates an instance of a BatchUploader
488
491
  * @param {IMParticleWebSDKInstance} mpInstance - the mParticle SDK instance
489
492
  * @param {number} uploadInterval - the desired upload interval in milliseconds
490
- */function a(b,c){var d,e;this.offlineStorageEnabled=!1,this.lastASTEventTime=0,this.AST_DEBOUNCE_MS=1e3,this.mpInstance=b,this.uploadIntervalMillis=c,this.batchingEnabled=c>=a.MINIMUM_INTERVAL_MILLIS,this.uploadIntervalMillis<a.MINIMUM_INTERVAL_MILLIS&&(this.uploadIntervalMillis=a.MINIMUM_INTERVAL_MILLIS),this.eventsQueuedForProcessing=[],this.batchesQueuedForProcessing=[],this.offlineStorageEnabled=this.isOfflineStorageAvailable();// When noFunctional is true, prevent events/batches storage
491
- var f=null===(e=b._CookieConsentManager)||void 0===e?void 0:e.getNoFunctional();this.offlineStorageEnabled&&!f&&(this.eventVault=new SessionStorageVault("".concat(b._Store.storageName,"-events")),this.batchVault=new LocalStorageVault("".concat(b._Store.storageName,"-batches")),(d=this.eventsQueuedForProcessing).push.apply(d,this.eventVault.retrieve()));var g=this.mpInstance._Store,h=g.SDKConfig,i=g.devToken,j=this.mpInstance._Helpers.createServiceUrl(h.v3SecureServiceUrl,i);this.uploadUrl="".concat(j,"/events"),this.uploader=window.fetch?new FetchUploader(this.uploadUrl):new XHRUploader(this.uploadUrl),this.triggerUploadInterval(!0,!1),this.addEventListeners();}return a.prototype.isOfflineStorageAvailable=function(){var a=this.mpInstance,b=a._Helpers.getFeatureFlag,c=a._Store.deviceId,d=b(Constants.FeatureFlags.OfflineStorage),e=parseInt(d,10),f=getRampNumber(c);// https://go.mparticle.com/work/SQDSDKS-6317
493
+ */function a(b,c){var d,e;this.offlineStorageEnabled=!1,this.lastASTEventTime=0,this.AST_DEBOUNCE_MS=1e3,this.uploadIntervalTimerId=null,this.exitHandler=null,this.visibilityChangeHandler=null,this.destroyed=!1,this.mpInstance=b,this.uploadIntervalMillis=c,this.batchingEnabled=c>=a.MINIMUM_INTERVAL_MILLIS,this.uploadIntervalMillis<a.MINIMUM_INTERVAL_MILLIS&&(this.uploadIntervalMillis=a.MINIMUM_INTERVAL_MILLIS),this.eventsQueuedForProcessing=[],this.batchesQueuedForProcessing=[],this.offlineStorageEnabled=this.isOfflineStorageAvailable();// When noFunctional is true, prevent events/batches storage
494
+ var f=null===(e=b._CookieConsentManager)||void 0===e?void 0:e.getNoFunctional();this.offlineStorageEnabled&&!f&&(this.eventVault=new SessionStorageVault("".concat(b._Store.storageName,"-events")),this.batchVault=new LocalStorageVault("".concat(b._Store.storageName,"-batches")),(d=this.eventsQueuedForProcessing).push.apply(d,this.eventVault.retrieve()));var g=this.mpInstance._Store,h=g.SDKConfig,i=g.devToken,j=this.mpInstance._Helpers.createServiceUrl(h.v3SecureServiceUrl,i);this.uploadUrl="".concat(j,"/events"),this.uploader=window.fetch?new FetchUploader(this.uploadUrl):new XHRUploader(this.uploadUrl),this.triggerUploadInterval(!0,!1),this.addEventListeners();}/**
495
+ * Cleans up timers and event listeners to prevent leaks when the SDK
496
+ * is re-initialized (e.g. between tests or on repeated init calls).
497
+ */return a.prototype.destroy=function(){this.destroyed=!0,null!==this.uploadIntervalTimerId&&(clearTimeout(this.uploadIntervalTimerId),this.uploadIntervalTimerId=null),this.visibilityChangeHandler&&document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.exitHandler&&(window.removeEventListener("beforeunload",this.exitHandler),window.removeEventListener("pagehide",this.exitHandler)),this.exitHandler=null,this.visibilityChangeHandler=null;},a.prototype.isOfflineStorageAvailable=function(){var a=this.mpInstance,b=a._Helpers.getFeatureFlag,c=a._Store.deviceId,d=b(Constants.FeatureFlags.OfflineStorage),e=parseInt(d,10),f=getRampNumber(c);// https://go.mparticle.com/work/SQDSDKS-6317
492
498
  // TODO: Handle cases where Local Storage is unavailable
493
499
  // Potentially shared between Vault and Persistence as well
494
500
  // https://go.mparticle.com/work/SQDSDKS-5022
@@ -496,9 +502,9 @@ return e>=f},a.prototype.shouldDebounceAndUpdateLastASTTime=function(){var a=Dat
496
502
  if(s){this.mpInstance._IntegrationCapture.capture();var t=this.mpInstance._IntegrationCapture.getClickIdsAsCustomFlags();o=__assign(__assign({},t),o);var u=this.mpInstance._IntegrationCapture.getClickIdsAsIntegrationAttributes();p=__assign(__assign({},u),p);}return n.CustomFlags=o,n.IntegrationAttributes=p,appendUserInfo(m(),n),n},a.prototype.addEventListeners=function(){var a=this,b=this,c=function(){// Check for debounce before creating and queueing event
497
503
  var c=a.mpInstance._Helpers.getFeatureFlag,d=Constants.FeatureFlags.AstBackgroundEvents;if(c(d)){if(b.shouldDebounceAndUpdateLastASTTime())return;// Add application state transition event to queue
498
504
  var e=b.createBackgroundASTEvent();b.queueEvent(e);}// Then trigger the upload with beacon
499
- b.prepareAndUpload(!1,b.isBeaconAvailable());};document.addEventListener("visibilitychange",function(){"hidden"===document.visibilityState&&c();}),window.addEventListener("beforeunload",c),window.addEventListener("pagehide",c);},a.prototype.isBeaconAvailable=function(){return !!navigator.sendBeacon},a.prototype.triggerUploadInterval=function(a,b){var c=this;void 0===a&&(a=!1),void 0===b&&(b=!1),setTimeout(function(){c.prepareAndUpload(a,b);},this.uploadIntervalMillis);},a.prototype.queueEvent=function(a){if(!isEmpty(a)){if(this.eventsQueuedForProcessing.push(a),this.offlineStorageEnabled&&this.eventVault&&this.eventVault.store(this.eventsQueuedForProcessing),this.mpInstance.Logger.isVerbose()){var b=obfuscateDevData(a,this.mpInstance._Store.SDKConfig.isDevelopmentMode);this.mpInstance.Logger.verbose("Queuing event: ".concat(JSON.stringify(b))),this.mpInstance.Logger.verbose("Queued event count: ".concat(this.eventsQueuedForProcessing.length));}this.shouldTriggerImmediateUpload(a.EventDataType)&&this.prepareAndUpload(!1,!1);}},a.prototype.shouldTriggerImmediateUpload=function(a){var b=[MessageType$1.Commerce,MessageType$1.UserIdentityChange];return !this.batchingEnabled||b.includes(a)},(a.createNewBatches=function(a,b,c){if(!b||!a||!a.length)return null;//bucket by MPID, and then by session, ordered by timestamp
505
+ b.prepareAndUpload(!1,b.isBeaconAvailable());};this.exitHandler=c,this.visibilityChangeHandler=function(){"hidden"===document.visibilityState&&c();},document.addEventListener("visibilitychange",this.visibilityChangeHandler),window.addEventListener("beforeunload",c),window.addEventListener("pagehide",c);},a.prototype.isBeaconAvailable=function(){return !!navigator.sendBeacon},a.prototype.triggerUploadInterval=function(a,b){var c=this;void 0===a&&(a=!1),void 0===b&&(b=!1),this.uploadIntervalTimerId=setTimeout(function(){c.prepareAndUpload(a,b);},this.uploadIntervalMillis);},a.prototype.queueEvent=function(a){if(!isEmpty(a)){if(this.eventsQueuedForProcessing.push(a),this.offlineStorageEnabled&&this.eventVault&&this.eventVault.store(this.eventsQueuedForProcessing),this.mpInstance.Logger.isVerbose()){var b=obfuscateDevData(a,this.mpInstance._Store.SDKConfig.isDevelopmentMode);this.mpInstance.Logger.verbose("Queuing event: ".concat(JSON.stringify(b))),this.mpInstance.Logger.verbose("Queued event count: ".concat(this.eventsQueuedForProcessing.length));}this.shouldTriggerImmediateUpload(a.EventDataType)&&this.prepareAndUpload(!1,!1);}},a.prototype.shouldTriggerImmediateUpload=function(a){var b=[MessageType$1.Commerce,MessageType$1.UserIdentityChange];return !this.batchingEnabled||b.includes(a)},(a.createNewBatches=function(a,b,c){if(!b||!a||!a.length)return null;//bucket by MPID, and then by session, ordered by timestamp
500
506
  for(var d,e=[],f=new Map,g=0,h=a;g<h.length;g++){//on initial startup, there may be events logged without an mpid.
501
- if(d=h[g],!d.MPID){var i=b.getMPID();d.MPID=i;}var j=f.get(d.MPID);j||(j=[]),j.push(d),f.set(d.MPID,j);}for(var k=0,l=Array.from(f.entries());k<l.length;k++){for(var m=l[k],i=m[0],n=m[1],o=new Map,p=0,q=n;p<q.length;p++){var d=q[p],j=o.get(d.SessionId);j||(j=[]),j.push(d),o.set(d.SessionId,j);}for(var r=0,s=Array.from(o.entries());r<s.length;r++){var t=s[r],u=convertEvents(i,t[1],c);if(u)try{c._Forwarders.sendBatchToForwarders(u);}catch(a){c.Logger.error("Error forwarding batch to kits. ".concat(a));}var v=c._Store.SDKConfig.onCreateBatch;v&&(u=v(u),u?u.modified=!0:c.Logger.warning("Skiping batch upload because no batch was returned from onCreateBatch callback")),u&&e.push(u);}}return e},a.prototype.prepareAndUpload=function(b,c){return void 0===b&&(b=!1),void 0===c&&(c=!1),__awaiter(this,void 0,void 0,function(){var d,e,f,g,h,i,j,k;return __generator(this,function(l){switch(l.label){case 0:return d=this.mpInstance.Identity.getCurrentUser(),e=this.eventsQueuedForProcessing,this.eventsQueuedForProcessing=[],this.offlineStorageEnabled&&this.eventVault&&this.eventVault.store([]),f=[],isEmpty(e)||(f=a.createNewBatches(e,d,this.mpInstance)),this.offlineStorageEnabled&&this.batchVault&&((i=this.batchesQueuedForProcessing).unshift.apply(i,this.batchVault.retrieve()),this.batchVault.purge()),isEmpty(f)||(j=this.batchesQueuedForProcessing).push.apply(j,f),g=this.batchesQueuedForProcessing,this.batchesQueuedForProcessing=[],[4/*yield*/,this.uploadBatches(g,c)];case 1:return h=l.sent(),isEmpty(h)||(k=this.batchesQueuedForProcessing).unshift.apply(k,h),!c&&this.offlineStorageEnabled&&this.batchVault&&(this.batchVault.store(this.batchesQueuedForProcessing),this.batchesQueuedForProcessing=[]),b&&this.triggerUploadInterval(b,!1),[2/*return*/]}})})},a.prototype.uploadBatches=function(b,c){return __awaiter(this,void 0,void 0,function(){var d,e,f,g,h,j,k;return __generator(this,function(i){switch(i.label){case 0:if(d=b.filter(function(a){return !isEmpty(a.events)}),isEmpty(d))return [2/*return*/,null];this.mpInstance.Logger.isVerbose()&&(e=obfuscateDevData(d,this.mpInstance._Store.SDKConfig.isDevelopmentMode),this.mpInstance.Logger.verbose("Uploading batches: ".concat(JSON.stringify(e))),this.mpInstance.Logger.verbose("Batch count: ".concat(d.length))),f=0,i.label=1;case 1:return f<d.length?(g={method:"POST",headers:{Accept:a.CONTENT_TYPE,"Content-Type":"text/plain;charset=UTF-8"},body:JSON.stringify(d[f])},!(c&&this.isBeaconAvailable()))?[3/*break*/,2]:(h=new Blob([g.body],{type:"text/plain;charset=UTF-8"}),navigator.sendBeacon(this.uploadUrl,h),[3/*break*/,5]):[3/*break*/,6];case 2:return i.trys.push([2,4,,5]),[4/*yield*/,this.uploader.upload(g)];case 3:if(j=i.sent(),200<=j.status&&300>j.status)this.mpInstance.Logger.verbose("Upload success for request ID: ".concat(d[f].source_request_id));else {if(500<=j.status||429===j.status)// Server error, add back current batches and try again later
507
+ if(d=h[g],!d.MPID){var i=b.getMPID();d.MPID=i;}var j=f.get(d.MPID);j||(j=[]),j.push(d),f.set(d.MPID,j);}for(var k=0,l=Array.from(f.entries());k<l.length;k++){for(var m=l[k],i=m[0],n=m[1],o=new Map,p=0,q=n;p<q.length;p++){var d=q[p],j=o.get(d.SessionId);j||(j=[]),j.push(d),o.set(d.SessionId,j);}for(var r=0,s=Array.from(o.entries());r<s.length;r++){var t=s[r],u=convertEvents(i,t[1],c);if(u)try{c._Forwarders.sendBatchToForwarders(u);}catch(a){c.Logger.error("Error forwarding batch to kits. ".concat(a));}var v=c._Store.SDKConfig.onCreateBatch;v&&(u=v(u),u?u.modified=!0:c.Logger.warning("Skiping batch upload because no batch was returned from onCreateBatch callback")),u&&e.push(u);}}return e},a.prototype.prepareAndUpload=function(b,c){return void 0===b&&(b=!1),void 0===c&&(c=!1),__awaiter(this,void 0,void 0,function(){var d,e,f,g,h,i,j,k;return __generator(this,function(l){switch(l.label){case 0:return d=this.mpInstance.Identity.getCurrentUser(),e=this.eventsQueuedForProcessing,this.eventsQueuedForProcessing=[],this.offlineStorageEnabled&&this.eventVault&&this.eventVault.store([]),f=[],isEmpty(e)||(f=a.createNewBatches(e,d,this.mpInstance)),this.offlineStorageEnabled&&this.batchVault&&((i=this.batchesQueuedForProcessing).unshift.apply(i,this.batchVault.retrieve()),this.batchVault.purge()),isEmpty(f)||(j=this.batchesQueuedForProcessing).push.apply(j,f),g=this.batchesQueuedForProcessing,this.batchesQueuedForProcessing=[],[4/*yield*/,this.uploadBatches(g,c)];case 1:return h=l.sent(),isEmpty(h)||(k=this.batchesQueuedForProcessing).unshift.apply(k,h),!c&&this.offlineStorageEnabled&&this.batchVault&&(this.batchVault.store(this.batchesQueuedForProcessing),this.batchesQueuedForProcessing=[]),b&&!this.destroyed&&this.triggerUploadInterval(b,!1),[2/*return*/]}})})},a.prototype.uploadBatches=function(b,c){return __awaiter(this,void 0,void 0,function(){var d,e,f,g,h,j,k;return __generator(this,function(i){switch(i.label){case 0:if(d=b.filter(function(a){return !isEmpty(a.events)}),isEmpty(d))return [2/*return*/,null];this.mpInstance.Logger.isVerbose()&&(e=obfuscateDevData(d,this.mpInstance._Store.SDKConfig.isDevelopmentMode),this.mpInstance.Logger.verbose("Uploading batches: ".concat(JSON.stringify(e))),this.mpInstance.Logger.verbose("Batch count: ".concat(d.length))),f=0,i.label=1;case 1:return f<d.length?(g={method:"POST",headers:{Accept:a.CONTENT_TYPE,"Content-Type":"text/plain;charset=UTF-8"},body:JSON.stringify(d[f])},!(c&&this.isBeaconAvailable()))?[3/*break*/,2]:(h=new Blob([g.body],{type:"text/plain;charset=UTF-8"}),navigator.sendBeacon(this.uploadUrl,h),[3/*break*/,5]):[3/*break*/,6];case 2:return i.trys.push([2,4,,5]),[4/*yield*/,this.uploader.upload(g)];case 3:if(j=i.sent(),200<=j.status&&300>j.status)this.mpInstance.Logger.verbose("Upload success for request ID: ".concat(d[f].source_request_id));else {if(500<=j.status||429===j.status)// Server error, add back current batches and try again later
502
508
  return this.mpInstance.Logger.error("HTTP error status ".concat(j.status," received")),[2/*return*/,d.slice(f,d.length)];if(401<=j.status)//if we're getting a 401, assume we'll keep getting a 401 and clear the uploads.
503
509
  return this.mpInstance.Logger.error("HTTP error status ".concat(j.status," while uploading - please verify your API key.")),[2/*return*/,null];throw console.error("HTTP error status ".concat(j.status," while uploading events."),j),new Error("Uncaught HTTP Error ".concat(j.status,". Batch upload will be re-attempted."))}return [3/*break*/,5];case 4:return k=i.sent(),this.mpInstance.Logger.error("Error sending event to mParticle servers. ".concat(k)),[2/*return*/,d.slice(f,d.length)];case 5:return f++,[3/*break*/,1];case 6:return [2/*return*/,null]}})})},a.CONTENT_TYPE="text/plain;charset=UTF-8",a.MINIMUM_INTERVAL_MILLIS=500,a)}();
504
510
 
@@ -632,9 +638,12 @@ function processFlags(a){var b={},c=Constants.FeatureFlags,d=c.ReportBatching,e=
632
638
  // Passed in config flags take priority over defaults
633
639
  }function processBaseUrls(a,b,c){// an API key is not present in a webview only mode. In this case, no baseUrls are needed
634
640
  if(!c)return {};// Set default baseUrls
635
- // When direct URL routing is false, update baseUrls based custom urls
641
+ // A CNAME (config.domain, e.g. set by the snippet v2.6+) takes precedence
642
+ // over direct URL routing so that customer-configured first-party domains
643
+ // and the snippet's fallback domain are always honored.
644
+ return isEmpty(a.domain)?b.directURLRouting?processDirectBaseUrls(a,c):processCustomBaseUrls(a):processCustomBaseUrls(a);// When direct URL routing is false, update baseUrls based custom urls
636
645
  // passed to the config
637
- return b.directURLRouting?processDirectBaseUrls(a,c):processCustomBaseUrls(a)}function processCustomBaseUrls(a){var b=Constants.DefaultBaseUrls,c=Constants.CNAMEUrlPaths,d={};// newBaseUrls are default if the customer is not using a CNAME
646
+ }function processCustomBaseUrls(a){var b=Constants.DefaultBaseUrls,c=Constants.CNAMEUrlPaths,d={};// newBaseUrls are default if the customer is not using a CNAME
638
647
  // If a customer passes either config.domain or config.v3SecureServiceUrl,
639
648
  // config.identityUrl, etc, the customer is using a CNAME.
640
649
  // config.domain will take priority if a customer passes both.
@@ -1334,8 +1343,12 @@ return a._Helpers.getFeatureFlag(FeatureFlags$1.AudienceAPI)?void(null===d.audie
1334
1343
  * @method getCartProducts
1335
1344
  * @return {Array} array of cart products
1336
1345
  * @deprecated
1337
- */getCartProducts:function getCartProducts(){return a.Logger.warning(generateDeprecationMessage("Identity.getCurrentUser().getCart().getCartProducts()",!0,"eCommerce.logProductAction()","https://docs.mparticle.com/developers/sdk/web/commerce-tracking")),[]}}},this.parseIdentityResponse=function(b,d,f,g,h,i,j){var k,l,m,n=a.Identity.getUser(d),o=n?n.getMPID():null,p=n?n.getUserIdentities().userIdentities:{},q={};a._Store.identityCallInFlight=!1;try{var r,s,t;if(a.Logger.verbose("Parsing \""+h+"\" identity response from server"),l=null!==(r=b.responseText)&&void 0!==r?r:null,a._Store.isLoggedIn=(null===(s=l)||void 0===s?void 0:s.is_logged_in)||!1,hasMPIDChanged(n,l)&&(a._Store.mpid=l.mpid,n&&a._Persistence.setLastSeenTime(d),k=!a._Persistence.getFirstSeenTime(l.mpid),a._Persistence.setFirstSeenTime(l.mpid)),b.status===HTTP_OK){c(CacheIdentity)&&cacheOrClearIdCache(h,i,e.idCache,b,j);var u=e.IdentityAPI.getUser(l.mpid),v=u?u.getUserIdentities().userIdentities:{};h===Modify$1?(q=a._Identity.IdentityRequest.combineUserIdentities(p,g.userIdentities),a._Store.setUserIdentities(d,q)):(h===Identify&&n&&l.mpid===o&&a._Persistence.setFirstSeenTime(l.mpid),a._Store.addMpidToSessionHistory(l.mpid,d),a._CookieSyncManager.attemptCookieSync(l.mpid,k),a._Persistence.swapCurrentUser(d,l.mpid,a._Store.currentSessionMPIDs),g&&!isEmpty(g.userIdentities)&&(q=e.IdentityRequest.combineUserIdentities(v,g.userIdentities)),a._Store.setUserIdentities(l.mpid,q),a._Persistence.update(),a._Store.syncPersistenceData(),a._Persistence.findPrevCookiesBasedOnUI(g),a._Store.context=l.context||a._Store.context),m=a.Identity.getCurrentUser(),tryOnUserAlias(n,m,g,a.Logger);var w=a._Persistence.getPersistence();m&&(a._Persistence.storeDataInMemory(w,m.getMPID()),e.reinitForwardersOnUserChange(n,m),e.setForwarderCallbacks(m,h));var x=IdentityType.getNewIdentitiesByName(q),y=h===Modify$1?p:v;// https://go.mparticle.com/work/SQDSDKS-6501
1338
- e.sendUserIdentityChangeEvent(x,h,l.mpid,y);}if(f){var z=0===b.status?HTTPCodes$2.noHttpCoverage:b.status;a._Helpers.invokeCallback(f,z,l||null,m);}else l&&!isEmpty(l.errors)&&// https://go.mparticle.com/work/SQDSDKS-6500
1346
+ */getCartProducts:function getCartProducts(){return a.Logger.warning(generateDeprecationMessage("Identity.getCurrentUser().getCart().getCartProducts()",!0,"eCommerce.logProductAction()","https://docs.mparticle.com/developers/sdk/web/commerce-tracking")),[]}}},this.parseIdentityResponse=function(b,d,f,g,h,i,j){var k,l,m,n=a.Identity.getUser(d),o=n?n.getMPID():null,p=n?n.getUserIdentities().userIdentities:{},q={};a._Store.identityCallInFlight=!1;try{var r,s,t;if(a.Logger.verbose("Parsing \""+h+"\" identity response from server"),l=null!==(r=b.responseText)&&void 0!==r?r:null,a._Store.isLoggedIn=(null===(s=l)||void 0===s?void 0:s.is_logged_in)||!1,hasMPIDChanged(n,l)&&(a._Store.mpid=l.mpid,n&&a._Persistence.setLastSeenTime(d),k=!a._Persistence.getFirstSeenTime(l.mpid),a._Persistence.setFirstSeenTime(l.mpid)),b.status===HTTP_OK){var u;c(CacheIdentity)&&cacheOrClearIdCache(h,i,e.idCache,b,j);var v=e.IdentityAPI.getUser(l.mpid),w=v?v.getUserIdentities().userIdentities:{};h===Modify$1?(q=a._Identity.IdentityRequest.combineUserIdentities(p,g.userIdentities),a._Store.setUserIdentities(d,q)):(h===Identify&&n&&l.mpid===o&&a._Persistence.setFirstSeenTime(l.mpid),a._Store.addMpidToSessionHistory(l.mpid,d),a._CookieSyncManager.attemptCookieSync(l.mpid,k),a._Persistence.swapCurrentUser(d,l.mpid,a._Store.currentSessionMPIDs),g&&!isEmpty(g.userIdentities)&&(q=e.IdentityRequest.combineUserIdentities(w,g.userIdentities)),a._Store.setUserIdentities(l.mpid,q),a._Persistence.update(),a._Store.syncPersistenceData(),a._Persistence.findPrevCookiesBasedOnUI(g),a._Store.context=l.context||a._Store.context),m=a.Identity.getCurrentUser(),tryOnUserAlias(n,m,g,a.Logger);var x=a._Persistence.getPersistence();m&&(a._Persistence.storeDataInMemory(x,m.getMPID()),e.reinitForwardersOnUserChange(n,m),e.setForwarderCallbacks(m,h));var y=IdentityType.getNewIdentitiesByName(q),z=h===Modify$1?p:w;// Sync $NoTargeting before sendUserIdentityChangeEvent
1347
+ // because UIC events call sendEventToServer which triggers
1348
+ // processQueuedEvents, draining the event queue. The
1349
+ // attribute must be in the store before that happens so
1350
+ // appendUserInfo picks it up.
1351
+ null===(u=a._CookieConsentManager)||void 0===u||u.syncNoTargetingAttribute(m),e.sendUserIdentityChangeEvent(y,h,l.mpid,z);}if(f){var A=0===b.status?HTTPCodes$2.noHttpCoverage:b.status;a._Helpers.invokeCallback(f,A,l||null,m);}else l&&!isEmpty(l.errors)&&// https://go.mparticle.com/work/SQDSDKS-6500
1339
1352
  a.Logger.error("Received HTTP response code of "+b.status+" - "+l.errors[0].message);a.Logger.verbose("Successfully parsed Identity Response"),null===(t=a._APIClient)||void 0===t||t.processQueuedEvents();}catch(c){f&&a._Helpers.invokeCallback(f,b.status,l||null),a.Logger.error("Error parsing JSON response from Identity server: "+c);}a._Store.isInitialized=!0,a._RoktManager.onIdentityComplete(),a._preInit.readyQueue=processReadyQueue(a._preInit.readyQueue);},this.sendUserIdentityChangeEvent=function(b,c,d,f){if(d||c===Modify$1)// https://go.mparticle.com/work/SQDSDKS-6501
1340
1353
  {// https://go.mparticle.com/work/SQDSDKS-6354
1341
1354
  var g=this.IdentityAPI.getUser(d);for(var h in b)// Verifies a change actually happened
@@ -1520,7 +1533,7 @@ Promise.resolve(k).then(function(a){h&&h(a);})["catch"](j);}catch(a){j(a);}});}}
1520
1533
  */var CookieConsentManager=/** @class */function(){function a(a){this.flags=a,this.flags={noFunctional:!0===a.noFunctional,noTargeting:!0===a.noTargeting};}/**
1521
1534
  * Returns true if third-party targeting is disabled.
1522
1535
  * Targeting is allowed when noTargeting is false (default).
1523
- */return a.prototype.getNoTargeting=function(){return this.flags.noTargeting},a.prototype.getNoFunctional=function(){return this.flags.noFunctional},a}();
1536
+ */return a.prototype.getNoTargeting=function(){return this.flags.noTargeting},a.prototype.getNoFunctional=function(){return this.flags.noFunctional},a.prototype.syncNoTargetingAttribute=function(a){a&&(this.flags.noTargeting?a.setUserAttribute(NO_TARGETING_ATTRIBUTE,!0):a.getAllUserAttributes().hasOwnProperty(NO_TARGETING_ATTRIBUTE)&&a.removeUserAttribute(NO_TARGETING_ATTRIBUTE));},a}();
1524
1537
 
1525
1538
  var ErrorReportingDispatcher=/** @class */function(){function a(){this.services=[];}return a.prototype.register=function(a){this.services.push(a);},a.prototype.report=function(a){var b=this;this.services.forEach(function(c){var d;try{c.report(a);}catch(a){null===(d=b.logger)||void 0===d?void 0:d.error("Error in ErrorReportingService: "+a);}});},a}();
1526
1539
 
@@ -1694,17 +1707,18 @@ if(b._Helpers.canLog()){if(!b._Helpers.Validators.isValidAttributeValue(c))retur
1694
1707
  if(b._preInit.integrationDelays[a]=c,!0!==c){// If the integration delay is set to false, check to see if there are any
1695
1708
  // other integration delays set to true. It not, process the queued events/.
1696
1709
  var d=Object.keys(b._preInit.integrationDelays);if(0!==d.length){var e=d.some(function(a){return !0===b._preInit.integrationDelays[a]});e||b._APIClient.processQueuedEvents();}}},this._setWrapperSDKInfo=function(a,c){var d=queueIfNotInitialized(function(){b._setWrapperSDKInfo(a,c);},b);d||(b._Store.wrapperSDKInfo===void 0||!b._Store.wrapperSDKInfo.isInfoSet)&&(b._Store.wrapperSDKInfo={name:a,version:c,isInfoSet:!0});},this._registerErrorReportingService=function(a){b._ErrorReportingDispatcher.register(a);},this._registerLoggingService=function(a){b._LoggingDispatcher.register(a);};var c=Constants.Rokt.LauncherInstanceGuidKey;this.setLauncherInstanceGuid=function(){window[c]&&"string"==typeof window[c]||(window[c]=b._Helpers.generateUniqueId());},this.getLauncherInstanceGuid=function(){return window[c]},this.captureTiming=function(a){var b;"undefined"!=typeof window&&(null===(b=window.performance)||void 0===b?void 0:b.mark)&&window.performance.mark(a);};}// Some (server) config settings need to be returned before they are set on SDKConfig in a self hosted environment
1697
- function completeSDKInitialization(a,b,c){var d,e,f=createKitBlocker(b,c),g=c._Helpers.getFeatureFlag;// Web View Bridge is used for cases where the Web SDK is loaded within an iOS or Android device's
1710
+ function completeSDKInitialization(a,b,c){var d,e,f,g,h=createKitBlocker(b,c),i=c._Helpers.getFeatureFlag;// Destroy previous batch uploader to prevent leaked timers and event listeners
1711
+ // Web View Bridge is used for cases where the Web SDK is loaded within an iOS or Android device's
1698
1712
  // Web View. The Web SDK simply acts as a passthrough to the mParticle Native SDK. It is not
1699
1713
  // responsible for sending events directly to mParticle's servers. The Web SDK will not initialize
1700
1714
  // persistence or Identity directly.
1701
- if(c._APIClient=new APIClient(c,f),c._Forwarders=new Forwarders(c,f),c._Store.processConfig(b),c._Identity.idCache=createIdentityCache(c),removeExpiredIdentityCacheDates(c._Identity.idCache),c._Store.webviewBridgeEnabled)c._NativeSdkHelpers.initializeSessionAttributes(a);else {c._Persistence.initializeStorage(),c._Store.syncPersistenceData();// Set up user identitiy variables for later use
1702
- var h=c.Identity.getCurrentUser(),i=h?h.getMPID():null,j=h?h.getUserIdentities().userIdentities:{};c._Store.SDKConfig.identifyRequest=c._Store.hasInvalidIdentifyRequest()?{userIdentities:j}:c._Store.SDKConfig.identifyRequest,g(ReportBatching)&&c._ForwardingStatsUploader.startForwardingStatsTimer();// https://go.mparticle.com/work/SQDSDKS-7639
1703
- var k=g(CaptureIntegrationSpecificIds),l=g(CaptureIntegrationSpecificIdsV2),m=l&&l!==CaptureIntegrationSpecificIdsV2Modes.None||!0===k;if(m){var n;k||l===CaptureIntegrationSpecificIdsV2Modes.All?n="all":l===CaptureIntegrationSpecificIdsV2Modes.RoktOnly&&(n="roktonly"),c._IntegrationCapture=new IntegrationCapture(n),c._IntegrationCapture.capture();}// Configure Rokt Manager with user and filtered user
1704
- var o=parseConfig(b,"Rokt",181);if(o){var p=null===(d=o.settings)||void 0===d?void 0:d.accountId;c._Store.setRoktAccountId(p);var q=o.userAttributeFilters,r=filteredMparticleUser(i,{userAttributeFilters:q},c),s={sandbox:null===b||void 0===b?void 0:b.isDevelopmentMode,launcherOptions:null===b||void 0===b?void 0:b.launcherOptions,domain:null===b||void 0===b?void 0:b.domain};// https://go.mparticle.com/work/SQDSDKS-7339
1705
- c._RoktManager.init(o,r,c.Identity,c._Store,c.Logger,s,c.captureTiming,c._ErrorReportingDispatcher,c._LoggingDispatcher);}c._Forwarders.processForwarders(b,c._APIClient.prepareForwardingStats),c._Forwarders.processPixelConfigs(b),c._SessionManager.initialize(),c._Events.logAST(),processIdentityCallback(c,h,i,j);}// We will continue to clear out the ready queue as part of the initial init flow
1715
+ if((null===(d=c._APIClient)||void 0===d?void 0:d.uploader)&&c._APIClient.uploader.destroy(),c._APIClient=new APIClient(c,h),c._Forwarders=new Forwarders(c,h),c._Store.processConfig(b),c._Identity.idCache=createIdentityCache(c),removeExpiredIdentityCacheDates(c._Identity.idCache),c._Store.webviewBridgeEnabled)c._NativeSdkHelpers.initializeSessionAttributes(a);else {c._Persistence.initializeStorage(),c._Store.syncPersistenceData();// Set up user identitiy variables for later use
1716
+ var j=c.Identity.getCurrentUser(),k=j?j.getMPID():null,l=j?j.getUserIdentities().userIdentities:{};c._Store.SDKConfig.identifyRequest=c._Store.hasInvalidIdentifyRequest()?{userIdentities:l}:c._Store.SDKConfig.identifyRequest,i(ReportBatching)&&c._ForwardingStatsUploader.startForwardingStatsTimer();// https://go.mparticle.com/work/SQDSDKS-7639
1717
+ var m=i(CaptureIntegrationSpecificIds),n=i(CaptureIntegrationSpecificIdsV2),o=n&&n!==CaptureIntegrationSpecificIdsV2Modes.None||!0===m;if(o){var p;m||n===CaptureIntegrationSpecificIdsV2Modes.All?p="all":n===CaptureIntegrationSpecificIdsV2Modes.RoktOnly&&(p="roktonly"),c._IntegrationCapture=new IntegrationCapture(p),c._IntegrationCapture.capture();}// Configure Rokt Manager with user and filtered user
1718
+ var q=parseConfig(b,"Rokt",181);if(q){var r=null===(e=q.settings)||void 0===e?void 0:e.accountId;c._Store.setRoktAccountId(r);var s=q.userAttributeFilters,t=filteredMparticleUser(k,{userAttributeFilters:s},c),u={sandbox:null===b||void 0===b?void 0:b.isDevelopmentMode,launcherOptions:null===b||void 0===b?void 0:b.launcherOptions,domain:null===b||void 0===b?void 0:b.domain};// https://go.mparticle.com/work/SQDSDKS-7339
1719
+ c._RoktManager.init(q,t,c.Identity,c._Store,c.Logger,u,c.captureTiming,c._ErrorReportingDispatcher,c._LoggingDispatcher);}c._Forwarders.processForwarders(b,c._APIClient.prepareForwardingStats),c._Forwarders.processPixelConfigs(b),c._SessionManager.initialize(),c._Events.logAST(),processIdentityCallback(c,j,k,l);}// We will continue to clear out the ready queue as part of the initial init flow
1706
1720
  // if an identify request is unnecessary, such as if there is an existing session
1707
- (c._Store.mpid&&!c._Store.identifyCalled||c._Store.webviewBridgeEnabled)&&(c._Store.isInitialized=!0,c._preInit.readyQueue=processReadyQueue(c._preInit.readyQueue)),null===(e=c.processQueueOnNoFunctional)||void 0===e?void 0:e.call(c),c._Store.isFirstRun&&(c._Store.isFirstRun=!1);}// https://go.mparticle.com/work/SQDSDKS-7061
1721
+ (c._Store.mpid&&!c._Store.identifyCalled||c._Store.webviewBridgeEnabled)&&(c._Store.isInitialized=!0,null===(f=c._CookieConsentManager)||void 0===f?void 0:f.syncNoTargetingAttribute(c.Identity.getCurrentUser()),c._preInit.readyQueue=processReadyQueue(c._preInit.readyQueue)),null===(g=c.processQueueOnNoFunctional)||void 0===g?void 0:g.call(c),c._Store.isFirstRun&&(c._Store.isFirstRun=!1);}// https://go.mparticle.com/work/SQDSDKS-7061
1708
1722
  function createKitBlocker(a,b){var c,d,e,f;/* There are three ways a data plan object for blocking can be passed to the SDK:
1709
1723
  1. Manually via config.dataPlanOptions (this takes priority)
1710
1724
  If not passed in manually, we user the server provided via either
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.64.0";
206
+ var version = "2.65.0";
207
207
 
208
208
  var Constants = {
209
209
  sdkVersion: version,
@@ -382,7 +382,7 @@ var mParticle = (function () {
382
382
  // - 'all' → capture all IDs
383
383
  // - 'none' → capture none
384
384
  // - 'roktonly' → capture only Rokt-related IDs
385
- CaptureIntegrationSpecificIdsV2: 'captureIntegrationSpecificIdsV2',
385
+ CaptureIntegrationSpecificIdsV2: 'captureIntegrationSpecificIds.V2',
386
386
  AstBackgroundEvents: 'astBackgroundEvents'
387
387
  },
388
388
  DefaultInstance: 'default_instance',
@@ -409,6 +409,10 @@ var mParticle = (function () {
409
409
  // https://go.mparticle.com/work/SQDSDKS-6080
410
410
  var ONE_DAY_IN_SECONDS = 60 * 60 * 24;
411
411
  var MILLIS_IN_ONE_SEC = 1000;
412
+ // User attribute set when the end user opts out of ad targeting via
413
+ // launcherOptions.noTargeting. Server-side systems use this attribute
414
+ // to exclude the user from retargeting audiences.
415
+ var NO_TARGETING_ATTRIBUTE = '$NoTargeting';
412
416
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
413
417
  var HTTP_OK = 200;
414
418
  var HTTP_ACCEPTED = 202;
@@ -2689,6 +2693,10 @@ var mParticle = (function () {
2689
2693
  this.offlineStorageEnabled = false;
2690
2694
  this.lastASTEventTime = 0;
2691
2695
  this.AST_DEBOUNCE_MS = 1000; // 1 second debounce
2696
+ this.uploadIntervalTimerId = null;
2697
+ this.exitHandler = null;
2698
+ this.visibilityChangeHandler = null;
2699
+ this.destroyed = false;
2692
2700
  this.mpInstance = mpInstance;
2693
2701
  this.uploadIntervalMillis = uploadInterval;
2694
2702
  this.batchingEnabled = uploadInterval >= BatchUploader.MINIMUM_INTERVAL_MILLIS;
@@ -2721,6 +2729,26 @@ var mParticle = (function () {
2721
2729
  this.triggerUploadInterval(true, false);
2722
2730
  this.addEventListeners();
2723
2731
  }
2732
+ /**
2733
+ * Cleans up timers and event listeners to prevent leaks when the SDK
2734
+ * is re-initialized (e.g. between tests or on repeated init calls).
2735
+ */
2736
+ BatchUploader.prototype.destroy = function () {
2737
+ this.destroyed = true;
2738
+ if (this.uploadIntervalTimerId !== null) {
2739
+ clearTimeout(this.uploadIntervalTimerId);
2740
+ this.uploadIntervalTimerId = null;
2741
+ }
2742
+ if (this.visibilityChangeHandler) {
2743
+ document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
2744
+ }
2745
+ if (this.exitHandler) {
2746
+ window.removeEventListener('beforeunload', this.exitHandler);
2747
+ window.removeEventListener('pagehide', this.exitHandler);
2748
+ }
2749
+ this.exitHandler = null;
2750
+ this.visibilityChangeHandler = null;
2751
+ };
2724
2752
  BatchUploader.prototype.isOfflineStorageAvailable = function () {
2725
2753
  var _a = this.mpInstance,
2726
2754
  getFeatureFlag = _a._Helpers.getFeatureFlag,
@@ -2816,12 +2844,14 @@ var mParticle = (function () {
2816
2844
  // Then trigger the upload with beacon
2817
2845
  _this.prepareAndUpload(false, _this.isBeaconAvailable());
2818
2846
  };
2819
- // visibility change is a document property, not window
2820
- document.addEventListener('visibilitychange', function () {
2847
+ this.exitHandler = handleExit;
2848
+ this.visibilityChangeHandler = function () {
2821
2849
  if (document.visibilityState === 'hidden') {
2822
2850
  handleExit();
2823
2851
  }
2824
- });
2852
+ };
2853
+ // visibility change is a document property, not window
2854
+ document.addEventListener('visibilitychange', this.visibilityChangeHandler);
2825
2855
  window.addEventListener('beforeunload', handleExit);
2826
2856
  window.addEventListener('pagehide', handleExit);
2827
2857
  };
@@ -2840,7 +2870,7 @@ var mParticle = (function () {
2840
2870
  if (useBeacon === void 0) {
2841
2871
  useBeacon = false;
2842
2872
  }
2843
- setTimeout(function () {
2873
+ this.uploadIntervalTimerId = setTimeout(function () {
2844
2874
  _this_1.prepareAndUpload(triggerFuture, useBeacon);
2845
2875
  }, this.uploadIntervalMillis);
2846
2876
  };
@@ -3004,7 +3034,7 @@ var mParticle = (function () {
3004
3034
  // Clear batch queue since everything should be in Offline Storage
3005
3035
  this.batchesQueuedForProcessing = [];
3006
3036
  }
3007
- if (triggerFuture) {
3037
+ if (triggerFuture && !this.destroyed) {
3008
3038
  this.triggerUploadInterval(triggerFuture, false);
3009
3039
  }
3010
3040
  return [2 /*return*/];
@@ -5108,6 +5138,12 @@ var mParticle = (function () {
5108
5138
  if (!apiKey) {
5109
5139
  return {};
5110
5140
  }
5141
+ // A CNAME (config.domain, e.g. set by the snippet v2.6+) takes precedence
5142
+ // over direct URL routing so that customer-configured first-party domains
5143
+ // and the snippet's fallback domain are always honored.
5144
+ if (!isEmpty(config.domain)) {
5145
+ return processCustomBaseUrls(config);
5146
+ }
5111
5147
  // When direct URL routing is false, update baseUrls based custom urls
5112
5148
  // passed to the config
5113
5149
  if (flags.directURLRouting) {
@@ -8555,6 +8591,7 @@ var mParticle = (function () {
8555
8591
  mpInstance._Persistence.setFirstSeenTime(identityApiResult.mpid);
8556
8592
  }
8557
8593
  if (identityResponse.status === HTTP_OK) {
8594
+ var _mpInstance$_CookieCo;
8558
8595
  if (getFeatureFlag(CacheIdentity)) {
8559
8596
  cacheOrClearIdCache(method, knownIdentities, self.idCache, identityResponse, parsingCachedResponse);
8560
8597
  }
@@ -8601,6 +8638,13 @@ var mParticle = (function () {
8601
8638
  var newIdentitiesByName = IdentityType.getNewIdentitiesByName(newIdentitiesByType);
8602
8639
  var uiByName = method === Modify$1 ? previousUIByName : incomingUIByName;
8603
8640
 
8641
+ // Sync $NoTargeting before sendUserIdentityChangeEvent
8642
+ // because UIC events call sendEventToServer which triggers
8643
+ // processQueuedEvents, draining the event queue. The
8644
+ // attribute must be in the store before that happens so
8645
+ // appendUserInfo picks it up.
8646
+ (_mpInstance$_CookieCo = mpInstance._CookieConsentManager) === null || _mpInstance$_CookieCo === void 0 || _mpInstance$_CookieCo.syncNoTargetingAttribute(newUser);
8647
+
8604
8648
  // https://go.mparticle.com/work/SQDSDKS-6501
8605
8649
  self.sendUserIdentityChangeEvent(newIdentitiesByName, method, identityApiResult.mpid, uiByName);
8606
8650
  }
@@ -10683,6 +10727,14 @@ var mParticle = (function () {
10683
10727
  CookieConsentManager.prototype.getNoFunctional = function () {
10684
10728
  return this.flags.noFunctional;
10685
10729
  };
10730
+ CookieConsentManager.prototype.syncNoTargetingAttribute = function (user) {
10731
+ if (!user) return;
10732
+ if (this.flags.noTargeting) {
10733
+ user.setUserAttribute(NO_TARGETING_ATTRIBUTE, true);
10734
+ } else if (user.getAllUserAttributes().hasOwnProperty(NO_TARGETING_ATTRIBUTE)) {
10735
+ user.removeUserAttribute(NO_TARGETING_ATTRIBUTE);
10736
+ }
10737
+ };
10686
10738
  return CookieConsentManager;
10687
10739
  }();
10688
10740
 
@@ -11716,9 +11768,13 @@ var mParticle = (function () {
11716
11768
  }
11717
11769
  // Some (server) config settings need to be returned before they are set on SDKConfig in a self hosted environment
11718
11770
  function completeSDKInitialization(apiKey, config, mpInstance) {
11719
- var _a, _b;
11771
+ var _a, _b, _c, _d;
11720
11772
  var kitBlocker = createKitBlocker(config, mpInstance);
11721
11773
  var getFeatureFlag = mpInstance._Helpers.getFeatureFlag;
11774
+ // Destroy previous batch uploader to prevent leaked timers and event listeners
11775
+ if ((_a = mpInstance._APIClient) === null || _a === void 0 ? void 0 : _a.uploader) {
11776
+ mpInstance._APIClient.uploader.destroy();
11777
+ }
11722
11778
  mpInstance._APIClient = new APIClient(mpInstance, kitBlocker);
11723
11779
  mpInstance._Forwarders = new Forwarders(mpInstance, kitBlocker);
11724
11780
  mpInstance._Store.processConfig(config);
@@ -11762,7 +11818,7 @@ var mParticle = (function () {
11762
11818
  // Configure Rokt Manager with user and filtered user
11763
11819
  var roktConfig = parseConfig(config, 'Rokt', 181);
11764
11820
  if (roktConfig) {
11765
- var accountId = (_a = roktConfig.settings) === null || _a === void 0 ? void 0 : _a.accountId;
11821
+ var accountId = (_b = roktConfig.settings) === null || _b === void 0 ? void 0 : _b.accountId;
11766
11822
  mpInstance._Store.setRoktAccountId(accountId);
11767
11823
  var userAttributeFilters = roktConfig.userAttributeFilters;
11768
11824
  var roktFilteredUser = filteredMparticleUser(currentUserMPID, {
@@ -11788,11 +11844,14 @@ var mParticle = (function () {
11788
11844
  // if an identify request is unnecessary, such as if there is an existing session
11789
11845
  if (mpInstance._Store.mpid && !mpInstance._Store.identifyCalled || mpInstance._Store.webviewBridgeEnabled) {
11790
11846
  mpInstance._Store.isInitialized = true;
11847
+ // Sync $NoTargeting user attribute on re-init when no identity call is made
11848
+ // if for some reason there was a change in boolean between init calls
11849
+ (_c = mpInstance._CookieConsentManager) === null || _c === void 0 ? void 0 : _c.syncNoTargetingAttribute(mpInstance.Identity.getCurrentUser());
11791
11850
  mpInstance._preInit.readyQueue = processReadyQueue(mpInstance._preInit.readyQueue);
11792
11851
  }
11793
11852
  // For noFunctional sessions with no identity, drain any pre-init ready callbacks
11794
11853
  // that were queued before _CookieConsentManager was available to evaluate the condition.
11795
- (_b = mpInstance.processQueueOnNoFunctional) === null || _b === void 0 ? void 0 : _b.call(mpInstance);
11854
+ (_d = mpInstance.processQueueOnNoFunctional) === null || _d === void 0 ? void 0 : _d.call(mpInstance);
11796
11855
  // https://go.mparticle.com/work/SQDSDKS-6040
11797
11856
  if (mpInstance._Store.isFirstRun) {
11798
11857
  mpInstance._Store.isFirstRun = false;
@@ -31,12 +31,21 @@ export declare class BatchUploader {
31
31
  private uploader;
32
32
  private lastASTEventTime;
33
33
  private readonly AST_DEBOUNCE_MS;
34
+ private uploadIntervalTimerId;
35
+ private exitHandler;
36
+ private visibilityChangeHandler;
37
+ private destroyed;
34
38
  /**
35
39
  * Creates an instance of a BatchUploader
36
40
  * @param {IMParticleWebSDKInstance} mpInstance - the mParticle SDK instance
37
41
  * @param {number} uploadInterval - the desired upload interval in milliseconds
38
42
  */
39
43
  constructor(mpInstance: IMParticleWebSDKInstance, uploadInterval: number);
44
+ /**
45
+ * Cleans up timers and event listeners to prevent leaks when the SDK
46
+ * is re-initialized (e.g. between tests or on repeated init calls).
47
+ */
48
+ destroy(): void;
40
49
  private isOfflineStorageAvailable;
41
50
  private shouldDebounceAndUpdateLastASTTime;
42
51
  private createBackgroundASTEvent;
@@ -165,7 +165,7 @@ declare const Constants: {
165
165
  readonly CacheIdentity: "cacheIdentity";
166
166
  readonly AudienceAPI: "audienceAPI";
167
167
  readonly CaptureIntegrationSpecificIds: "captureIntegrationSpecificIds";
168
- readonly CaptureIntegrationSpecificIdsV2: "captureIntegrationSpecificIdsV2";
168
+ readonly CaptureIntegrationSpecificIdsV2: "captureIntegrationSpecificIds.V2";
169
169
  readonly AstBackgroundEvents: "astBackgroundEvents";
170
170
  };
171
171
  readonly DefaultInstance: "default_instance";
@@ -192,6 +192,7 @@ declare const Constants: {
192
192
  export default Constants;
193
193
  export declare const ONE_DAY_IN_SECONDS: number;
194
194
  export declare const MILLIS_IN_ONE_SEC = 1000;
195
+ export declare const NO_TARGETING_ATTRIBUTE = "$NoTargeting";
195
196
  export declare const HTTP_OK: 200;
196
197
  export declare const HTTP_ACCEPTED: 202;
197
198
  export declare const HTTP_BAD_REQUEST: 400;
@@ -1,3 +1,4 @@
1
+ import { IMParticleUser } from './identity-user-interfaces';
1
2
  /**
2
3
  * Cookie consent flags control SDK behavior based on user consent preferences for Rokt integration.
3
4
  * @see https://docs.rokt.com/developers/integration-guides/web/cookie-consent-flags/
@@ -24,6 +25,11 @@ export interface ICookieConsentManager {
24
25
  * Functional tracking is allowed when noFunctional is false (default)
25
26
  */
26
27
  getNoFunctional: () => boolean;
28
+ /**
29
+ * Syncs the $NoTargeting user attribute based on the current noTargeting flag.
30
+ * Sets the attribute when noTargeting is true, removes it when false.
31
+ */
32
+ syncNoTargetingAttribute: (user: IMParticleUser | null) => void;
27
33
  }
28
34
  /**
29
35
  * CookieConsentManager handles storage and access of consent flags (noFunctional, noTargeting)
@@ -47,4 +53,5 @@ export default class CookieConsentManager implements ICookieConsentManager {
47
53
  * Functional tracking is allowed when noFunctional is false (default).
48
54
  */
49
55
  getNoFunctional(): boolean;
56
+ syncNoTargetingAttribute(user: IMParticleUser | null): void;
50
57
  }
@@ -75,7 +75,7 @@ export interface IFeatureFlags {
75
75
  directURLRouting?: boolean;
76
76
  cacheIdentity?: boolean;
77
77
  captureIntegrationSpecificIds?: boolean;
78
- captureIntegrationSpecificIdsV2?: string;
78
+ 'captureIntegrationSpecificIds.V2'?: string;
79
79
  astBackgroundEvents?: boolean;
80
80
  }
81
81
  export interface IStore {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mparticle/web-sdk",
3
- "version": "2.64.0",
3
+ "version": "2.65.0",
4
4
  "description": "mParticle core SDK for web applications",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -47,6 +47,10 @@ export class BatchUploader {
47
47
  private uploader: AsyncUploader;
48
48
  private lastASTEventTime: number = 0;
49
49
  private readonly AST_DEBOUNCE_MS: number = 1000; // 1 second debounce
50
+ private uploadIntervalTimerId: ReturnType<typeof setTimeout> | null = null;
51
+ private exitHandler: (() => void) | null = null;
52
+ private visibilityChangeHandler: (() => void) | null = null;
53
+ private destroyed = false;
50
54
 
51
55
  /**
52
56
  * Creates an instance of a BatchUploader
@@ -105,6 +109,31 @@ export class BatchUploader {
105
109
  this.addEventListeners();
106
110
  }
107
111
 
112
+ /**
113
+ * Cleans up timers and event listeners to prevent leaks when the SDK
114
+ * is re-initialized (e.g. between tests or on repeated init calls).
115
+ */
116
+ public destroy(): void {
117
+ this.destroyed = true;
118
+
119
+ if (this.uploadIntervalTimerId !== null) {
120
+ clearTimeout(this.uploadIntervalTimerId);
121
+ this.uploadIntervalTimerId = null;
122
+ }
123
+
124
+ if (this.visibilityChangeHandler) {
125
+ document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
126
+ }
127
+
128
+ if (this.exitHandler) {
129
+ window.removeEventListener('beforeunload', this.exitHandler);
130
+ window.removeEventListener('pagehide', this.exitHandler);
131
+ }
132
+
133
+ this.exitHandler = null;
134
+ this.visibilityChangeHandler = null;
135
+ }
136
+
108
137
  private isOfflineStorageAvailable(): boolean {
109
138
  const {
110
139
  _Helpers: { getFeatureFlag },
@@ -218,12 +247,17 @@ export class BatchUploader {
218
247
  // Then trigger the upload with beacon
219
248
  _this.prepareAndUpload(false, _this.isBeaconAvailable());
220
249
  };
221
- // visibility change is a document property, not window
222
- document.addEventListener('visibilitychange', () => {
250
+
251
+ this.exitHandler = handleExit;
252
+
253
+ this.visibilityChangeHandler = () => {
223
254
  if (document.visibilityState === 'hidden') {
224
255
  handleExit();
225
256
  }
226
- });
257
+ };
258
+
259
+ // visibility change is a document property, not window
260
+ document.addEventListener('visibilitychange', this.visibilityChangeHandler);
227
261
  window.addEventListener('beforeunload', handleExit);
228
262
  window.addEventListener('pagehide', handleExit);
229
263
  }
@@ -240,7 +274,7 @@ export class BatchUploader {
240
274
  triggerFuture: boolean = false,
241
275
  useBeacon: boolean = false
242
276
  ): void {
243
- setTimeout(() => {
277
+ this.uploadIntervalTimerId = setTimeout(() => {
244
278
  this.prepareAndUpload(triggerFuture, useBeacon);
245
279
  }, this.uploadIntervalMillis);
246
280
  }
@@ -445,7 +479,7 @@ export class BatchUploader {
445
479
  this.batchesQueuedForProcessing = [];
446
480
  }
447
481
 
448
- if (triggerFuture) {
482
+ if (triggerFuture && !this.destroyed) {
449
483
  this.triggerUploadInterval(triggerFuture, false);
450
484
  }
451
485
  }
package/src/constants.ts CHANGED
@@ -193,7 +193,7 @@ const Constants = {
193
193
  // - 'all' → capture all IDs
194
194
  // - 'none' → capture none
195
195
  // - 'roktonly' → capture only Rokt-related IDs
196
- CaptureIntegrationSpecificIdsV2: 'captureIntegrationSpecificIdsV2',
196
+ CaptureIntegrationSpecificIdsV2: 'captureIntegrationSpecificIds.V2',
197
197
  AstBackgroundEvents: 'astBackgroundEvents',
198
198
  },
199
199
  DefaultInstance: 'default_instance',
@@ -225,6 +225,11 @@ export default Constants;
225
225
  export const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
226
226
  export const MILLIS_IN_ONE_SEC = 1000;
227
227
 
228
+ // User attribute set when the end user opts out of ad targeting via
229
+ // launcherOptions.noTargeting. Server-side systems use this attribute
230
+ // to exclude the user from retargeting audiences.
231
+ export const NO_TARGETING_ATTRIBUTE = '$NoTargeting';
232
+
228
233
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
229
234
  export const HTTP_OK = 200 as const;
230
235
  export const HTTP_ACCEPTED = 202 as const;
@@ -1,3 +1,6 @@
1
+ import { NO_TARGETING_ATTRIBUTE } from './constants';
2
+ import { IMParticleUser } from './identity-user-interfaces';
3
+
1
4
  /**
2
5
  * Cookie consent flags control SDK behavior based on user consent preferences for Rokt integration.
3
6
  * @see https://docs.rokt.com/developers/integration-guides/web/cookie-consent-flags/
@@ -27,6 +30,12 @@ export interface ICookieConsentManager {
27
30
  * Functional tracking is allowed when noFunctional is false (default)
28
31
  */
29
32
  getNoFunctional: () => boolean;
33
+
34
+ /**
35
+ * Syncs the $NoTargeting user attribute based on the current noTargeting flag.
36
+ * Sets the attribute when noTargeting is true, removes it when false.
37
+ */
38
+ syncNoTargetingAttribute: (user: IMParticleUser | null) => void;
30
39
  }
31
40
 
32
41
  /**
@@ -61,4 +70,18 @@ export default class CookieConsentManager implements ICookieConsentManager {
61
70
  getNoFunctional(): boolean {
62
71
  return this.flags.noFunctional;
63
72
  }
73
+
74
+ syncNoTargetingAttribute(user: IMParticleUser | null): void {
75
+ if (!user) return;
76
+
77
+ if (this.flags.noTargeting) {
78
+ user.setUserAttribute(NO_TARGETING_ATTRIBUTE, true);
79
+ } else if (
80
+ user
81
+ .getAllUserAttributes()
82
+ .hasOwnProperty(NO_TARGETING_ATTRIBUTE)
83
+ ) {
84
+ user.removeUserAttribute(NO_TARGETING_ATTRIBUTE);
85
+ }
86
+ }
64
87
  }
package/src/identity.js CHANGED
@@ -1524,6 +1524,15 @@ export default function Identity(mpInstance) {
1524
1524
  const uiByName =
1525
1525
  method === Modify ? previousUIByName : incomingUIByName;
1526
1526
 
1527
+ // Sync $NoTargeting before sendUserIdentityChangeEvent
1528
+ // because UIC events call sendEventToServer which triggers
1529
+ // processQueuedEvents, draining the event queue. The
1530
+ // attribute must be in the store before that happens so
1531
+ // appendUserInfo picks it up.
1532
+ mpInstance._CookieConsentManager?.syncNoTargetingAttribute(
1533
+ newUser
1534
+ );
1535
+
1527
1536
  // https://go.mparticle.com/work/SQDSDKS-6501
1528
1537
  self.sendUserIdentityChangeEvent(
1529
1538
  newIdentitiesByName,
@@ -1446,6 +1446,11 @@ function completeSDKInitialization(apiKey, config, mpInstance) {
1446
1446
  const kitBlocker = createKitBlocker(config, mpInstance);
1447
1447
  const { getFeatureFlag } = mpInstance._Helpers;
1448
1448
 
1449
+ // Destroy previous batch uploader to prevent leaked timers and event listeners
1450
+ if (mpInstance._APIClient?.uploader) {
1451
+ mpInstance._APIClient.uploader.destroy();
1452
+ }
1453
+
1449
1454
  mpInstance._APIClient = new APIClient(mpInstance, kitBlocker);
1450
1455
  mpInstance._Forwarders = new Forwarders(mpInstance, kitBlocker);
1451
1456
  mpInstance._Store.processConfig(config);
@@ -1553,6 +1558,12 @@ function completeSDKInitialization(apiKey, config, mpInstance) {
1553
1558
  ) {
1554
1559
  mpInstance._Store.isInitialized = true;
1555
1560
 
1561
+ // Sync $NoTargeting user attribute on re-init when no identity call is made
1562
+ // if for some reason there was a change in boolean between init calls
1563
+ mpInstance._CookieConsentManager?.syncNoTargetingAttribute(
1564
+ mpInstance.Identity.getCurrentUser()
1565
+ );
1566
+
1556
1567
  mpInstance._preInit.readyQueue = processReadyQueue(
1557
1568
  mpInstance._preInit.readyQueue
1558
1569
  );
package/src/store.ts CHANGED
@@ -148,7 +148,7 @@ export interface IFeatureFlags {
148
148
  directURLRouting?: boolean;
149
149
  cacheIdentity?: boolean;
150
150
  captureIntegrationSpecificIds?: boolean;
151
- captureIntegrationSpecificIdsV2?: string;
151
+ 'captureIntegrationSpecificIds.V2'?: string;
152
152
  astBackgroundEvents?: boolean;
153
153
  }
154
154
 
@@ -800,6 +800,13 @@ export function processBaseUrls(
800
800
  // Set default baseUrls
801
801
  let baseUrls: Dictionary<string>;
802
802
 
803
+ // A CNAME (config.domain, e.g. set by the snippet v2.6+) takes precedence
804
+ // over direct URL routing so that customer-configured first-party domains
805
+ // and the snippet's fallback domain are always honored.
806
+ if (!isEmpty(config.domain)) {
807
+ return processCustomBaseUrls(config);
808
+ }
809
+
803
810
  // When direct URL routing is false, update baseUrls based custom urls
804
811
  // passed to the config
805
812
  if (flags.directURLRouting) {