@mparticle/web-sdk 2.28.3 → 2.29.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.
@@ -154,11 +154,11 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
154
154
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
155
155
  };
156
156
 
157
- var version = "2.28.3";
157
+ var version = "2.29.0";
158
158
 
159
159
  var Constants={sdkVersion:version,sdkVendor:"mparticle",platform:"web",Messages:{DeprecationMessages:{MethodIsDeprecatedPostfix:"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
160
160
  },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/"},Base64CookieKeys:{csm:1,sa:1,ss:1,ua:1,ui:1,csd:1,ia:1,con:1},// https://go.mparticle.com/work/SQDSDKS-6039
161
- SDKv2NonMPIDCookieKeys:{gs:1,cu:1,l:1,globalSettings:1,currentUserMPID:1},HTTPCodes:{noHttpCoverage:-1,activeIdentityRequest:-2,activeSession:-3,validationIssue:-4,nativeIdentityRequest:-5,loggingDisabledOrMissingAPIKey:-6,tooManyRequests:429},FeatureFlags:{ReportBatching:"reportBatching",EventBatchingIntervalMillis:"eventBatchingIntervalMillis",OfflineStorage:"offlineStorage",DirectUrlRouting:"directURLRouting",CacheIdentity:"cacheIdentity",AudienceAPI:"audienceAPI"},DefaultInstance:"default_instance",CCPAPurpose:"data_sale_opt_out",IdentityMethods:{Modify:"modify",Logout:"logout",Login:"login",Identify:"identify"}};var ONE_DAY_IN_SECONDS=86400;var MILLIS_IN_ONE_SEC=1e3;// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
161
+ SDKv2NonMPIDCookieKeys:{gs:1,cu:1,l:1,globalSettings:1,currentUserMPID:1},HTTPCodes:{noHttpCoverage:-1,activeIdentityRequest:-2,activeSession:-3,validationIssue:-4,nativeIdentityRequest:-5,loggingDisabledOrMissingAPIKey:-6,tooManyRequests:429},FeatureFlags:{ReportBatching:"reportBatching",EventBatchingIntervalMillis:"eventBatchingIntervalMillis",OfflineStorage:"offlineStorage",DirectUrlRouting:"directURLRouting",CacheIdentity:"cacheIdentity",AudienceAPI:"audienceAPI",CaptureIntegrationSpecificIds:"captureIntegrationSpecificIds"},DefaultInstance:"default_instance",CCPAPurpose:"data_sale_opt_out",IdentityMethods:{Modify:"modify",Logout:"logout",Login:"login",Identify:"identify"}};var ONE_DAY_IN_SECONDS=86400;var MILLIS_IN_ONE_SEC=1e3;// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
162
162
  var HTTP_OK=200;var HTTP_ACCEPTED=202;
163
163
 
164
164
  var Messages$a=Constants.Messages,createCookieString=function(a){return replaceCommasWithPipes(replaceQuotesWithApostrophes(a))},revertCookieString=function(a){return replacePipesWithCommas(replaceApostrophesWithQuotes(a))},inArray=function(a,b){var c=0;if(Array.prototype.indexOf)return 0<=a.indexOf(b,0);for(var d=a.length;c<d;c++)if(c in a&&a[c]===b)return !0;return !1},findKeyInObject=function(a,b){if(b&&a)for(var c in a)if(a.hasOwnProperty(c)&&c.toLowerCase()===b.toLowerCase())return c;return null},generateDeprecationMessage=function(a,b){var c=[a,Messages$a.DeprecationMessages.MethodIsDeprecatedPostfix];return b&&(c.push(b),c.push(Messages$a.DeprecationMessages.MethodIsDeprecatedPostfix)),c.join(" ")};function generateHash(a){var b,c=0;if(void 0===a||null===a)return 0;if(a=a.toString().toLowerCase(),Array.prototype.reduce)return a.split("").reduce(function(c,d){return c=(c<<5)-c+d.charCodeAt(0),c&c},0);if(0===a.length)return c;for(var d=0;d<a.length;d++)b=a.charCodeAt(d),c=(c<<5)-c+b,c&=c;return c}var generateRandomValue=function(){var b,c;return window.crypto&&window.crypto.getRandomValues&&(b=window.crypto.getRandomValues(new Uint8Array(1))),b?(c^b[0]%16>>c/4).toString(16):(c^16*Math.random()>>c/4).toString(16)},generateUniqueId=function(b){return void 0===b&&(b=""),b// if the placeholder was passed, return
@@ -171,7 +171,11 @@ var Messages$a=Constants.Messages,createCookieString=function(a){return replaceC
171
171
  "".concat(1e7,"-").concat(1e3,"-").concat(4e3,"-").concat(8e3,"-").concat(1e11).replace(/[018]/g,// zeroes, ones, and eights with
172
172
  generateUniqueId// random hex digits
173
173
  )},getRampNumber=function(a){if(!a)return 100;var b=generateHash(a);return Math.abs(b%100)+1},isObject=function(a){var b=Object.prototype.toString.call(a);return "[object Object]"===b||"[object Error]"===b},parseNumber=function(a){if(isNaN(a)||!isFinite(a))return 0;var b=parseFloat(a);return isNaN(b)?0:b},parseStringOrNumber=function(a){return isStringOrNumber(a)?a:null},replaceCommasWithPipes=function(a){return a.replace(/,/g,"|")},replacePipesWithCommas=function(a){return a.replace(/\|/g,",")},replaceApostrophesWithQuotes=function(a){return a.replace(/\'/g,"\"")},replaceQuotesWithApostrophes=function(a){return a.replace(/\"/g,"'")},returnConvertedBoolean=function(a){return "false"!==a&&"0"!==a&&!!a},decoded=function(a){return decodeURIComponent(a.replace(/\+/g," "))},converted=function(a){return 0===a.indexOf("\"")&&(a=a.slice(1,-1).replace(/\\"/g,"\"").replace(/\\\\/g,"\\")),a},isString=function(a){return "string"==typeof a},isNumber=function(a){return "number"==typeof a},isBoolean=function(a){return "boolean"==typeof a},isFunction=function(a){return "function"==typeof a},isValidCustomFlagProperty=function(a){return isNumber(a)||isString(a)||isBoolean(a)},toDataPlanSlug=function(a){// Make sure we are only acting on strings or numbers
174
- return isStringOrNumber(a)?a.toString().toLowerCase().replace(/[^0-9a-zA-Z]+/g,"_"):""},isDataPlanSlug=function(a){return a===toDataPlanSlug(a)},isStringOrNumber=function(a){return isString(a)||isNumber(a)},isEmpty=function(a){return null==a||!(Object.keys(a)||a).length},moveElementToEnd=function(a,b){return a.slice(0,b).concat(a.slice(b+1),a[b])};/**
174
+ return isStringOrNumber(a)?a.toString().toLowerCase().replace(/[^0-9a-zA-Z]+/g,"_"):""},isDataPlanSlug=function(a){return a===toDataPlanSlug(a)},isStringOrNumber=function(a){return isString(a)||isNumber(a)},isEmpty=function(a){return null==a||!(Object.keys(a)||a).length},moveElementToEnd=function(a,b){return a.slice(0,b).concat(a.slice(b+1),a[b])},queryStringParser=function(a,b){void 0===b&&(b=[]);var c,d={};if(!a)return d;if("undefined"!=typeof URL&&"undefined"!=typeof URLSearchParams){var e=new URL(a);c=new URLSearchParams(e.search);}else c=queryStringParserFallback(a);return isEmpty(b)?c.forEach(function(a,b){d[b]=a;}):b.forEach(function(a){var b=c.get(a);b&&(d[a]=b);}),d},queryStringParserFallback=function(a){var b={},c=a.split("?")[1]||"",d=c.split("&");return d.forEach(function(a){var c=a.split("="),d=c[0],e=c[1];d&&e&&(b[d]=decodeURIComponent(e||""));}),{get:function get(a){return b[a]},forEach:function forEach(a){for(var c in b)b.hasOwnProperty(c)&&a(b[c],c);}}},getCookies=function(a){// Helper function to parse cookies from document.cookie
175
+ var b=function parseCookies(){return "undefined"==typeof window?[]:window.document.cookie.split(";").map(function(a){return a.trim()})}();// Helper function to filter cookies by keys
176
+ // Parse cookies from document.cookie
177
+ // Filter cookies by keys if provided
178
+ return function filterCookies(a,b){for(var c={},d=0,e=a;d<e.length;d++){var f=e[d],g=f.split("="),h=g[0],i=g[1];(!b||b.includes(h))&&(c[h]=i);}return c}(b,a)},getHref=function(){return "undefined"!=typeof window&&window.location?window.location.href:""};/**
175
179
  * Returns a value between 1-100 inclusive.
176
180
  */ // FIXME: REFACTOR for V3
177
181
 
@@ -566,7 +570,7 @@ var c=b.Identity.getCurrentUser();return a===(null===c||void 0===c?void 0:c.getM
566
570
  // such as if the SDK is being self-hosted and the flags are different on the server config
567
571
  // https://go.mparticle.com/work/SQDSDKS-6317
568
572
  d.SDKConfig.flags=processFlags(a);var j=processBaseUrls(a,d.SDKConfig.flags,c);for(var k in j)d.SDKConfig[k]=j[k];e?d.SDKConfig.workspaceToken=e:b.Logger.warning("You should have a workspaceToken on your config object for security purposes."),d.storageName=f(e),d.prodStorageName=g(e),d.SDKConfig.requiredWebviewBridgeName=i||e,d.webviewBridgeEnabled=h(d.SDKConfig.requiredWebviewBridgeName,d.SDKConfig.minWebviewBridgeVersion),d.configurationLoaded=!0;};}// https://go.mparticle.com/work/SQDSDKS-6317
569
- function processFlags(a){var b={},c=Constants.FeatureFlags,d=c.ReportBatching,e=c.EventBatchingIntervalMillis,f=c.OfflineStorage,g=c.DirectUrlRouting,h=c.CacheIdentity,i=c.AudienceAPI;return a.flags?(b[d]=a.flags[d]||!1,b[e]=parseNumber(a.flags[e])||Constants.DefaultConfig.uploadInterval,b[f]=a.flags[f]||"0",b[g]="True"===a.flags[g],b[h]="True"===a.flags[h],b[i]="True"===a.flags[i],b):{};// https://go.mparticle.com/work/SQDSDKS-6317
573
+ function processFlags(a){var b={},c=Constants.FeatureFlags,d=c.ReportBatching,e=c.EventBatchingIntervalMillis,f=c.OfflineStorage,g=c.DirectUrlRouting,h=c.CacheIdentity,i=c.AudienceAPI,j=c.CaptureIntegrationSpecificIds;return a.flags?(b[d]=a.flags[d]||!1,b[e]=parseNumber(a.flags[e])||Constants.DefaultConfig.uploadInterval,b[f]=a.flags[f]||"0",b[g]="True"===a.flags[g],b[h]="True"===a.flags[h],b[i]="True"===a.flags[i],b[j]="True"===a.flags[j],b):{};// https://go.mparticle.com/work/SQDSDKS-6317
570
574
  // Passed in config flags take priority over defaults
571
575
  }function processBaseUrls(a,b,c){// an API key is not present in a webview only mode. In this case, no baseUrls are needed
572
576
  if(!c)return {};// Set default baseUrls
@@ -1085,11 +1089,12 @@ this.appendUserInfo=function(b,c){if(c){if(!b)return c.MPID=null,c.ConsentState=
1085
1089
  // tracked. If this is an `optOut` Event, we set `optOut` to the inverse of the SDK's
1086
1090
  // `isEnabled` boolean which is controlled via `MPInstanceManager.setOptOut`.
1087
1091
  // TODO: Why is Webview Bridge Enabled or Opt Out necessary here?
1088
- if(a._Store.sessionId||c.messageType===Types.MessageType.OptOut||a._Store.webviewBridgeEnabled){f=c.hasOwnProperty("toEventAPIObject")?c.toEventAPIObject():{// This is an artifact from v2 events where SessionStart/End and AST event
1092
+ if(a._Store.sessionId||c.messageType===Types.MessageType.OptOut||a._Store.webviewBridgeEnabled){var h=__assign({},c.customFlags);// https://go.mparticle.com/work/SQDSDKS-5053
1093
+ if(a._Helpers.getFeatureFlag&&a._Helpers.getFeatureFlag(Constants.FeatureFlags.CaptureIntegrationSpecificIds)){a._IntegrationCapture.capture();var i=a._IntegrationCapture.getClickIdsAsCustomFlags();h=__assign(__assign({},i),h);}f=c.hasOwnProperty("toEventAPIObject")?c.toEventAPIObject():{// This is an artifact from v2 events where SessionStart/End and AST event
1089
1094
  // names are numbers (1, 2, or 10), but going forward with v3, these lifecycle
1090
1095
  // events do not have names, but are denoted by their `event_type`
1091
- EventName:c.name||c.messageType,EventCategory:c.eventType,EventAttributes:a._Helpers.sanitizeAttributes(c.data,c.name),SourceMessageId:c.sourceMessageId||a._Helpers.generateUniqueId(),EventDataType:c.messageType,CustomFlags:c.customFlags||{},UserAttributeChanges:c.userAttributeChanges,UserIdentityChanges:c.userIdentityChanges},c.messageType!==Types.MessageType.SessionEnd&&(a._Store.dateLastEventSent=new Date),e={// FIXME: Deprecate when we get rid of V2
1092
- Store:a._Store.serverSettings,SDKVersion:Constants.sdkVersion,SessionId:a._Store.sessionId,SessionStartDate:a._Store.sessionStartDate?a._Store.sessionStartDate.getTime():0,Debug:a._Store.SDKConfig.isDevelopmentMode,Location:a._Store.currentPosition,OptOut:g,ExpandedEventCount:0,AppVersion:a.getAppVersion(),AppName:a.getAppName(),Package:a._Store.SDKConfig["package"],ClientGeneratedId:a._Store.clientId,DeviceId:a._Store.deviceId,IntegrationAttributes:a._Store.integrationAttributes,CurrencyCode:a._Store.currencyCode,DataPlan:a._Store.SDKConfig.dataPlan?a._Store.SDKConfig.dataPlan:{}},f.EventDataType===MessageType.AppStateTransition&&(f.IsFirstRun=a._Store.isFirstRun,f.LaunchReferral=window.location.href||null),f.CurrencyCode=a._Store.currencyCode;var h=d||a.Identity.getCurrentUser();return b.appendUserInfo(h,f),c.messageType===Types.MessageType.SessionEnd&&(f.SessionLength=a._Store.dateLastEventSent.getTime()-a._Store.sessionStartDate.getTime(),f.currentSessionMPIDs=a._Store.currentSessionMPIDs,f.EventAttributes=a._Store.sessionAttributes,a._Store.currentSessionMPIDs=[],a._Store.sessionStartDate=null),e.Timestamp=a._Store.dateLastEventSent.getTime(),a._Helpers.extend({},f,e)}return null},this.convertEventToV2DTO=function(c){var d={n:c.EventName,et:c.EventCategory,ua:c.UserAttributes,ui:c.UserIdentities,ia:c.IntegrationAttributes,str:c.Store,attrs:c.EventAttributes,sdk:c.SDKVersion,sid:c.SessionId,sl:c.SessionLength,ssd:c.SessionStartDate,dt:c.EventDataType,dbg:c.Debug,ct:c.Timestamp,lc:c.Location,o:c.OptOut,eec:c.ExpandedEventCount,av:c.AppVersion,cgid:c.ClientGeneratedId,das:c.DeviceId,mpid:c.MPID,smpids:c.currentSessionMPIDs};c.DataPlan&&c.DataPlan.PlanId&&(d.dp_id=c.DataPlan.PlanId,c.DataPlan.PlanVersion&&(d.dp_v=c.DataPlan.PlanVersion));var e=b.convertToConsentStateV2DTO(c.ConsentState);return e&&(d.con=e),c.EventDataType===MessageType.AppStateTransition&&(d.fr=c.IsFirstRun,d.iu=!1,d.at=ApplicationTransitionType.AppInit,d.lr=c.LaunchReferral,d.attrs=null),c.CustomFlags&&convertCustomFlags(c,d),c.EventDataType===MessageType.Commerce?(d.cu=c.CurrencyCode,c.ShoppingCart&&(d.sc={pl:convertProductListToV2DTO(c.ShoppingCart.ProductList)}),c.ProductAction?d.pd={an:c.ProductAction.ProductActionType,cs:a._Helpers.parseNumber(c.ProductAction.CheckoutStep),co:c.ProductAction.CheckoutOptions,pl:convertProductListToV2DTO(c.ProductAction.ProductList),ti:c.ProductAction.TransactionId,ta:c.ProductAction.Affiliation,tcc:c.ProductAction.CouponCode,tr:a._Helpers.parseNumber(c.ProductAction.TotalAmount),ts:a._Helpers.parseNumber(c.ProductAction.ShippingAmount),tt:a._Helpers.parseNumber(c.ProductAction.TaxAmount)}:c.PromotionAction?d.pm={an:c.PromotionAction.PromotionActionType,pl:c.PromotionAction.PromotionList.map(function(a){return {id:a.Id,nm:a.Name,cr:a.Creative,ps:a.Position?a.Position:0}})}:c.ProductImpressions&&(d.pi=c.ProductImpressions.map(function(a){return {pil:a.ProductImpressionList,pl:convertProductListToV2DTO(a.ProductList)}}))):c.EventDataType===MessageType.Profile&&(d.pet=c.ProfileMessageType),d};}
1096
+ EventName:c.name||c.messageType,EventCategory:c.eventType,EventAttributes:a._Helpers.sanitizeAttributes(c.data,c.name),SourceMessageId:c.sourceMessageId||a._Helpers.generateUniqueId(),EventDataType:c.messageType,CustomFlags:h,UserAttributeChanges:c.userAttributeChanges,UserIdentityChanges:c.userIdentityChanges},c.messageType!==Types.MessageType.SessionEnd&&(a._Store.dateLastEventSent=new Date),e={// FIXME: Deprecate when we get rid of V2
1097
+ Store:a._Store.serverSettings,SDKVersion:Constants.sdkVersion,SessionId:a._Store.sessionId,SessionStartDate:a._Store.sessionStartDate?a._Store.sessionStartDate.getTime():0,Debug:a._Store.SDKConfig.isDevelopmentMode,Location:a._Store.currentPosition,OptOut:g,ExpandedEventCount:0,AppVersion:a.getAppVersion(),AppName:a.getAppName(),Package:a._Store.SDKConfig["package"],ClientGeneratedId:a._Store.clientId,DeviceId:a._Store.deviceId,IntegrationAttributes:a._Store.integrationAttributes,CurrencyCode:a._Store.currencyCode,DataPlan:a._Store.SDKConfig.dataPlan?a._Store.SDKConfig.dataPlan:{}},f.EventDataType===MessageType.AppStateTransition&&(f.IsFirstRun=a._Store.isFirstRun,f.LaunchReferral=window.location.href||null),f.CurrencyCode=a._Store.currencyCode;var j=d||a.Identity.getCurrentUser();return b.appendUserInfo(j,f),c.messageType===Types.MessageType.SessionEnd&&(f.SessionLength=a._Store.dateLastEventSent.getTime()-a._Store.sessionStartDate.getTime(),f.currentSessionMPIDs=a._Store.currentSessionMPIDs,f.EventAttributes=a._Store.sessionAttributes,a._Store.currentSessionMPIDs=[],a._Store.sessionStartDate=null),e.Timestamp=a._Store.dateLastEventSent.getTime(),a._Helpers.extend({},f,e)}return null},this.convertEventToV2DTO=function(c){var d={n:c.EventName,et:c.EventCategory,ua:c.UserAttributes,ui:c.UserIdentities,ia:c.IntegrationAttributes,str:c.Store,attrs:c.EventAttributes,sdk:c.SDKVersion,sid:c.SessionId,sl:c.SessionLength,ssd:c.SessionStartDate,dt:c.EventDataType,dbg:c.Debug,ct:c.Timestamp,lc:c.Location,o:c.OptOut,eec:c.ExpandedEventCount,av:c.AppVersion,cgid:c.ClientGeneratedId,das:c.DeviceId,mpid:c.MPID,smpids:c.currentSessionMPIDs};c.DataPlan&&c.DataPlan.PlanId&&(d.dp_id=c.DataPlan.PlanId,c.DataPlan.PlanVersion&&(d.dp_v=c.DataPlan.PlanVersion));var e=b.convertToConsentStateV2DTO(c.ConsentState);return e&&(d.con=e),c.EventDataType===MessageType.AppStateTransition&&(d.fr=c.IsFirstRun,d.iu=!1,d.at=ApplicationTransitionType.AppInit,d.lr=c.LaunchReferral,d.attrs=null),c.CustomFlags&&convertCustomFlags(c,d),c.EventDataType===MessageType.Commerce?(d.cu=c.CurrencyCode,c.ShoppingCart&&(d.sc={pl:convertProductListToV2DTO(c.ShoppingCart.ProductList)}),c.ProductAction?d.pd={an:c.ProductAction.ProductActionType,cs:a._Helpers.parseNumber(c.ProductAction.CheckoutStep),co:c.ProductAction.CheckoutOptions,pl:convertProductListToV2DTO(c.ProductAction.ProductList),ti:c.ProductAction.TransactionId,ta:c.ProductAction.Affiliation,tcc:c.ProductAction.CouponCode,tr:a._Helpers.parseNumber(c.ProductAction.TotalAmount),ts:a._Helpers.parseNumber(c.ProductAction.ShippingAmount),tt:a._Helpers.parseNumber(c.ProductAction.TaxAmount)}:c.PromotionAction?d.pm={an:c.PromotionAction.PromotionActionType,pl:c.PromotionAction.PromotionList.map(function(a){return {id:a.Id,nm:a.Name,cr:a.Creative,ps:a.Position?a.Position:0}})}:c.ProductImpressions&&(d.pi=c.ProductImpressions.map(function(a){return {pil:a.ProductImpressionList,pl:convertProductListToV2DTO(a.ProductList)}}))):c.EventDataType===MessageType.Profile&&(d.pet=c.ProfileMessageType),d};}
1093
1098
 
1094
1099
  function forwardingStatsUploader(a){function b(){var b=a._Forwarders.getForwarderStatsQueue(),c=a._Persistence.forwardingStatsBatches.uploadsTable,d=Date.now();for(var e in b.length&&(c[d]={uploading:!1,data:b},a._Forwarders.setForwarderStatsQueue([])),c)(function(b){if(c.hasOwnProperty(b)&&!1===c[b].uploading){var d=function(){4===e.readyState&&(200===e.status||202===e.status?(a.Logger.verbose("Successfully sent "+e.statusText+" from server"),delete c[b]):"4"===e.status.toString()[0]?429!==e.status&&delete c[b]:c[b].uploading=!1);},e=a._Helpers.createXHR(d),f=c[b].data;c[b].uploading=!0,a._APIClient.sendBatchForwardingStatsToServer(f,e);}})(e);}this.startForwardingStatsTimer=function(){mParticle._forwardingStatsTimer=setInterval(function(){b();},a._Store.SDKConfig.forwarderStatsTimeout);};}
1095
1100
 
@@ -1402,7 +1407,21 @@ var HTTPCodes$2=Constants.HTTPCodes,Messages$2=Constants.Messages;function sendA
1402
1407
  var HTTPCodes$1=Constants.HTTPCodes,Messages$1=Constants.Messages,Modify=Constants.IdentityMethods.Modify;function IdentityAPIClient(a){this.sendAliasRequest=/*#__PURE__*/function(){var b=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function d(b,c){return _regeneratorRuntime.wrap(function(d){for(;;)switch(d.prev=d.next){case 0:return d.next=2,sendAliasRequest(a,b,c);case 2:case"end":return d.stop()}},d)}));return function(){return b.apply(this,arguments)}}(),this.sendIdentityRequest=function(b,c,d,e,f,g,h){var i,j;if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityBegin),!b)return void a.Logger.error(Messages$1.ErrorMessages.APIRequestEmpty);if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityHttp),i=a._Helpers.createXHR(function xhrCallback(){if(4===i.readyState){a.Logger.verbose("Received "+i.statusText+" from server");// https://go.mparticle.com/work/SQDSDKS-6565
1403
1408
  var b=xhrIdentityResponseAdapter(i);f(b,j,d,e,c,h,!1);}}),i)try{a._Store.identityCallInFlight?a._Helpers.invokeCallback(d,HTTPCodes$1.activeIdentityRequest,"There is currently an Identity request processing. Please wait for this to return before requesting again"):(j=g||null,c===Modify?i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+g+"/"+c):i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+c),i.setRequestHeader("Content-Type","application/json"),i.setRequestHeader("x-mp-key",a._Store.devToken),a._Store.identityCallInFlight=!0,i.send(JSON.stringify(b)));}catch(b){a._Store.identityCallInFlight=!1,a._Helpers.invokeCallback(d,HTTPCodes$1.noHttpCoverage,b),a.Logger.error("Error sending identity request to servers with status code "+i.status+" - "+b);}};}
1404
1409
 
1405
- var Messages=Constants.Messages,HTTPCodes=Constants.HTTPCodes,FeatureFlags=Constants.FeatureFlags,ReportBatching=FeatureFlags.ReportBatching,StartingInitialization=Messages.InformationMessages.StartingInitialization;/**
1410
+ // The formatted ClickID value must be of the form version.subdomainIndex.creationTime.<fbclid>, where:
1411
+ // - version is always this prefix: fb
1412
+ // - subdomainIndex is which domain the cookie is defined on ('com' = 0, 'example.com' = 1, 'www.example.com' = 2)
1413
+ // - creationTime is the UNIX time since epoch in milliseconds when the _fbc was stored. If you don't save the _fbc cookie, use the timestamp when you first observed or received this fbclid value
1414
+ // - <fbclid> is the value for the fbclid query parameter in the page URL.
1415
+ // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc
1416
+ var facebookClickIdProcessor=function(a,b,c){if(!a||!b)return "";var d=null===b||void 0===b?void 0:b.split("//");if(!d)return "";var e=d[1].split("/"),f=e[0].split("."),g=1;// The rules for subdomainIndex are for parsing the domain portion
1417
+ // of the URL for cookies, but in this case we are parsing the URL
1418
+ // itself, so we can ignore the use of 0 for 'com'
1419
+ 3<=f.length&&(g=2);// If timestamp is not provided, use the current time
1420
+ var h=c||Date.now();return "fb.".concat(g,".").concat(h,".").concat(a)};var integrationMapping={fbclid:{mappedKey:"Facebook.ClickId",processor:facebookClickIdProcessor},_fbp:{mappedKey:"Facebook.BrowserId"},_fbc:{mappedKey:"Facebook.ClickId"}},IntegrationCapture=/** @class */function(){function a(){this.initialTimestamp=Date.now();}/**
1421
+ * Captures Integration Ids from cookies and query params and stores them in clickIds object
1422
+ */return a.prototype.capture=function(){var a=this.captureQueryParams()||{},b=this.captureCookies()||{};a.fbclid&&b._fbc&&delete b._fbc,this.clickIds=__assign(__assign(__assign({},this.clickIds),a),b);},a.prototype.captureCookies=function(){var a=getCookies(Object.keys(integrationMapping));return this.applyProcessors(a)},a.prototype.captureQueryParams=function(){var a=this.getQueryParams();return this.applyProcessors(a,getHref(),this.initialTimestamp)},a.prototype.getQueryParams=function(){return queryStringParser(getHref(),Object.keys(integrationMapping))},a.prototype.getClickIdsAsCustomFlags=function(){var a,b={};if(!this.clickIds)return b;for(var c=0,d=Object.entries(this.clickIds);c<d.length;c++){var e=d[c],f=e[0],g=e[1],h=null===(a=integrationMapping[f])||void 0===a?void 0:a.mappedKey;isEmpty(h)||(b[h]=g);}return b},a.prototype.applyProcessors=function(a,b,c){for(var d,e={},f=0,g=Object.entries(a);f<g.length;f++){var h=g[f],i=h[0],j=h[1],k=null===(d=integrationMapping[i])||void 0===d?void 0:d.processor;e[i]=k?k(j,b,c):j;}return e},a}();
1423
+
1424
+ var Messages=Constants.Messages,HTTPCodes=Constants.HTTPCodes,FeatureFlags=Constants.FeatureFlags,ReportBatching=FeatureFlags.ReportBatching,CaptureIntegrationSpecificIds=FeatureFlags.CaptureIntegrationSpecificIds,StartingInitialization=Messages.InformationMessages.StartingInitialization;/**
1406
1425
  * <p>All of the following methods can be called on the primary mParticle class. In version 2.10.0, we introduced <a href="https://docs.mparticle.com/developers/sdk/web/multiple-instances/">multiple instances</a>. If you are using multiple instances (self hosted environments only), you should call these methods on each instance.</p>
1407
1426
  * <p>In current versions of mParticle, if your site has one instance, that instance name is 'default_instance'. Any methods called on mParticle on a site with one instance will be mapped to the `default_instance`.</p>
1408
1427
  * <p>This is for simplicity and backwards compatibility. For example, calling mParticle.logPageView() automatically maps to mParticle.getInstance('default_instance').logPageView().</p>
@@ -1576,7 +1595,7 @@ var Messages=Constants.Messages,HTTPCodes=Constants.HTTPCodes,FeatureFlags=Const
1576
1595
  If there is no delay, then the events sent before an integration attribute is included would not
1577
1596
  be forwarded successfully server side.
1578
1597
  */ // Internal use only. Used by our wrapper SDKs to identify themselves during initialization.
1579
- this._instanceName=a,this._NativeSdkHelpers=new NativeSdkHelpers(this),this._SessionManager=new SessionManager(this),this._Persistence=new _Persistence(this),this._Helpers=new Helpers(this),this._Events=new Events(this),this._CookieSyncManager=new cookieSyncManager(this),this._ServerModel=new ServerModel(this),this._Ecommerce=new Ecommerce(this),this._ForwardingStatsUploader=new forwardingStatsUploader(this),this._Consent=new Consent(this),this._IdentityAPIClient=new IdentityAPIClient(this),this._preInit={readyQueue:[],integrationDelays:{},forwarderConstructors:[]},this.IdentityType=Types.IdentityType,this.EventType=Types.EventType,this.CommerceEventType=Types.CommerceEventType,this.PromotionType=Types.PromotionActionType,this.ProductActionType=Types.ProductActionType,this._Identity=new Identity(this),this.Identity=this._Identity.IdentityAPI,this.generateHash=this._Helpers.generateHash,this.getDeviceId=this._Persistence.getDeviceId,"undefined"!=typeof window&&window.mParticle&&window.mParticle.config&&window.mParticle.config.hasOwnProperty("rq")&&(this._preInit.readyQueue=window.mParticle.config.rq),this.init=function(a,b){var c=this;// config code - Fetch config when requestConfig = true, otherwise, proceed with SDKInitialization
1598
+ this._instanceName=a,this._NativeSdkHelpers=new NativeSdkHelpers(this),this._SessionManager=new SessionManager(this),this._Persistence=new _Persistence(this),this._Helpers=new Helpers(this),this._Events=new Events(this),this._CookieSyncManager=new cookieSyncManager(this),this._ServerModel=new ServerModel(this),this._Ecommerce=new Ecommerce(this),this._ForwardingStatsUploader=new forwardingStatsUploader(this),this._Consent=new Consent(this),this._IdentityAPIClient=new IdentityAPIClient(this),this._preInit={readyQueue:[],integrationDelays:{},forwarderConstructors:[]},this._IntegrationCapture=new IntegrationCapture,this.IdentityType=Types.IdentityType,this.EventType=Types.EventType,this.CommerceEventType=Types.CommerceEventType,this.PromotionType=Types.PromotionActionType,this.ProductActionType=Types.ProductActionType,this._Identity=new Identity(this),this.Identity=this._Identity.IdentityAPI,this.generateHash=this._Helpers.generateHash,this.getDeviceId=this._Persistence.getDeviceId,"undefined"!=typeof window&&window.mParticle&&window.mParticle.config&&window.mParticle.config.hasOwnProperty("rq")&&(this._preInit.readyQueue=window.mParticle.config.rq),this.init=function(a,b){var c=this;// config code - Fetch config when requestConfig = true, otherwise, proceed with SDKInitialization
1580
1599
  // Since fetching the configuration is asynchronous, we must pass completeSDKInitialization
1581
1600
  // to it for it to be run after fetched
1582
1601
  if(b||console.warn("You did not pass a config object to init(). mParticle will not initialize properly"),runPreConfigFetchInitialization(this,a,b),!b)return void console.error("No config available on the window, please pass a config object to mParticle.init()");if(!b.hasOwnProperty("requestConfig")||b.requestConfig){var d=new ConfigAPIClient(a,b,this);d.getSDKConfiguration().then(function(d){var e=c._Helpers.extend({},b,d);completeSDKInitialization(a,e,c);});}else completeSDKInitialization(a,b,this);},this.setLogLevel=function(a){b.Logger.setLogLevel(a);},this.reset=function(a){try{a._Persistence.resetPersistence(),a._Store&&delete a._Store;}catch(a){console.error("Cannot reset mParticle",a);}},this._resetForTests=function(a,b,c){c._Store&&delete c._Store,c._Store=new Store(a,c),c._Store.isLocalStorageAvailable=c._Persistence.determineLocalStorageAvailability(window.localStorage),c._Events.stopTracking(),b||c._Persistence.resetPersistence(),c._Persistence.forwardingStatsBatches.uploadsTable={},c._Persistence.forwardingStatsBatches.forwardingStatsEventQueue=[],c._preInit={readyQueue:[],pixelConfigurations:[],integrationDelays:{},forwarderConstructors:[],isDevelopmentMode:!1};},this.ready=function(a){b.isInitialized()&&"function"==typeof a?a():b._preInit.readyQueue.push(a);},this.getEnvironment=function(){return b._Store.SDKConfig.isDevelopmentMode?Types.Environment.Development:Types.Environment.Production},this.getVersion=function(){return Constants.sdkVersion},this.setAppVersion=function(a){var c=queueIfNotInitialized(function(){b.setAppVersion(a);},b);c||(b._Store.SDKConfig.appVersion=a,b._Persistence.update());},this.setDeviceId=function(a){var c=queueIfNotInitialized(function(){b.setDeviceId(a);},b);c||this._Store.setDeviceId(a);},this.isInitialized=function(){return !!b._Store&&b._Store.isInitialized},this.getAppName=function(){return b._Store.SDKConfig.appName},this.setAppName=function(a){var c=queueIfNotInitialized(function(){b.setAppName(a);},b);c||(b._Store.SDKConfig.appName=a);},this.getAppVersion=function(){return b._Store.SDKConfig.appVersion},this.stopTrackingLocation=function(){b._SessionManager.resetSessionTimer(),b._Events.stopTracking();},this.startTrackingLocation=function(a){isFunction(a)||b.Logger.warning("Warning: Location tracking is triggered, but not including a callback into the `startTrackingLocation` may result in events logged too quickly and not being associated with a location."),b._SessionManager.resetSessionTimer(),b._Events.startTracking(a);},this.setPosition=function(a,c){var d=queueIfNotInitialized(function(){b.setPosition(a,c);},b);d||(b._SessionManager.resetSessionTimer(),"number"==typeof a&&"number"==typeof c?b._Store.currentPosition={lat:a,lng:c}:b.Logger.error("Position latitude and/or longitude must both be of type number"));},this.startNewSession=function(){b._SessionManager.startNewSession();},this.endSession=function(){// Sends true as an over ride vs when endSession is called from the setInterval
@@ -1737,7 +1756,7 @@ function completeSDKInitialization(a,b,c){var d=createKitBlocker(b,c);// Web Vie
1737
1756
  // responsible for sending events directly to mParticle's servers. The Web SDK will not initialize
1738
1757
  // persistence or Identity directly.
1739
1758
  if(c._APIClient=new APIClient(c,d),c._Forwarders=new Forwarders(c,d),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
1740
- var e=c.Identity.getCurrentUser(),f=e?e.getMPID():null,g=e?e.getUserIdentities().userIdentities:{};c._Store.SDKConfig.identifyRequest=c._Store.hasInvalidIdentifyRequest()?{userIdentities:g}:c._Store.SDKConfig.identifyRequest,c._Helpers.getFeatureFlag(ReportBatching)&&c._ForwardingStatsUploader.startForwardingStatsTimer(),c._Forwarders.processForwarders(b,c._APIClient.prepareForwardingStats),c._Forwarders.processPixelConfigs(b),c._SessionManager.initialize(),c._Events.logAST(),processIdentityCallback(c,e,f,g);}c._Store.isInitialized=!0;// Call any functions that are waiting for the library to be initialized
1759
+ var e=c.Identity.getCurrentUser(),f=e?e.getMPID():null,g=e?e.getUserIdentities().userIdentities:{};c._Store.SDKConfig.identifyRequest=c._Store.hasInvalidIdentifyRequest()?{userIdentities:g}:c._Store.SDKConfig.identifyRequest,c._Helpers.getFeatureFlag(ReportBatching)&&c._ForwardingStatsUploader.startForwardingStatsTimer(),c._Helpers.getFeatureFlag(CaptureIntegrationSpecificIds)&&c._IntegrationCapture.capture(),c._Forwarders.processForwarders(b,c._APIClient.prepareForwardingStats),c._Forwarders.processPixelConfigs(b),c._SessionManager.initialize(),c._Events.logAST(),processIdentityCallback(c,e,f,g);}c._Store.isInitialized=!0;// Call any functions that are waiting for the library to be initialized
1741
1760
  try{c._preInit.readyQueue=processReadyQueue(c._preInit.readyQueue);}catch(a){c.Logger.error(a);}// https://go.mparticle.com/work/SQDSDKS-6040
1742
1761
  c._Store.isFirstRun&&(c._Store.isFirstRun=!1);}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:
1743
1762
  1. Manually via config.dataPlanOptions (this takes priority)
@@ -154,11 +154,11 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
154
154
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
155
155
  };
156
156
 
157
- var version = "2.28.3";
157
+ var version = "2.29.0";
158
158
 
159
159
  var Constants={sdkVersion:version,sdkVendor:"mparticle",platform:"web",Messages:{DeprecationMessages:{MethodIsDeprecatedPostfix:"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
160
160
  },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/"},Base64CookieKeys:{csm:1,sa:1,ss:1,ua:1,ui:1,csd:1,ia:1,con:1},// https://go.mparticle.com/work/SQDSDKS-6039
161
- SDKv2NonMPIDCookieKeys:{gs:1,cu:1,l:1,globalSettings:1,currentUserMPID:1},HTTPCodes:{noHttpCoverage:-1,activeIdentityRequest:-2,activeSession:-3,validationIssue:-4,nativeIdentityRequest:-5,loggingDisabledOrMissingAPIKey:-6,tooManyRequests:429},FeatureFlags:{ReportBatching:"reportBatching",EventBatchingIntervalMillis:"eventBatchingIntervalMillis",OfflineStorage:"offlineStorage",DirectUrlRouting:"directURLRouting",CacheIdentity:"cacheIdentity",AudienceAPI:"audienceAPI"},DefaultInstance:"default_instance",CCPAPurpose:"data_sale_opt_out",IdentityMethods:{Modify:"modify",Logout:"logout",Login:"login",Identify:"identify"}};var ONE_DAY_IN_SECONDS=86400;var MILLIS_IN_ONE_SEC=1e3;// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
161
+ SDKv2NonMPIDCookieKeys:{gs:1,cu:1,l:1,globalSettings:1,currentUserMPID:1},HTTPCodes:{noHttpCoverage:-1,activeIdentityRequest:-2,activeSession:-3,validationIssue:-4,nativeIdentityRequest:-5,loggingDisabledOrMissingAPIKey:-6,tooManyRequests:429},FeatureFlags:{ReportBatching:"reportBatching",EventBatchingIntervalMillis:"eventBatchingIntervalMillis",OfflineStorage:"offlineStorage",DirectUrlRouting:"directURLRouting",CacheIdentity:"cacheIdentity",AudienceAPI:"audienceAPI",CaptureIntegrationSpecificIds:"captureIntegrationSpecificIds"},DefaultInstance:"default_instance",CCPAPurpose:"data_sale_opt_out",IdentityMethods:{Modify:"modify",Logout:"logout",Login:"login",Identify:"identify"}};var ONE_DAY_IN_SECONDS=86400;var MILLIS_IN_ONE_SEC=1e3;// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
162
162
  var HTTP_OK=200;var HTTP_ACCEPTED=202;
163
163
 
164
164
  var Messages$a=Constants.Messages,createCookieString=function(a){return replaceCommasWithPipes(replaceQuotesWithApostrophes(a))},revertCookieString=function(a){return replacePipesWithCommas(replaceApostrophesWithQuotes(a))},inArray=function(a,b){var c=0;if(Array.prototype.indexOf)return 0<=a.indexOf(b,0);for(var d=a.length;c<d;c++)if(c in a&&a[c]===b)return !0;return !1},findKeyInObject=function(a,b){if(b&&a)for(var c in a)if(a.hasOwnProperty(c)&&c.toLowerCase()===b.toLowerCase())return c;return null},generateDeprecationMessage=function(a,b){var c=[a,Messages$a.DeprecationMessages.MethodIsDeprecatedPostfix];return b&&(c.push(b),c.push(Messages$a.DeprecationMessages.MethodIsDeprecatedPostfix)),c.join(" ")};function generateHash(a){var b,c=0;if(void 0===a||null===a)return 0;if(a=a.toString().toLowerCase(),Array.prototype.reduce)return a.split("").reduce(function(c,d){return c=(c<<5)-c+d.charCodeAt(0),c&c},0);if(0===a.length)return c;for(var d=0;d<a.length;d++)b=a.charCodeAt(d),c=(c<<5)-c+b,c&=c;return c}var generateRandomValue=function(){var b,c;return window.crypto&&window.crypto.getRandomValues&&(b=window.crypto.getRandomValues(new Uint8Array(1))),b?(c^b[0]%16>>c/4).toString(16):(c^16*Math.random()>>c/4).toString(16)},generateUniqueId=function(b){return void 0===b&&(b=""),b// if the placeholder was passed, return
@@ -171,7 +171,11 @@ var Messages$a=Constants.Messages,createCookieString=function(a){return replaceC
171
171
  "".concat(1e7,"-").concat(1e3,"-").concat(4e3,"-").concat(8e3,"-").concat(1e11).replace(/[018]/g,// zeroes, ones, and eights with
172
172
  generateUniqueId// random hex digits
173
173
  )},getRampNumber=function(a){if(!a)return 100;var b=generateHash(a);return Math.abs(b%100)+1},isObject=function(a){var b=Object.prototype.toString.call(a);return "[object Object]"===b||"[object Error]"===b},parseNumber=function(a){if(isNaN(a)||!isFinite(a))return 0;var b=parseFloat(a);return isNaN(b)?0:b},parseStringOrNumber=function(a){return isStringOrNumber(a)?a:null},replaceCommasWithPipes=function(a){return a.replace(/,/g,"|")},replacePipesWithCommas=function(a){return a.replace(/\|/g,",")},replaceApostrophesWithQuotes=function(a){return a.replace(/\'/g,"\"")},replaceQuotesWithApostrophes=function(a){return a.replace(/\"/g,"'")},returnConvertedBoolean=function(a){return "false"!==a&&"0"!==a&&!!a},decoded=function(a){return decodeURIComponent(a.replace(/\+/g," "))},converted=function(a){return 0===a.indexOf("\"")&&(a=a.slice(1,-1).replace(/\\"/g,"\"").replace(/\\\\/g,"\\")),a},isString=function(a){return "string"==typeof a},isNumber=function(a){return "number"==typeof a},isBoolean=function(a){return "boolean"==typeof a},isFunction=function(a){return "function"==typeof a},isValidCustomFlagProperty=function(a){return isNumber(a)||isString(a)||isBoolean(a)},toDataPlanSlug=function(a){// Make sure we are only acting on strings or numbers
174
- return isStringOrNumber(a)?a.toString().toLowerCase().replace(/[^0-9a-zA-Z]+/g,"_"):""},isDataPlanSlug=function(a){return a===toDataPlanSlug(a)},isStringOrNumber=function(a){return isString(a)||isNumber(a)},isEmpty=function(a){return null==a||!(Object.keys(a)||a).length},moveElementToEnd=function(a,b){return a.slice(0,b).concat(a.slice(b+1),a[b])};/**
174
+ return isStringOrNumber(a)?a.toString().toLowerCase().replace(/[^0-9a-zA-Z]+/g,"_"):""},isDataPlanSlug=function(a){return a===toDataPlanSlug(a)},isStringOrNumber=function(a){return isString(a)||isNumber(a)},isEmpty=function(a){return null==a||!(Object.keys(a)||a).length},moveElementToEnd=function(a,b){return a.slice(0,b).concat(a.slice(b+1),a[b])},queryStringParser=function(a,b){void 0===b&&(b=[]);var c,d={};if(!a)return d;if("undefined"!=typeof URL&&"undefined"!=typeof URLSearchParams){var e=new URL(a);c=new URLSearchParams(e.search);}else c=queryStringParserFallback(a);return isEmpty(b)?c.forEach(function(a,b){d[b]=a;}):b.forEach(function(a){var b=c.get(a);b&&(d[a]=b);}),d},queryStringParserFallback=function(a){var b={},c=a.split("?")[1]||"",d=c.split("&");return d.forEach(function(a){var c=a.split("="),d=c[0],e=c[1];d&&e&&(b[d]=decodeURIComponent(e||""));}),{get:function get(a){return b[a]},forEach:function forEach(a){for(var c in b)b.hasOwnProperty(c)&&a(b[c],c);}}},getCookies=function(a){// Helper function to parse cookies from document.cookie
175
+ var b=function parseCookies(){return "undefined"==typeof window?[]:window.document.cookie.split(";").map(function(a){return a.trim()})}();// Helper function to filter cookies by keys
176
+ // Parse cookies from document.cookie
177
+ // Filter cookies by keys if provided
178
+ return function filterCookies(a,b){for(var c={},d=0,e=a;d<e.length;d++){var f=e[d],g=f.split("="),h=g[0],i=g[1];(!b||b.includes(h))&&(c[h]=i);}return c}(b,a)},getHref=function(){return "undefined"!=typeof window&&window.location?window.location.href:""};/**
175
179
  * Returns a value between 1-100 inclusive.
176
180
  */ // FIXME: REFACTOR for V3
177
181
 
@@ -566,7 +570,7 @@ var c=b.Identity.getCurrentUser();return a===(null===c||void 0===c?void 0:c.getM
566
570
  // such as if the SDK is being self-hosted and the flags are different on the server config
567
571
  // https://go.mparticle.com/work/SQDSDKS-6317
568
572
  d.SDKConfig.flags=processFlags(a);var j=processBaseUrls(a,d.SDKConfig.flags,c);for(var k in j)d.SDKConfig[k]=j[k];e?d.SDKConfig.workspaceToken=e:b.Logger.warning("You should have a workspaceToken on your config object for security purposes."),d.storageName=f(e),d.prodStorageName=g(e),d.SDKConfig.requiredWebviewBridgeName=i||e,d.webviewBridgeEnabled=h(d.SDKConfig.requiredWebviewBridgeName,d.SDKConfig.minWebviewBridgeVersion),d.configurationLoaded=!0;};}// https://go.mparticle.com/work/SQDSDKS-6317
569
- function processFlags(a){var b={},c=Constants.FeatureFlags,d=c.ReportBatching,e=c.EventBatchingIntervalMillis,f=c.OfflineStorage,g=c.DirectUrlRouting,h=c.CacheIdentity,i=c.AudienceAPI;return a.flags?(b[d]=a.flags[d]||!1,b[e]=parseNumber(a.flags[e])||Constants.DefaultConfig.uploadInterval,b[f]=a.flags[f]||"0",b[g]="True"===a.flags[g],b[h]="True"===a.flags[h],b[i]="True"===a.flags[i],b):{};// https://go.mparticle.com/work/SQDSDKS-6317
573
+ function processFlags(a){var b={},c=Constants.FeatureFlags,d=c.ReportBatching,e=c.EventBatchingIntervalMillis,f=c.OfflineStorage,g=c.DirectUrlRouting,h=c.CacheIdentity,i=c.AudienceAPI,j=c.CaptureIntegrationSpecificIds;return a.flags?(b[d]=a.flags[d]||!1,b[e]=parseNumber(a.flags[e])||Constants.DefaultConfig.uploadInterval,b[f]=a.flags[f]||"0",b[g]="True"===a.flags[g],b[h]="True"===a.flags[h],b[i]="True"===a.flags[i],b[j]="True"===a.flags[j],b):{};// https://go.mparticle.com/work/SQDSDKS-6317
570
574
  // Passed in config flags take priority over defaults
571
575
  }function processBaseUrls(a,b,c){// an API key is not present in a webview only mode. In this case, no baseUrls are needed
572
576
  if(!c)return {};// Set default baseUrls
@@ -1085,11 +1089,12 @@ this.appendUserInfo=function(b,c){if(c){if(!b)return c.MPID=null,c.ConsentState=
1085
1089
  // tracked. If this is an `optOut` Event, we set `optOut` to the inverse of the SDK's
1086
1090
  // `isEnabled` boolean which is controlled via `MPInstanceManager.setOptOut`.
1087
1091
  // TODO: Why is Webview Bridge Enabled or Opt Out necessary here?
1088
- if(a._Store.sessionId||c.messageType===Types.MessageType.OptOut||a._Store.webviewBridgeEnabled){f=c.hasOwnProperty("toEventAPIObject")?c.toEventAPIObject():{// This is an artifact from v2 events where SessionStart/End and AST event
1092
+ if(a._Store.sessionId||c.messageType===Types.MessageType.OptOut||a._Store.webviewBridgeEnabled){var h=__assign({},c.customFlags);// https://go.mparticle.com/work/SQDSDKS-5053
1093
+ if(a._Helpers.getFeatureFlag&&a._Helpers.getFeatureFlag(Constants.FeatureFlags.CaptureIntegrationSpecificIds)){a._IntegrationCapture.capture();var i=a._IntegrationCapture.getClickIdsAsCustomFlags();h=__assign(__assign({},i),h);}f=c.hasOwnProperty("toEventAPIObject")?c.toEventAPIObject():{// This is an artifact from v2 events where SessionStart/End and AST event
1089
1094
  // names are numbers (1, 2, or 10), but going forward with v3, these lifecycle
1090
1095
  // events do not have names, but are denoted by their `event_type`
1091
- EventName:c.name||c.messageType,EventCategory:c.eventType,EventAttributes:a._Helpers.sanitizeAttributes(c.data,c.name),SourceMessageId:c.sourceMessageId||a._Helpers.generateUniqueId(),EventDataType:c.messageType,CustomFlags:c.customFlags||{},UserAttributeChanges:c.userAttributeChanges,UserIdentityChanges:c.userIdentityChanges},c.messageType!==Types.MessageType.SessionEnd&&(a._Store.dateLastEventSent=new Date),e={// FIXME: Deprecate when we get rid of V2
1092
- Store:a._Store.serverSettings,SDKVersion:Constants.sdkVersion,SessionId:a._Store.sessionId,SessionStartDate:a._Store.sessionStartDate?a._Store.sessionStartDate.getTime():0,Debug:a._Store.SDKConfig.isDevelopmentMode,Location:a._Store.currentPosition,OptOut:g,ExpandedEventCount:0,AppVersion:a.getAppVersion(),AppName:a.getAppName(),Package:a._Store.SDKConfig["package"],ClientGeneratedId:a._Store.clientId,DeviceId:a._Store.deviceId,IntegrationAttributes:a._Store.integrationAttributes,CurrencyCode:a._Store.currencyCode,DataPlan:a._Store.SDKConfig.dataPlan?a._Store.SDKConfig.dataPlan:{}},f.EventDataType===MessageType.AppStateTransition&&(f.IsFirstRun=a._Store.isFirstRun,f.LaunchReferral=window.location.href||null),f.CurrencyCode=a._Store.currencyCode;var h=d||a.Identity.getCurrentUser();return b.appendUserInfo(h,f),c.messageType===Types.MessageType.SessionEnd&&(f.SessionLength=a._Store.dateLastEventSent.getTime()-a._Store.sessionStartDate.getTime(),f.currentSessionMPIDs=a._Store.currentSessionMPIDs,f.EventAttributes=a._Store.sessionAttributes,a._Store.currentSessionMPIDs=[],a._Store.sessionStartDate=null),e.Timestamp=a._Store.dateLastEventSent.getTime(),a._Helpers.extend({},f,e)}return null},this.convertEventToV2DTO=function(c){var d={n:c.EventName,et:c.EventCategory,ua:c.UserAttributes,ui:c.UserIdentities,ia:c.IntegrationAttributes,str:c.Store,attrs:c.EventAttributes,sdk:c.SDKVersion,sid:c.SessionId,sl:c.SessionLength,ssd:c.SessionStartDate,dt:c.EventDataType,dbg:c.Debug,ct:c.Timestamp,lc:c.Location,o:c.OptOut,eec:c.ExpandedEventCount,av:c.AppVersion,cgid:c.ClientGeneratedId,das:c.DeviceId,mpid:c.MPID,smpids:c.currentSessionMPIDs};c.DataPlan&&c.DataPlan.PlanId&&(d.dp_id=c.DataPlan.PlanId,c.DataPlan.PlanVersion&&(d.dp_v=c.DataPlan.PlanVersion));var e=b.convertToConsentStateV2DTO(c.ConsentState);return e&&(d.con=e),c.EventDataType===MessageType.AppStateTransition&&(d.fr=c.IsFirstRun,d.iu=!1,d.at=ApplicationTransitionType.AppInit,d.lr=c.LaunchReferral,d.attrs=null),c.CustomFlags&&convertCustomFlags(c,d),c.EventDataType===MessageType.Commerce?(d.cu=c.CurrencyCode,c.ShoppingCart&&(d.sc={pl:convertProductListToV2DTO(c.ShoppingCart.ProductList)}),c.ProductAction?d.pd={an:c.ProductAction.ProductActionType,cs:a._Helpers.parseNumber(c.ProductAction.CheckoutStep),co:c.ProductAction.CheckoutOptions,pl:convertProductListToV2DTO(c.ProductAction.ProductList),ti:c.ProductAction.TransactionId,ta:c.ProductAction.Affiliation,tcc:c.ProductAction.CouponCode,tr:a._Helpers.parseNumber(c.ProductAction.TotalAmount),ts:a._Helpers.parseNumber(c.ProductAction.ShippingAmount),tt:a._Helpers.parseNumber(c.ProductAction.TaxAmount)}:c.PromotionAction?d.pm={an:c.PromotionAction.PromotionActionType,pl:c.PromotionAction.PromotionList.map(function(a){return {id:a.Id,nm:a.Name,cr:a.Creative,ps:a.Position?a.Position:0}})}:c.ProductImpressions&&(d.pi=c.ProductImpressions.map(function(a){return {pil:a.ProductImpressionList,pl:convertProductListToV2DTO(a.ProductList)}}))):c.EventDataType===MessageType.Profile&&(d.pet=c.ProfileMessageType),d};}
1096
+ EventName:c.name||c.messageType,EventCategory:c.eventType,EventAttributes:a._Helpers.sanitizeAttributes(c.data,c.name),SourceMessageId:c.sourceMessageId||a._Helpers.generateUniqueId(),EventDataType:c.messageType,CustomFlags:h,UserAttributeChanges:c.userAttributeChanges,UserIdentityChanges:c.userIdentityChanges},c.messageType!==Types.MessageType.SessionEnd&&(a._Store.dateLastEventSent=new Date),e={// FIXME: Deprecate when we get rid of V2
1097
+ Store:a._Store.serverSettings,SDKVersion:Constants.sdkVersion,SessionId:a._Store.sessionId,SessionStartDate:a._Store.sessionStartDate?a._Store.sessionStartDate.getTime():0,Debug:a._Store.SDKConfig.isDevelopmentMode,Location:a._Store.currentPosition,OptOut:g,ExpandedEventCount:0,AppVersion:a.getAppVersion(),AppName:a.getAppName(),Package:a._Store.SDKConfig["package"],ClientGeneratedId:a._Store.clientId,DeviceId:a._Store.deviceId,IntegrationAttributes:a._Store.integrationAttributes,CurrencyCode:a._Store.currencyCode,DataPlan:a._Store.SDKConfig.dataPlan?a._Store.SDKConfig.dataPlan:{}},f.EventDataType===MessageType.AppStateTransition&&(f.IsFirstRun=a._Store.isFirstRun,f.LaunchReferral=window.location.href||null),f.CurrencyCode=a._Store.currencyCode;var j=d||a.Identity.getCurrentUser();return b.appendUserInfo(j,f),c.messageType===Types.MessageType.SessionEnd&&(f.SessionLength=a._Store.dateLastEventSent.getTime()-a._Store.sessionStartDate.getTime(),f.currentSessionMPIDs=a._Store.currentSessionMPIDs,f.EventAttributes=a._Store.sessionAttributes,a._Store.currentSessionMPIDs=[],a._Store.sessionStartDate=null),e.Timestamp=a._Store.dateLastEventSent.getTime(),a._Helpers.extend({},f,e)}return null},this.convertEventToV2DTO=function(c){var d={n:c.EventName,et:c.EventCategory,ua:c.UserAttributes,ui:c.UserIdentities,ia:c.IntegrationAttributes,str:c.Store,attrs:c.EventAttributes,sdk:c.SDKVersion,sid:c.SessionId,sl:c.SessionLength,ssd:c.SessionStartDate,dt:c.EventDataType,dbg:c.Debug,ct:c.Timestamp,lc:c.Location,o:c.OptOut,eec:c.ExpandedEventCount,av:c.AppVersion,cgid:c.ClientGeneratedId,das:c.DeviceId,mpid:c.MPID,smpids:c.currentSessionMPIDs};c.DataPlan&&c.DataPlan.PlanId&&(d.dp_id=c.DataPlan.PlanId,c.DataPlan.PlanVersion&&(d.dp_v=c.DataPlan.PlanVersion));var e=b.convertToConsentStateV2DTO(c.ConsentState);return e&&(d.con=e),c.EventDataType===MessageType.AppStateTransition&&(d.fr=c.IsFirstRun,d.iu=!1,d.at=ApplicationTransitionType.AppInit,d.lr=c.LaunchReferral,d.attrs=null),c.CustomFlags&&convertCustomFlags(c,d),c.EventDataType===MessageType.Commerce?(d.cu=c.CurrencyCode,c.ShoppingCart&&(d.sc={pl:convertProductListToV2DTO(c.ShoppingCart.ProductList)}),c.ProductAction?d.pd={an:c.ProductAction.ProductActionType,cs:a._Helpers.parseNumber(c.ProductAction.CheckoutStep),co:c.ProductAction.CheckoutOptions,pl:convertProductListToV2DTO(c.ProductAction.ProductList),ti:c.ProductAction.TransactionId,ta:c.ProductAction.Affiliation,tcc:c.ProductAction.CouponCode,tr:a._Helpers.parseNumber(c.ProductAction.TotalAmount),ts:a._Helpers.parseNumber(c.ProductAction.ShippingAmount),tt:a._Helpers.parseNumber(c.ProductAction.TaxAmount)}:c.PromotionAction?d.pm={an:c.PromotionAction.PromotionActionType,pl:c.PromotionAction.PromotionList.map(function(a){return {id:a.Id,nm:a.Name,cr:a.Creative,ps:a.Position?a.Position:0}})}:c.ProductImpressions&&(d.pi=c.ProductImpressions.map(function(a){return {pil:a.ProductImpressionList,pl:convertProductListToV2DTO(a.ProductList)}}))):c.EventDataType===MessageType.Profile&&(d.pet=c.ProfileMessageType),d};}
1093
1098
 
1094
1099
  function forwardingStatsUploader(a){function b(){var b=a._Forwarders.getForwarderStatsQueue(),c=a._Persistence.forwardingStatsBatches.uploadsTable,d=Date.now();for(var e in b.length&&(c[d]={uploading:!1,data:b},a._Forwarders.setForwarderStatsQueue([])),c)(function(b){if(c.hasOwnProperty(b)&&!1===c[b].uploading){var d=function(){4===e.readyState&&(200===e.status||202===e.status?(a.Logger.verbose("Successfully sent "+e.statusText+" from server"),delete c[b]):"4"===e.status.toString()[0]?429!==e.status&&delete c[b]:c[b].uploading=!1);},e=a._Helpers.createXHR(d),f=c[b].data;c[b].uploading=!0,a._APIClient.sendBatchForwardingStatsToServer(f,e);}})(e);}this.startForwardingStatsTimer=function(){mParticle._forwardingStatsTimer=setInterval(function(){b();},a._Store.SDKConfig.forwarderStatsTimeout);};}
1095
1100
 
@@ -1402,7 +1407,21 @@ var HTTPCodes$2=Constants.HTTPCodes,Messages$2=Constants.Messages;function sendA
1402
1407
  var HTTPCodes$1=Constants.HTTPCodes,Messages$1=Constants.Messages,Modify=Constants.IdentityMethods.Modify;function IdentityAPIClient(a){this.sendAliasRequest=/*#__PURE__*/function(){var b=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function d(b,c){return _regeneratorRuntime.wrap(function(d){for(;;)switch(d.prev=d.next){case 0:return d.next=2,sendAliasRequest(a,b,c);case 2:case"end":return d.stop()}},d)}));return function(){return b.apply(this,arguments)}}(),this.sendIdentityRequest=function(b,c,d,e,f,g,h){var i,j;if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityBegin),!b)return void a.Logger.error(Messages$1.ErrorMessages.APIRequestEmpty);if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityHttp),i=a._Helpers.createXHR(function xhrCallback(){if(4===i.readyState){a.Logger.verbose("Received "+i.statusText+" from server");// https://go.mparticle.com/work/SQDSDKS-6565
1403
1408
  var b=xhrIdentityResponseAdapter(i);f(b,j,d,e,c,h,!1);}}),i)try{a._Store.identityCallInFlight?a._Helpers.invokeCallback(d,HTTPCodes$1.activeIdentityRequest,"There is currently an Identity request processing. Please wait for this to return before requesting again"):(j=g||null,c===Modify?i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+g+"/"+c):i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+c),i.setRequestHeader("Content-Type","application/json"),i.setRequestHeader("x-mp-key",a._Store.devToken),a._Store.identityCallInFlight=!0,i.send(JSON.stringify(b)));}catch(b){a._Store.identityCallInFlight=!1,a._Helpers.invokeCallback(d,HTTPCodes$1.noHttpCoverage,b),a.Logger.error("Error sending identity request to servers with status code "+i.status+" - "+b);}};}
1404
1409
 
1405
- var Messages=Constants.Messages,HTTPCodes=Constants.HTTPCodes,FeatureFlags=Constants.FeatureFlags,ReportBatching=FeatureFlags.ReportBatching,StartingInitialization=Messages.InformationMessages.StartingInitialization;/**
1410
+ // The formatted ClickID value must be of the form version.subdomainIndex.creationTime.<fbclid>, where:
1411
+ // - version is always this prefix: fb
1412
+ // - subdomainIndex is which domain the cookie is defined on ('com' = 0, 'example.com' = 1, 'www.example.com' = 2)
1413
+ // - creationTime is the UNIX time since epoch in milliseconds when the _fbc was stored. If you don't save the _fbc cookie, use the timestamp when you first observed or received this fbclid value
1414
+ // - <fbclid> is the value for the fbclid query parameter in the page URL.
1415
+ // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc
1416
+ var facebookClickIdProcessor=function(a,b,c){if(!a||!b)return "";var d=null===b||void 0===b?void 0:b.split("//");if(!d)return "";var e=d[1].split("/"),f=e[0].split("."),g=1;// The rules for subdomainIndex are for parsing the domain portion
1417
+ // of the URL for cookies, but in this case we are parsing the URL
1418
+ // itself, so we can ignore the use of 0 for 'com'
1419
+ 3<=f.length&&(g=2);// If timestamp is not provided, use the current time
1420
+ var h=c||Date.now();return "fb.".concat(g,".").concat(h,".").concat(a)};var integrationMapping={fbclid:{mappedKey:"Facebook.ClickId",processor:facebookClickIdProcessor},_fbp:{mappedKey:"Facebook.BrowserId"},_fbc:{mappedKey:"Facebook.ClickId"}},IntegrationCapture=/** @class */function(){function a(){this.initialTimestamp=Date.now();}/**
1421
+ * Captures Integration Ids from cookies and query params and stores them in clickIds object
1422
+ */return a.prototype.capture=function(){var a=this.captureQueryParams()||{},b=this.captureCookies()||{};a.fbclid&&b._fbc&&delete b._fbc,this.clickIds=__assign(__assign(__assign({},this.clickIds),a),b);},a.prototype.captureCookies=function(){var a=getCookies(Object.keys(integrationMapping));return this.applyProcessors(a)},a.prototype.captureQueryParams=function(){var a=this.getQueryParams();return this.applyProcessors(a,getHref(),this.initialTimestamp)},a.prototype.getQueryParams=function(){return queryStringParser(getHref(),Object.keys(integrationMapping))},a.prototype.getClickIdsAsCustomFlags=function(){var a,b={};if(!this.clickIds)return b;for(var c=0,d=Object.entries(this.clickIds);c<d.length;c++){var e=d[c],f=e[0],g=e[1],h=null===(a=integrationMapping[f])||void 0===a?void 0:a.mappedKey;isEmpty(h)||(b[h]=g);}return b},a.prototype.applyProcessors=function(a,b,c){for(var d,e={},f=0,g=Object.entries(a);f<g.length;f++){var h=g[f],i=h[0],j=h[1],k=null===(d=integrationMapping[i])||void 0===d?void 0:d.processor;e[i]=k?k(j,b,c):j;}return e},a}();
1423
+
1424
+ var Messages=Constants.Messages,HTTPCodes=Constants.HTTPCodes,FeatureFlags=Constants.FeatureFlags,ReportBatching=FeatureFlags.ReportBatching,CaptureIntegrationSpecificIds=FeatureFlags.CaptureIntegrationSpecificIds,StartingInitialization=Messages.InformationMessages.StartingInitialization;/**
1406
1425
  * <p>All of the following methods can be called on the primary mParticle class. In version 2.10.0, we introduced <a href="https://docs.mparticle.com/developers/sdk/web/multiple-instances/">multiple instances</a>. If you are using multiple instances (self hosted environments only), you should call these methods on each instance.</p>
1407
1426
  * <p>In current versions of mParticle, if your site has one instance, that instance name is 'default_instance'. Any methods called on mParticle on a site with one instance will be mapped to the `default_instance`.</p>
1408
1427
  * <p>This is for simplicity and backwards compatibility. For example, calling mParticle.logPageView() automatically maps to mParticle.getInstance('default_instance').logPageView().</p>
@@ -1576,7 +1595,7 @@ var Messages=Constants.Messages,HTTPCodes=Constants.HTTPCodes,FeatureFlags=Const
1576
1595
  If there is no delay, then the events sent before an integration attribute is included would not
1577
1596
  be forwarded successfully server side.
1578
1597
  */ // Internal use only. Used by our wrapper SDKs to identify themselves during initialization.
1579
- this._instanceName=a,this._NativeSdkHelpers=new NativeSdkHelpers(this),this._SessionManager=new SessionManager(this),this._Persistence=new _Persistence(this),this._Helpers=new Helpers(this),this._Events=new Events(this),this._CookieSyncManager=new cookieSyncManager(this),this._ServerModel=new ServerModel(this),this._Ecommerce=new Ecommerce(this),this._ForwardingStatsUploader=new forwardingStatsUploader(this),this._Consent=new Consent(this),this._IdentityAPIClient=new IdentityAPIClient(this),this._preInit={readyQueue:[],integrationDelays:{},forwarderConstructors:[]},this.IdentityType=Types.IdentityType,this.EventType=Types.EventType,this.CommerceEventType=Types.CommerceEventType,this.PromotionType=Types.PromotionActionType,this.ProductActionType=Types.ProductActionType,this._Identity=new Identity(this),this.Identity=this._Identity.IdentityAPI,this.generateHash=this._Helpers.generateHash,this.getDeviceId=this._Persistence.getDeviceId,"undefined"!=typeof window&&window.mParticle&&window.mParticle.config&&window.mParticle.config.hasOwnProperty("rq")&&(this._preInit.readyQueue=window.mParticle.config.rq),this.init=function(a,b){var c=this;// config code - Fetch config when requestConfig = true, otherwise, proceed with SDKInitialization
1598
+ this._instanceName=a,this._NativeSdkHelpers=new NativeSdkHelpers(this),this._SessionManager=new SessionManager(this),this._Persistence=new _Persistence(this),this._Helpers=new Helpers(this),this._Events=new Events(this),this._CookieSyncManager=new cookieSyncManager(this),this._ServerModel=new ServerModel(this),this._Ecommerce=new Ecommerce(this),this._ForwardingStatsUploader=new forwardingStatsUploader(this),this._Consent=new Consent(this),this._IdentityAPIClient=new IdentityAPIClient(this),this._preInit={readyQueue:[],integrationDelays:{},forwarderConstructors:[]},this._IntegrationCapture=new IntegrationCapture,this.IdentityType=Types.IdentityType,this.EventType=Types.EventType,this.CommerceEventType=Types.CommerceEventType,this.PromotionType=Types.PromotionActionType,this.ProductActionType=Types.ProductActionType,this._Identity=new Identity(this),this.Identity=this._Identity.IdentityAPI,this.generateHash=this._Helpers.generateHash,this.getDeviceId=this._Persistence.getDeviceId,"undefined"!=typeof window&&window.mParticle&&window.mParticle.config&&window.mParticle.config.hasOwnProperty("rq")&&(this._preInit.readyQueue=window.mParticle.config.rq),this.init=function(a,b){var c=this;// config code - Fetch config when requestConfig = true, otherwise, proceed with SDKInitialization
1580
1599
  // Since fetching the configuration is asynchronous, we must pass completeSDKInitialization
1581
1600
  // to it for it to be run after fetched
1582
1601
  if(b||console.warn("You did not pass a config object to init(). mParticle will not initialize properly"),runPreConfigFetchInitialization(this,a,b),!b)return void console.error("No config available on the window, please pass a config object to mParticle.init()");if(!b.hasOwnProperty("requestConfig")||b.requestConfig){var d=new ConfigAPIClient(a,b,this);d.getSDKConfiguration().then(function(d){var e=c._Helpers.extend({},b,d);completeSDKInitialization(a,e,c);});}else completeSDKInitialization(a,b,this);},this.setLogLevel=function(a){b.Logger.setLogLevel(a);},this.reset=function(a){try{a._Persistence.resetPersistence(),a._Store&&delete a._Store;}catch(a){console.error("Cannot reset mParticle",a);}},this._resetForTests=function(a,b,c){c._Store&&delete c._Store,c._Store=new Store(a,c),c._Store.isLocalStorageAvailable=c._Persistence.determineLocalStorageAvailability(window.localStorage),c._Events.stopTracking(),b||c._Persistence.resetPersistence(),c._Persistence.forwardingStatsBatches.uploadsTable={},c._Persistence.forwardingStatsBatches.forwardingStatsEventQueue=[],c._preInit={readyQueue:[],pixelConfigurations:[],integrationDelays:{},forwarderConstructors:[],isDevelopmentMode:!1};},this.ready=function(a){b.isInitialized()&&"function"==typeof a?a():b._preInit.readyQueue.push(a);},this.getEnvironment=function(){return b._Store.SDKConfig.isDevelopmentMode?Types.Environment.Development:Types.Environment.Production},this.getVersion=function(){return Constants.sdkVersion},this.setAppVersion=function(a){var c=queueIfNotInitialized(function(){b.setAppVersion(a);},b);c||(b._Store.SDKConfig.appVersion=a,b._Persistence.update());},this.setDeviceId=function(a){var c=queueIfNotInitialized(function(){b.setDeviceId(a);},b);c||this._Store.setDeviceId(a);},this.isInitialized=function(){return !!b._Store&&b._Store.isInitialized},this.getAppName=function(){return b._Store.SDKConfig.appName},this.setAppName=function(a){var c=queueIfNotInitialized(function(){b.setAppName(a);},b);c||(b._Store.SDKConfig.appName=a);},this.getAppVersion=function(){return b._Store.SDKConfig.appVersion},this.stopTrackingLocation=function(){b._SessionManager.resetSessionTimer(),b._Events.stopTracking();},this.startTrackingLocation=function(a){isFunction(a)||b.Logger.warning("Warning: Location tracking is triggered, but not including a callback into the `startTrackingLocation` may result in events logged too quickly and not being associated with a location."),b._SessionManager.resetSessionTimer(),b._Events.startTracking(a);},this.setPosition=function(a,c){var d=queueIfNotInitialized(function(){b.setPosition(a,c);},b);d||(b._SessionManager.resetSessionTimer(),"number"==typeof a&&"number"==typeof c?b._Store.currentPosition={lat:a,lng:c}:b.Logger.error("Position latitude and/or longitude must both be of type number"));},this.startNewSession=function(){b._SessionManager.startNewSession();},this.endSession=function(){// Sends true as an over ride vs when endSession is called from the setInterval
@@ -1737,7 +1756,7 @@ function completeSDKInitialization(a,b,c){var d=createKitBlocker(b,c);// Web Vie
1737
1756
  // responsible for sending events directly to mParticle's servers. The Web SDK will not initialize
1738
1757
  // persistence or Identity directly.
1739
1758
  if(c._APIClient=new APIClient(c,d),c._Forwarders=new Forwarders(c,d),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
1740
- var e=c.Identity.getCurrentUser(),f=e?e.getMPID():null,g=e?e.getUserIdentities().userIdentities:{};c._Store.SDKConfig.identifyRequest=c._Store.hasInvalidIdentifyRequest()?{userIdentities:g}:c._Store.SDKConfig.identifyRequest,c._Helpers.getFeatureFlag(ReportBatching)&&c._ForwardingStatsUploader.startForwardingStatsTimer(),c._Forwarders.processForwarders(b,c._APIClient.prepareForwardingStats),c._Forwarders.processPixelConfigs(b),c._SessionManager.initialize(),c._Events.logAST(),processIdentityCallback(c,e,f,g);}c._Store.isInitialized=!0;// Call any functions that are waiting for the library to be initialized
1759
+ var e=c.Identity.getCurrentUser(),f=e?e.getMPID():null,g=e?e.getUserIdentities().userIdentities:{};c._Store.SDKConfig.identifyRequest=c._Store.hasInvalidIdentifyRequest()?{userIdentities:g}:c._Store.SDKConfig.identifyRequest,c._Helpers.getFeatureFlag(ReportBatching)&&c._ForwardingStatsUploader.startForwardingStatsTimer(),c._Helpers.getFeatureFlag(CaptureIntegrationSpecificIds)&&c._IntegrationCapture.capture(),c._Forwarders.processForwarders(b,c._APIClient.prepareForwardingStats),c._Forwarders.processPixelConfigs(b),c._SessionManager.initialize(),c._Events.logAST(),processIdentityCallback(c,e,f,g);}c._Store.isInitialized=!0;// Call any functions that are waiting for the library to be initialized
1741
1760
  try{c._preInit.readyQueue=processReadyQueue(c._preInit.readyQueue);}catch(a){c.Logger.error(a);}// https://go.mparticle.com/work/SQDSDKS-6040
1742
1761
  c._Store.isFirstRun&&(c._Store.isFirstRun=!1);}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:
1743
1762
  1. Manually via config.dataPlanOptions (this takes priority)
package/dist/mparticle.js CHANGED
@@ -393,7 +393,7 @@ var mParticle = (function () {
393
393
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
394
394
  };
395
395
 
396
- var version = "2.28.3";
396
+ var version = "2.29.0";
397
397
 
398
398
  var Constants = {
399
399
  sdkVersion: version,
@@ -552,7 +552,8 @@ var mParticle = (function () {
552
552
  OfflineStorage: 'offlineStorage',
553
553
  DirectUrlRouting: 'directURLRouting',
554
554
  CacheIdentity: 'cacheIdentity',
555
- AudienceAPI: 'audienceAPI'
555
+ AudienceAPI: 'audienceAPI',
556
+ CaptureIntegrationSpecificIds: 'captureIntegrationSpecificIds'
556
557
  },
557
558
  DefaultInstance: 'default_instance',
558
559
  CCPAPurpose: 'data_sale_opt_out',
@@ -755,6 +756,91 @@ var mParticle = (function () {
755
756
  var moveElementToEnd = function moveElementToEnd(array, index) {
756
757
  return array.slice(0, index).concat(array.slice(index + 1), array[index]);
757
758
  };
759
+ var queryStringParser = function queryStringParser(url, keys) {
760
+ if (keys === void 0) {
761
+ keys = [];
762
+ }
763
+ var urlParams;
764
+ var results = {};
765
+ if (!url) return results;
766
+ if (typeof URL !== 'undefined' && typeof URLSearchParams !== 'undefined') {
767
+ var urlObject = new URL(url);
768
+ urlParams = new URLSearchParams(urlObject.search);
769
+ } else {
770
+ urlParams = queryStringParserFallback(url);
771
+ }
772
+ if (isEmpty(keys)) {
773
+ urlParams.forEach(function (value, key) {
774
+ results[key] = value;
775
+ });
776
+ } else {
777
+ keys.forEach(function (key) {
778
+ var value = urlParams.get(key);
779
+ if (value) {
780
+ results[key] = value;
781
+ }
782
+ });
783
+ }
784
+ return results;
785
+ };
786
+ var queryStringParserFallback = function queryStringParserFallback(url) {
787
+ var params = {};
788
+ var queryString = url.split('?')[1] || '';
789
+ var pairs = queryString.split('&');
790
+ pairs.forEach(function (pair) {
791
+ var _a = pair.split('='),
792
+ key = _a[0],
793
+ value = _a[1];
794
+ if (key && value) {
795
+ params[key] = decodeURIComponent(value || '');
796
+ }
797
+ });
798
+ return {
799
+ get: function get(key) {
800
+ return params[key];
801
+ },
802
+ forEach: function forEach(callback) {
803
+ for (var key in params) {
804
+ if (params.hasOwnProperty(key)) {
805
+ callback(params[key], key);
806
+ }
807
+ }
808
+ }
809
+ };
810
+ };
811
+ // Get cookies as a dictionary
812
+ var getCookies = function getCookies(keys) {
813
+ // Helper function to parse cookies from document.cookie
814
+ var parseCookies = function parseCookies() {
815
+ if (typeof window === 'undefined') {
816
+ return [];
817
+ }
818
+ return window.document.cookie.split(';').map(function (cookie) {
819
+ return cookie.trim();
820
+ });
821
+ };
822
+ // Helper function to filter cookies by keys
823
+ var filterCookies = function filterCookies(cookies, keys) {
824
+ var results = {};
825
+ for (var _i = 0, cookies_1 = cookies; _i < cookies_1.length; _i++) {
826
+ var cookie = cookies_1[_i];
827
+ var _a = cookie.split('='),
828
+ key = _a[0],
829
+ value = _a[1];
830
+ if (!keys || keys.includes(key)) {
831
+ results[key] = value;
832
+ }
833
+ }
834
+ return results;
835
+ };
836
+ // Parse cookies from document.cookie
837
+ var parsedCookies = parseCookies();
838
+ // Filter cookies by keys if provided
839
+ return filterCookies(parsedCookies, keys);
840
+ };
841
+ var getHref = function getHref() {
842
+ return typeof window !== 'undefined' && window.location ? window.location.href : '';
843
+ };
758
844
 
759
845
  function getNewIdentitiesByName(newIdentitiesByType) {
760
846
  var newIdentitiesByName = {};
@@ -4217,7 +4303,8 @@ var mParticle = (function () {
4217
4303
  OfflineStorage = _a.OfflineStorage,
4218
4304
  DirectUrlRouting = _a.DirectUrlRouting,
4219
4305
  CacheIdentity = _a.CacheIdentity,
4220
- AudienceAPI = _a.AudienceAPI;
4306
+ AudienceAPI = _a.AudienceAPI,
4307
+ CaptureIntegrationSpecificIds = _a.CaptureIntegrationSpecificIds;
4221
4308
  if (!config.flags) {
4222
4309
  return {};
4223
4310
  }
@@ -4230,6 +4317,7 @@ var mParticle = (function () {
4230
4317
  flags[DirectUrlRouting] = config.flags[DirectUrlRouting] === 'True';
4231
4318
  flags[CacheIdentity] = config.flags[CacheIdentity] === 'True';
4232
4319
  flags[AudienceAPI] = config.flags[AudienceAPI] === 'True';
4320
+ flags[CaptureIntegrationSpecificIds] = config.flags[CaptureIntegrationSpecificIds] === 'True';
4233
4321
  return flags;
4234
4322
  }
4235
4323
  function processBaseUrls(config, flags, apiKey) {
@@ -6510,6 +6598,15 @@ var mParticle = (function () {
6510
6598
  var optOut = event.messageType === Types.MessageType.OptOut ? !mpInstance._Store.isEnabled : null;
6511
6599
  // TODO: Why is Webview Bridge Enabled or Opt Out necessary here?
6512
6600
  if (mpInstance._Store.sessionId || event.messageType === Types.MessageType.OptOut || mpInstance._Store.webviewBridgeEnabled) {
6601
+ var customFlags = __assign({}, event.customFlags);
6602
+ // https://go.mparticle.com/work/SQDSDKS-5053
6603
+ if (mpInstance._Helpers.getFeatureFlag && mpInstance._Helpers.getFeatureFlag(Constants.FeatureFlags.CaptureIntegrationSpecificIds)) {
6604
+ // Attempt to recapture click IDs in case a third party integration
6605
+ // has added or updated new click IDs since the last event was sent.
6606
+ mpInstance._IntegrationCapture.capture();
6607
+ var transformedClickIDs = mpInstance._IntegrationCapture.getClickIdsAsCustomFlags();
6608
+ customFlags = __assign(__assign({}, transformedClickIDs), customFlags);
6609
+ }
6513
6610
  if (event.hasOwnProperty('toEventAPIObject')) {
6514
6611
  eventObject = event.toEventAPIObject();
6515
6612
  } else {
@@ -6522,7 +6619,7 @@ var mParticle = (function () {
6522
6619
  EventAttributes: mpInstance._Helpers.sanitizeAttributes(event.data, event.name),
6523
6620
  SourceMessageId: event.sourceMessageId || mpInstance._Helpers.generateUniqueId(),
6524
6621
  EventDataType: event.messageType,
6525
- CustomFlags: event.customFlags || {},
6622
+ CustomFlags: customFlags,
6526
6623
  UserAttributeChanges: event.userAttributeChanges,
6527
6624
  UserIdentityChanges: event.userIdentityChanges
6528
6625
  };
@@ -9034,10 +9131,129 @@ var mParticle = (function () {
9034
9131
  };
9035
9132
  }
9036
9133
 
9134
+ // Facebook Click ID has specific formatting rules
9135
+ // The formatted ClickID value must be of the form version.subdomainIndex.creationTime.<fbclid>, where:
9136
+ // - version is always this prefix: fb
9137
+ // - subdomainIndex is which domain the cookie is defined on ('com' = 0, 'example.com' = 1, 'www.example.com' = 2)
9138
+ // - creationTime is the UNIX time since epoch in milliseconds when the _fbc was stored. If you don't save the _fbc cookie, use the timestamp when you first observed or received this fbclid value
9139
+ // - <fbclid> is the value for the fbclid query parameter in the page URL.
9140
+ // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc
9141
+ var facebookClickIdProcessor = function facebookClickIdProcessor(clickId, url, timestamp) {
9142
+ if (!clickId || !url) {
9143
+ return '';
9144
+ }
9145
+ var urlSegments = url === null || url === void 0 ? void 0 : url.split('//');
9146
+ if (!urlSegments) {
9147
+ return '';
9148
+ }
9149
+ var urlParts = urlSegments[1].split('/');
9150
+ var domainParts = urlParts[0].split('.');
9151
+ var subdomainIndex = 1;
9152
+ // The rules for subdomainIndex are for parsing the domain portion
9153
+ // of the URL for cookies, but in this case we are parsing the URL
9154
+ // itself, so we can ignore the use of 0 for 'com'
9155
+ if (domainParts.length >= 3) {
9156
+ subdomainIndex = 2;
9157
+ }
9158
+ // If timestamp is not provided, use the current time
9159
+ var _timestamp = timestamp || Date.now();
9160
+ return "fb.".concat(subdomainIndex, ".").concat(_timestamp, ".").concat(clickId);
9161
+ };
9162
+ var integrationMapping = {
9163
+ fbclid: {
9164
+ mappedKey: 'Facebook.ClickId',
9165
+ processor: facebookClickIdProcessor
9166
+ },
9167
+ _fbp: {
9168
+ mappedKey: 'Facebook.BrowserId'
9169
+ },
9170
+ _fbc: {
9171
+ mappedKey: 'Facebook.ClickId'
9172
+ }
9173
+ };
9174
+ var IntegrationCapture = /** @class */function () {
9175
+ function IntegrationCapture() {
9176
+ this.initialTimestamp = Date.now();
9177
+ }
9178
+ /**
9179
+ * Captures Integration Ids from cookies and query params and stores them in clickIds object
9180
+ */
9181
+ IntegrationCapture.prototype.capture = function () {
9182
+ var queryParams = this.captureQueryParams() || {};
9183
+ var cookies = this.captureCookies() || {};
9184
+ // Exclude _fbc if fbclid is present
9185
+ // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc#retrieve-from-fbclid-url-query-parameter
9186
+ if (queryParams['fbclid'] && cookies['_fbc']) {
9187
+ delete cookies['_fbc'];
9188
+ }
9189
+ this.clickIds = __assign(__assign(__assign({}, this.clickIds), queryParams), cookies);
9190
+ };
9191
+ /**
9192
+ * Captures cookies based on the integration ID mapping.
9193
+ */
9194
+ IntegrationCapture.prototype.captureCookies = function () {
9195
+ var cookies = getCookies(Object.keys(integrationMapping));
9196
+ return this.applyProcessors(cookies);
9197
+ };
9198
+ /**
9199
+ * Captures query parameters based on the integration ID mapping.
9200
+ */
9201
+ IntegrationCapture.prototype.captureQueryParams = function () {
9202
+ var queryParams = this.getQueryParams();
9203
+ return this.applyProcessors(queryParams, getHref(), this.initialTimestamp);
9204
+ };
9205
+ /**
9206
+ * Gets the query parameters based on the integration ID mapping.
9207
+ * @returns {Dictionary<string>} The query parameters.
9208
+ */
9209
+ IntegrationCapture.prototype.getQueryParams = function () {
9210
+ return queryStringParser(getHref(), Object.keys(integrationMapping));
9211
+ };
9212
+ /**
9213
+ * Converts captured click IDs to custom flags for SDK events.
9214
+ * @returns {SDKEventCustomFlags} The custom flags.
9215
+ */
9216
+ IntegrationCapture.prototype.getClickIdsAsCustomFlags = function () {
9217
+ var _a;
9218
+ var customFlags = {};
9219
+ if (!this.clickIds) {
9220
+ return customFlags;
9221
+ }
9222
+ for (var _i = 0, _b = Object.entries(this.clickIds); _i < _b.length; _i++) {
9223
+ var _c = _b[_i],
9224
+ key = _c[0],
9225
+ value = _c[1];
9226
+ var mappedKey = (_a = integrationMapping[key]) === null || _a === void 0 ? void 0 : _a.mappedKey;
9227
+ if (!isEmpty(mappedKey)) {
9228
+ customFlags[mappedKey] = value;
9229
+ }
9230
+ }
9231
+ return customFlags;
9232
+ };
9233
+ IntegrationCapture.prototype.applyProcessors = function (clickIds, url, timestamp) {
9234
+ var _a;
9235
+ var processedClickIds = {};
9236
+ for (var _i = 0, _b = Object.entries(clickIds); _i < _b.length; _i++) {
9237
+ var _c = _b[_i],
9238
+ key = _c[0],
9239
+ value = _c[1];
9240
+ var processor = (_a = integrationMapping[key]) === null || _a === void 0 ? void 0 : _a.processor;
9241
+ if (processor) {
9242
+ processedClickIds[key] = processor(value, url, timestamp);
9243
+ } else {
9244
+ processedClickIds[key] = value;
9245
+ }
9246
+ }
9247
+ return processedClickIds;
9248
+ };
9249
+ return IntegrationCapture;
9250
+ }();
9251
+
9037
9252
  var Messages = Constants.Messages,
9038
9253
  HTTPCodes = Constants.HTTPCodes,
9039
9254
  FeatureFlags = Constants.FeatureFlags;
9040
- var ReportBatching = FeatureFlags.ReportBatching;
9255
+ var ReportBatching = FeatureFlags.ReportBatching,
9256
+ CaptureIntegrationSpecificIds = FeatureFlags.CaptureIntegrationSpecificIds;
9041
9257
  var StartingInitialization = Messages.InformationMessages.StartingInitialization;
9042
9258
 
9043
9259
  /**
@@ -9073,6 +9289,7 @@ var mParticle = (function () {
9073
9289
  integrationDelays: {},
9074
9290
  forwarderConstructors: []
9075
9291
  };
9292
+ this._IntegrationCapture = new IntegrationCapture();
9076
9293
 
9077
9294
  // required for forwarders once they reference the mparticle instance
9078
9295
  this.IdentityType = Types.IdentityType;
@@ -10013,6 +10230,9 @@ var mParticle = (function () {
10013
10230
  if (mpInstance._Helpers.getFeatureFlag(ReportBatching)) {
10014
10231
  mpInstance._ForwardingStatsUploader.startForwardingStatsTimer();
10015
10232
  }
10233
+ if (mpInstance._Helpers.getFeatureFlag(CaptureIntegrationSpecificIds)) {
10234
+ mpInstance._IntegrationCapture.capture();
10235
+ }
10016
10236
  mpInstance._Forwarders.processForwarders(config, mpInstance._APIClient.prepareForwardingStats);
10017
10237
  mpInstance._Forwarders.processPixelConfigs(config);
10018
10238
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mparticle/web-sdk",
3
- "version": "2.28.3",
3
+ "version": "2.29.0",
4
4
  "description": "mParticle core SDK for web applications",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
package/src/constants.ts CHANGED
@@ -174,6 +174,7 @@ const Constants = {
174
174
  DirectUrlRouting: 'directURLRouting',
175
175
  CacheIdentity: 'cacheIdentity',
176
176
  AudienceAPI: 'audienceAPI',
177
+ CaptureIntegrationSpecificIds: 'captureIntegrationSpecificIds',
177
178
  },
178
179
  DefaultInstance: 'default_instance',
179
180
  CCPAPurpose: 'data_sale_opt_out',
@@ -55,7 +55,7 @@ export interface IIdentityAPIRequestData {
55
55
  context: string | null;
56
56
  environment: Environment;
57
57
  request_id: string;
58
- reqest_timestamp_unixtime_ms: number;
58
+ request_timestamp_unixtime_ms: number;
59
59
  previous_mpid: MPID | null;
60
60
  known_identities: IKnownIdentities;
61
61
  }
@@ -0,0 +1,153 @@
1
+ import { SDKEventCustomFlags } from './sdkRuntimeModels';
2
+ import {
3
+ Dictionary,
4
+ queryStringParser,
5
+ getCookies,
6
+ getHref,
7
+ isEmpty,
8
+ } from './utils';
9
+
10
+ export interface IntegrationCaptureProcessorFunction {
11
+ (clickId: string, url: string, timestamp?: number): string;
12
+ }
13
+
14
+ // Facebook Click ID has specific formatting rules
15
+ // The formatted ClickID value must be of the form version.subdomainIndex.creationTime.<fbclid>, where:
16
+ // - version is always this prefix: fb
17
+ // - subdomainIndex is which domain the cookie is defined on ('com' = 0, 'example.com' = 1, 'www.example.com' = 2)
18
+ // - creationTime is the UNIX time since epoch in milliseconds when the _fbc was stored. If you don't save the _fbc cookie, use the timestamp when you first observed or received this fbclid value
19
+ // - <fbclid> is the value for the fbclid query parameter in the page URL.
20
+ // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc
21
+ export const facebookClickIdProcessor: IntegrationCaptureProcessorFunction = (
22
+ clickId: string,
23
+ url: string,
24
+ timestamp?: number,
25
+ ): string => {
26
+ if (!clickId || !url) {
27
+ return '';
28
+ }
29
+
30
+ const urlSegments = url?.split('//')
31
+ if (!urlSegments) {
32
+ return '';
33
+ }
34
+
35
+ const urlParts = urlSegments[1].split('/');
36
+ const domainParts = urlParts[0].split('.');
37
+ let subdomainIndex: number = 1;
38
+
39
+ // The rules for subdomainIndex are for parsing the domain portion
40
+ // of the URL for cookies, but in this case we are parsing the URL
41
+ // itself, so we can ignore the use of 0 for 'com'
42
+ if (domainParts.length >= 3) {
43
+ subdomainIndex = 2;
44
+ }
45
+
46
+ // If timestamp is not provided, use the current time
47
+ const _timestamp = timestamp || Date.now();
48
+
49
+ return `fb.${subdomainIndex}.${_timestamp}.${clickId}`;
50
+ };
51
+ interface IntegrationIdMapping {
52
+ [key: string]: {
53
+ mappedKey: string;
54
+ processor?: IntegrationCaptureProcessorFunction;
55
+ };
56
+ }
57
+
58
+ const integrationMapping: IntegrationIdMapping = {
59
+ fbclid: {
60
+ mappedKey: 'Facebook.ClickId',
61
+ processor: facebookClickIdProcessor,
62
+ },
63
+ _fbp: {
64
+ mappedKey: 'Facebook.BrowserId',
65
+ },
66
+ _fbc: {
67
+ mappedKey: 'Facebook.ClickId',
68
+ },
69
+ };
70
+
71
+ export default class IntegrationCapture {
72
+ public clickIds: Dictionary<string>;
73
+ public readonly initialTimestamp: number;
74
+
75
+ constructor() {
76
+ this.initialTimestamp = Date.now();
77
+ }
78
+
79
+ /**
80
+ * Captures Integration Ids from cookies and query params and stores them in clickIds object
81
+ */
82
+ public capture(): void {
83
+ const queryParams = this.captureQueryParams() || {};
84
+ const cookies = this.captureCookies() || {};
85
+
86
+ // Exclude _fbc if fbclid is present
87
+ // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc#retrieve-from-fbclid-url-query-parameter
88
+ if (queryParams['fbclid'] && cookies['_fbc']) {
89
+ delete cookies['_fbc'];
90
+ }
91
+
92
+ this.clickIds = { ...this.clickIds, ...queryParams, ...cookies };
93
+ }
94
+
95
+ /**
96
+ * Captures cookies based on the integration ID mapping.
97
+ */
98
+ public captureCookies(): Dictionary<string> {
99
+ const cookies = getCookies(Object.keys(integrationMapping));
100
+ return this.applyProcessors(cookies);
101
+ }
102
+
103
+ /**
104
+ * Captures query parameters based on the integration ID mapping.
105
+ */
106
+ public captureQueryParams(): Dictionary<string> {
107
+ const queryParams = this.getQueryParams();
108
+ return this.applyProcessors(queryParams, getHref(), this.initialTimestamp);
109
+ }
110
+
111
+ /**
112
+ * Gets the query parameters based on the integration ID mapping.
113
+ * @returns {Dictionary<string>} The query parameters.
114
+ */
115
+ public getQueryParams(): Dictionary<string> {
116
+ return queryStringParser(getHref(), Object.keys(integrationMapping));
117
+ }
118
+
119
+ /**
120
+ * Converts captured click IDs to custom flags for SDK events.
121
+ * @returns {SDKEventCustomFlags} The custom flags.
122
+ */
123
+ public getClickIdsAsCustomFlags(): SDKEventCustomFlags {
124
+ const customFlags: SDKEventCustomFlags = {};
125
+
126
+ if (!this.clickIds) {
127
+ return customFlags;
128
+ }
129
+
130
+ for (const [key, value] of Object.entries(this.clickIds)) {
131
+ const mappedKey = integrationMapping[key]?.mappedKey;
132
+ if (!isEmpty(mappedKey)) {
133
+ customFlags[mappedKey] = value;
134
+ }
135
+ }
136
+ return customFlags;
137
+ }
138
+
139
+ private applyProcessors(clickIds: Dictionary<string>, url?: string, timestamp?: number): Dictionary<string> {
140
+ const processedClickIds: Dictionary<string> = {};
141
+
142
+ for (const [key, value] of Object.entries(clickIds)) {
143
+ const processor = integrationMapping[key]?.processor;
144
+ if (processor) {
145
+ processedClickIds[key] = processor(value, url, timestamp);
146
+ } else {
147
+ processedClickIds[key] = value;
148
+ }
149
+ }
150
+
151
+ return processedClickIds;
152
+ }
153
+ }
@@ -39,9 +39,10 @@ import IdentityAPIClient from './identityApiClient';
39
39
  import { isEmpty, isFunction } from './utils';
40
40
  import { LocalStorageVault } from './vault';
41
41
  import { removeExpiredIdentityCacheDates } from './identity-utils';
42
+ import IntegrationCapture from './integrationCapture';
42
43
 
43
44
  const { Messages, HTTPCodes, FeatureFlags } = Constants;
44
- const { ReportBatching } = FeatureFlags;
45
+ const { ReportBatching, CaptureIntegrationSpecificIds } = FeatureFlags;
45
46
  const { StartingInitialization } = Messages.InformationMessages;
46
47
 
47
48
  /**
@@ -77,6 +78,7 @@ export default function mParticleInstance(instanceName) {
77
78
  integrationDelays: {},
78
79
  forwarderConstructors: [],
79
80
  };
81
+ this._IntegrationCapture = new IntegrationCapture();
80
82
 
81
83
  // required for forwarders once they reference the mparticle instance
82
84
  this.IdentityType = Types.IdentityType;
@@ -1336,6 +1338,10 @@ function completeSDKInitialization(apiKey, config, mpInstance) {
1336
1338
  mpInstance._ForwardingStatsUploader.startForwardingStatsTimer();
1337
1339
  }
1338
1340
 
1341
+ if (mpInstance._Helpers.getFeatureFlag(CaptureIntegrationSpecificIds)) {
1342
+ mpInstance._IntegrationCapture.capture();
1343
+ }
1344
+
1339
1345
  mpInstance._Forwarders.processForwarders(
1340
1346
  config,
1341
1347
  mpInstance._APIClient.prepareForwardingStats
@@ -30,6 +30,7 @@ import {
30
30
  ISDKUserAttributes,
31
31
  } from './identity-user-interfaces';
32
32
  import { IIdentityType } from './types.interfaces';
33
+ import IntegrationCapture from './integrationCapture';
33
34
 
34
35
  // TODO: Resolve this with version in @mparticle/web-sdk
35
36
  export type SDKEventCustomFlags = Dictionary<any>;
@@ -150,6 +151,7 @@ interface IEvents {
150
151
 
151
152
  export interface MParticleWebSDK {
152
153
  addForwarder(mockForwarder: MPForwarder): void;
154
+ _IntegrationCapture: IntegrationCapture;
153
155
  IdentityType: IIdentityType;
154
156
  _Identity: IIdentity;
155
157
  Identity: SDKIdentityApi;
@@ -8,6 +8,7 @@ import {
8
8
  BaseEvent,
9
9
  MParticleWebSDK,
10
10
  SDKEvent,
11
+ SDKEventCustomFlags,
11
12
  SDKGeoLocation,
12
13
  SDKProduct,
13
14
  } from './sdkRuntimeModels';
@@ -317,6 +318,18 @@ export default function ServerModel(
317
318
  event.messageType === Types.MessageType.OptOut ||
318
319
  mpInstance._Store.webviewBridgeEnabled
319
320
  ) {
321
+ let customFlags: SDKEventCustomFlags = {...event.customFlags};
322
+
323
+ // https://go.mparticle.com/work/SQDSDKS-5053
324
+ if (mpInstance._Helpers.getFeatureFlag && mpInstance._Helpers.getFeatureFlag(Constants.FeatureFlags.CaptureIntegrationSpecificIds)) {
325
+
326
+ // Attempt to recapture click IDs in case a third party integration
327
+ // has added or updated new click IDs since the last event was sent.
328
+ mpInstance._IntegrationCapture.capture();
329
+ const transformedClickIDs = mpInstance._IntegrationCapture.getClickIdsAsCustomFlags();
330
+ customFlags = {...transformedClickIDs, ...customFlags};
331
+ }
332
+
320
333
  if (event.hasOwnProperty('toEventAPIObject')) {
321
334
  eventObject = event.toEventAPIObject();
322
335
  } else {
@@ -336,7 +349,7 @@ export default function ServerModel(
336
349
  event.sourceMessageId ||
337
350
  mpInstance._Helpers.generateUniqueId(),
338
351
  EventDataType: event.messageType,
339
- CustomFlags: event.customFlags || {},
352
+ CustomFlags: customFlags,
340
353
  UserAttributeChanges: event.userAttributeChanges,
341
354
  UserIdentityChanges: event.userIdentityChanges,
342
355
  };
package/src/store.ts CHANGED
@@ -710,6 +710,7 @@ export function processFlags(config: SDKInitConfig): IFeatureFlags {
710
710
  DirectUrlRouting,
711
711
  CacheIdentity,
712
712
  AudienceAPI,
713
+ CaptureIntegrationSpecificIds,
713
714
  } = Constants.FeatureFlags;
714
715
 
715
716
  if (!config.flags) {
@@ -727,6 +728,7 @@ export function processFlags(config: SDKInitConfig): IFeatureFlags {
727
728
  flags[DirectUrlRouting] = config.flags[DirectUrlRouting] === 'True';
728
729
  flags[CacheIdentity] = config.flags[CacheIdentity] === 'True';
729
730
  flags[AudienceAPI] = config.flags[AudienceAPI] === 'True';
731
+ flags[CaptureIntegrationSpecificIds] = config.flags[CaptureIntegrationSpecificIds] === 'True';
730
732
 
731
733
  return flags;
732
734
  }
package/src/utils.ts CHANGED
@@ -222,7 +222,7 @@ const isDataPlanSlug = (str: string): boolean => str === toDataPlanSlug(str);
222
222
  const isStringOrNumber = (value: any): boolean =>
223
223
  isString(value) || isNumber(value);
224
224
 
225
- const isEmpty = (value: Dictionary<any> | null | undefined): boolean =>
225
+ const isEmpty = (value: Dictionary<any> | string | null | undefined): boolean =>
226
226
  value == null || !(Object.keys(value) || value).length;
227
227
 
228
228
  const mergeObjects = <T extends object>(...objects: T[]): T => {
@@ -232,6 +232,107 @@ const mergeObjects = <T extends object>(...objects: T[]): T => {
232
232
  const moveElementToEnd = <T>(array: T[], index: number): T[] =>
233
233
  array.slice(0, index).concat(array.slice(index + 1), array[index]);
234
234
 
235
+ const queryStringParser = (
236
+ url: string,
237
+ keys: string[] = []
238
+ ): Dictionary<string> => {
239
+ let urlParams: URLSearchParams | URLSearchParamsFallback;
240
+ let results: Dictionary<string> = {};
241
+
242
+ if (!url) return results;
243
+
244
+ if (typeof URL !== 'undefined' && typeof URLSearchParams !== 'undefined') {
245
+ const urlObject = new URL(url);
246
+ urlParams = new URLSearchParams(urlObject.search);
247
+ } else {
248
+ urlParams = queryStringParserFallback(url);
249
+ }
250
+
251
+ if (isEmpty(keys)) {
252
+ urlParams.forEach((value, key) => {
253
+ results[key] = value;
254
+ });
255
+ } else {
256
+ keys.forEach(key => {
257
+ const value = urlParams.get(key);
258
+ if (value) {
259
+ results[key] = value;
260
+ }
261
+ });
262
+ }
263
+
264
+ return results;
265
+ };
266
+
267
+ interface URLSearchParamsFallback {
268
+ get: (key: string) => string | null;
269
+ forEach: (callback: (value: string, key: string) => void) => void;
270
+ }
271
+
272
+ const queryStringParserFallback = (url: string): URLSearchParamsFallback => {
273
+ let params: Dictionary<string> = {};
274
+ const queryString = url.split('?')[1] || '';
275
+ const pairs = queryString.split('&');
276
+
277
+ pairs.forEach(pair => {
278
+ var [key, value] = pair.split('=');
279
+ if (key && value) {
280
+ params[key] = decodeURIComponent(value || '');
281
+ }
282
+ });
283
+
284
+ return {
285
+ get: function(key: string) {
286
+ return params[key];
287
+ },
288
+ forEach: function(callback: (value: string, key: string) => void) {
289
+ for (var key in params) {
290
+ if (params.hasOwnProperty(key)) {
291
+ callback(params[key], key);
292
+ }
293
+ }
294
+ },
295
+ };
296
+ };
297
+
298
+ // Get cookies as a dictionary
299
+ const getCookies = (keys?: string[]): Dictionary<string> => {
300
+ // Helper function to parse cookies from document.cookie
301
+ const parseCookies = (): string[] => {
302
+ if (typeof window === 'undefined') {
303
+ return [];
304
+ }
305
+ return window.document.cookie.split(';').map(cookie => cookie.trim());
306
+ };
307
+
308
+ // Helper function to filter cookies by keys
309
+ const filterCookies = (
310
+ cookies: string[],
311
+ keys?: string[]
312
+ ): Dictionary<string> => {
313
+ const results: Dictionary<string> = {};
314
+ for (const cookie of cookies) {
315
+ const [key, value] = cookie.split('=');
316
+ if (!keys || keys.includes(key)) {
317
+ results[key] = value;
318
+ }
319
+ }
320
+ return results;
321
+ };
322
+
323
+ // Parse cookies from document.cookie
324
+ const parsedCookies: string[] = parseCookies();
325
+
326
+ // Filter cookies by keys if provided
327
+ return filterCookies(parsedCookies, keys);
328
+ };
329
+
330
+ const getHref = (): string => {
331
+ return typeof window !== 'undefined' && window.location
332
+ ? window.location.href
333
+ : '';
334
+ };
335
+
235
336
  export {
236
337
  createCookieString,
237
338
  revertCookieString,
@@ -262,4 +363,7 @@ export {
262
363
  isValidCustomFlagProperty,
263
364
  mergeObjects,
264
365
  moveElementToEnd,
366
+ queryStringParser,
367
+ getCookies,
368
+ getHref,
265
369
  };