@mparticle/web-sdk 2.77.0 → 2.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mparticle.common.js +16 -8
- package/dist/mparticle.esm.js +16 -8
- package/dist/mparticle.js +31 -5
- package/dist/types/src/utils.d.ts +3 -2
- package/package.json +1 -1
- package/src/cookieSyncManager.ts +13 -2
- package/src/utils.ts +25 -5
package/dist/mparticle.common.js
CHANGED
|
@@ -15,7 +15,7 @@ map:function map(a,b){var c,d,e;if(null===this)throw new TypeError(" this is nul
|
|
|
15
15
|
filter:function filter(a/*, thisArg*/){if(void 0===this||null===this)throw new TypeError;var b=Object(this),c=b.length>>>0;if("function"!=typeof a)throw new TypeError;for(var d=[],e=2<=arguments.length?arguments[1]:void 0,f=0;f<c;f++)if(f in b){var g=b[f];a.call(e,g,f,b)&&d.push(g);}return d},// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
|
|
16
16
|
isArray:function isArray(a){return "[object Array]"===Object.prototype.toString.call(a)},Base64:Base64$1};
|
|
17
17
|
|
|
18
|
-
var version = "2.
|
|
18
|
+
var version = "2.78.0";
|
|
19
19
|
|
|
20
20
|
var Constants={sdkVersion:version,sdkVendor:"mparticle",platform:"web",Messages:{DeprecationMessages:{MethodHasBeenDeprecated:"has been deprecated.",MethodMarkedForDeprecationPostfix:"is a deprecated method and will be removed in future releases.",AlternativeMethodPrefix:"Please use the alternate method:"},ErrorMessages:{NoToken:"A token must be specified.",EventNameInvalidType:"Event name must be a valid string value.",EventDataInvalidType:"Event data must be a valid object hash.",LoggingDisabled:"Event logging is currently disabled.",CookieParseError:"Could not parse cookie",EventEmpty:"Event object is null or undefined, cancelling send",APIRequestEmpty:"APIRequest is null or undefined, cancelling send",NoEventType:"Event type must be specified.",TransactionIdRequired:"Transaction ID is required",TransactionRequired:"A transaction attributes object is required",PromotionIdRequired:"Promotion ID is required",BadAttribute:"Attribute value cannot be object or array",BadKey:"Key value cannot be object or array",BadLogPurchase:"Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions",AudienceAPINotEnabled:"Your workspace is not enabled to retrieve user audiences."},InformationMessages:{CookieSearch:"Searching for cookie",CookieFound:"Cookie found, parsing values",CookieNotFound:"Cookies not found",CookieSet:"Setting cookie",CookieSync:"Performing cookie sync",SendBegin:"Starting to send event",SendIdentityBegin:"Starting to send event to identity server",SendWindowsPhone:"Sending event to Windows Phone container",SendIOS:"Calling iOS path: ",SendAndroid:"Calling Android JS interface method: ",SendHttp:"Sending event to mParticle HTTP service",SendAliasHttp:"Sending alias request to mParticle HTTP service",SendIdentityHttp:"Sending event to mParticle HTTP service",StartingNewSession:"Starting new Session",StartingLogEvent:"Starting to log event",StartingLogOptOut:"Starting to log user opt in/out",StartingEndSession:"Starting to end session",StartingInitialization:"Starting to initialize",StartingLogCommerceEvent:"Starting to log commerce event",StartingAliasRequest:"Starting to Alias MPIDs",LoadingConfig:"Loading configuration options",AbandonLogEvent:"Cannot log event, logging disabled or developer token not set",AbandonAliasUsers:"Cannot Alias Users, logging disabled or developer token not set",AbandonStartSession:"Cannot start session, logging disabled or developer token not set",AbandonEndSession:"Cannot end session, logging disabled or developer token not set",NoSessionToEnd:"Cannot end session, no active session found"},ValidationMessages:{ModifyIdentityRequestUserIdentitiesPresent:"identityRequests to modify require userIdentities to be present. Request not sent to server. Please fix and try again",IdentityRequesetInvalidKey:"There is an invalid key on your identityRequest object. It can only contain a `userIdentities` object and a `onUserAlias` function. Request not sent to server. Please fix and try again.",OnUserAliasType:"The onUserAlias value must be a function.",UserIdentities:"The userIdentities key must be an object with keys of identityTypes and values of strings. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidKey:"There is an invalid identity key on your `userIdentities` object within the identityRequest. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidValues:"All user identity values must be strings or null. Request not sent to server. Please fix and try again.",AliasMissingMpid:"Alias Request must contain both a destinationMpid and a sourceMpid",AliasNonUniqueMpid:"Alias Request's destinationMpid and sourceMpid must be unique",AliasMissingTime:"Alias Request must have both a startTime and an endTime",AliasStartBeforeEndTime:"Alias Request's endTime must be later than its startTime"}},NativeSdkPaths:{LogEvent:"logEvent",SetUserTag:"setUserTag",RemoveUserTag:"removeUserTag",SetUserAttribute:"setUserAttribute",RemoveUserAttribute:"removeUserAttribute",SetSessionAttribute:"setSessionAttribute",AddToCart:"addToCart",RemoveFromCart:"removeFromCart",ClearCart:"clearCart",LogOut:"logOut",SetUserAttributeList:"setUserAttributeList",RemoveAllUserAttributes:"removeAllUserAttributes",GetUserAttributesLists:"getUserAttributesLists",GetAllUserAttributes:"getAllUserAttributes",Identify:"identify",Logout:"logout",Login:"login",Modify:"modify",Alias:"aliasUsers",Upload:"upload"},StorageNames:{localStorageName:"mprtcl-api",localStorageNameV3:"mprtcl-v3",cookieName:"mprtcl-api",cookieNameV2:"mprtcl-v2",cookieNameV3:"mprtcl-v3",localStorageNameV4:"mprtcl-v4",localStorageProductsV4:"mprtcl-prodv4",cookieNameV4:"mprtcl-v4",currentStorageName:"mprtcl-v4",currentStorageProductsName:"mprtcl-prodv4"},DefaultConfig:{cookieDomain:null,cookieExpiration:365,logLevel:null,timeout:300,sessionTimeout:30,maxProducts:20,forwarderStatsTimeout:5e3,integrationDelayTimeout:5e3,maxCookieSize:3e3,aliasMaxWindow:90,uploadInterval:0// Maximum milliseconds in between batch uploads, below 500 will mean immediate upload. The server returns this as a string, but we are using it as a number internally
|
|
21
21
|
},DefaultBaseUrls:{v1SecureServiceUrl:"jssdks.mparticle.com/v1/JS/",v2SecureServiceUrl:"jssdks.mparticle.com/v2/JS/",v3SecureServiceUrl:"jssdks.mparticle.com/v3/JS/",configUrl:"jssdkcdns.mparticle.com/JS/v2/",identityUrl:"identity.mparticle.com/v1/",aliasUrl:"jssdks.mparticle.com/v1/identity/",userAudienceUrl:"nativesdks.mparticle.com/v1/"},// These are the paths that are used to construct the CNAME urls
|
|
@@ -147,7 +147,7 @@ var Messages$a=Constants.Messages,createCookieString=function(a){return replaceC
|
|
|
147
147
|
// -1e11 -> //-100000000000,
|
|
148
148
|
"".concat(1e7,"-").concat(1e3,"-").concat(4e3,"-").concat(8e3,"-").concat(1e11).replace(/[018]/g,// zeroes, ones, and eights with
|
|
149
149
|
generateUniqueId// random hex digits
|
|
150
|
-
)},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},parseSettingsString=function(a){try{return a?JSON.parse(a.replace(/"/g,"\"")):[]}catch(a){throw new Error("Settings string contains invalid JSON")}},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,"'")},replaceMPID=function(a,b){return a.replace("%%mpid%%",b)},replaceAmpWithAmpersand=function(a){return a.replace(/&/g,"&")},createCookieSyncUrl=function(a,b,c,d){var
|
|
150
|
+
)},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},parseSettingsString=function(a){try{return a?JSON.parse(a.replace(/"/g,"\"")):[]}catch(a){throw new Error("Settings string contains invalid JSON")}},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,"'")},replaceMPID=function(a,b){return a.replace("%%mpid%%",b)},replaceAmpWithAmpersand=function(a){return a.replace(/&/g,"&")},createCookieSyncUrl=function(a,b,c,d,e){var f=replaceAmpWithAmpersand(b),g=c?replaceAmpWithAmpersand(c):null,h=replaceMPID(f,a),i=g?replaceMPID(g,a):"",j=h+encodeURIComponent(i);if(d){var k=j.includes("?")?"&":"?";j+="".concat(k,"domain=").concat(d);}if(e){var k=j.includes("?")?"&":"?";j+="".concat(k,"google_hm=").concat(e);}return j},WEB_SAFE_BASE64_REPLACEMENTS={"+":"-","/":"_","=":""},toWebSafeBase64=function(a){return btoa(a).replace(/[+/=]/g,function(a){return WEB_SAFE_BASE64_REPLACEMENTS[a]})},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},isValidAttributeValue=function(a){return a!==void 0&&!isObject(a)&&!Array.isArray(a)},isValidCustomFlagProperty=function(a){return isNumber(a)||isString(a)||isBoolean(a)},toDataPlanSlug=function(a){// Make sure we are only acting on strings or numbers
|
|
151
151
|
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={},e={};if(!a)return d;if("undefined"!=typeof URL&&"undefined"!=typeof URLSearchParams){var f=new URL(a);c=new URLSearchParams(f.search);}else c=queryStringParserFallback(a);return (c.forEach(function(a,b){e[b.toLowerCase()]=a;}),isEmpty(b))?e:(b.forEach(function(a){var b=e[a.toLowerCase()];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.slice(1),f=e.join("=");if(d&&void 0!==f)try{b[d]=decodeURIComponent(f||"");}catch(a){console.error("Failed to decode value for key ".concat(d,": ").concat(a));}}),{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
|
|
152
152
|
var b=function parseCookies(){try{return "undefined"==typeof window?[]:window.document.cookie.split(";").map(function(a){return a.trim()})}catch(a){return console.error("Unable to parse cookies",a),[]}}();// Helper function to filter cookies by keys
|
|
153
153
|
// Parse cookies from document.cookie
|
|
@@ -158,7 +158,11 @@ if(Array.isArray(a))return a.map(function(a){return obfuscateData(a)});// Handle
|
|
|
158
158
|
if(isObject(a)){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[c]=obfuscateData(a[c]));return b}// For primitives and other types, return the type as a string
|
|
159
159
|
return _typeof$1(a)},obfuscateDevData=function(a,b){return b?a:obfuscateData(a)};/**
|
|
160
160
|
* Returns a value between 1-100 inclusive.
|
|
161
|
-
*/ //
|
|
161
|
+
*/ // Google's cookie matching service requires `google_hm` values to be web-safe
|
|
162
|
+
// base64 (RFC 4648 §5) without padding, otherwise the write to the hosted
|
|
163
|
+
// match table fails: https://developers.google.com/authorized-buyers/rtb/cookie-guide
|
|
164
|
+
// (String#replaceAll is not available in our ES5 browser targets.)
|
|
165
|
+
// FIXME: REFACTOR for V3
|
|
162
166
|
// only used in store.js to sanitize server-side formatting of
|
|
163
167
|
// booleans when checking for `isDevelopmentMode`
|
|
164
168
|
// Should be removed in v3
|
|
@@ -632,19 +636,23 @@ var PARTNER_MODULE_IDS={AdobeEventForwarder:11,DoubleclickDFP:41,AppNexus:50,Lot
|
|
|
632
636
|
// Private
|
|
633
637
|
this.attemptCookieSync=function(c,d){var e,f=a._Store,g=f.pixelConfigurations,h=f.webviewBridgeEnabled;if(c&&!h&&(null===(e=a._CookieConsentManager)||void 0===e||!e.getNoFunctional()))// When noFunctional is true, persistence is not saved, so we cannot track cookie sync
|
|
634
638
|
// dates. Skip cookie sync to avoid running it on every page load.
|
|
635
|
-
{var i=a._Persistence.getPersistence();isEmpty(i)||g.forEach(function(e){var f,g,h=!1,
|
|
636
|
-
|
|
639
|
+
{var i=a._Persistence.getPersistence();isEmpty(i)||g.forEach(function(e){var f,g,h,j=!1,k=e.filteringConsentRuleValues,l=e.pixelUrl,m=e.redirectUrl,n=e.moduleId,o=e.settings,// Tells you how often we should do a cookie sync (in days)
|
|
640
|
+
p=e.frequencyCap,q=(k||{}).values;// set requiresConsent to false to start each additional pixel configuration
|
|
637
641
|
// set to true only if filteringConsenRuleValues.values.length exists
|
|
638
642
|
// Filtering rules as defined in UI
|
|
639
|
-
if(!isEmpty(
|
|
643
|
+
if(!isEmpty(l)&&(isEmpty(q)||(j=!0),!(j&&d))&&!(n===PARTNER_MODULE_IDS.Rokt&&a._CookieConsentManager.getNoTargeting()))// For Rokt, block cookie sync when noTargeting privacy flag is true
|
|
640
644
|
// If MPID is new to cookies, we should not try to perform the cookie sync
|
|
641
645
|
// because a cookie sync can only occur once a user either consents or doesn't.
|
|
642
646
|
// we should not check if it's enabled if the user has a blank consent
|
|
643
647
|
// The Trade Desk requires a URL parameter for GDPR enabled users.
|
|
644
648
|
// It is optional but to simplify the code, we add it for all Trade
|
|
645
649
|
// // Desk cookie syncs.
|
|
646
|
-
//
|
|
647
|
-
|
|
650
|
+
// Google Marketing Platform accepts a web-safe base64-encoded MPID via the
|
|
651
|
+
// `google_hm` query parameter, but only for accounts provisioned for Google
|
|
652
|
+
// Hosted Matching — Google returns errors otherwise. It is therefore gated
|
|
653
|
+
// behind the opt-in `enableHmTag` setting (off by default), which the server
|
|
654
|
+
// delivers as the string 'True' when the UI toggle is enabled.
|
|
655
|
+
{var r=a._Consent.isEnabledForUserConsent;if(r(k,a.Identity.getCurrentUser())){var s=null!==(g=null===(f=i[c])||void 0===f?void 0:f.csd)&&void 0!==g?g:{},t=s[n]||null;if(isLastSyncDateExpired(p,t)){var u=n===PARTNER_MODULE_IDS.TradeDesk?window.location.hostname:void 0,v="true"===(null===(h=null===o||void 0===o?void 0:o.enableHmTag)||void 0===h?void 0:h.toLowerCase()),w=n===PARTNER_MODULE_IDS.DoubleclickDFP,x=w&&v?toWebSafeBase64(c):void 0,y=createCookieSyncUrl(c,l,m,u,x);b.performCookieSync(y,n.toString(),c,s);}}}});}},this.performCookieSync=function(b,c,d,e){var f=document.createElement("img");a.Logger.verbose(InformationMessages.CookieSync),f.onload=function(){e[c]=new Date().getTime(),a._Persistence.saveUserCookieSyncDatesToPersistence(d,e);},f.src=b;};}var isLastSyncDateExpired=function(a,b){// If there is no lastSyncDate, then there is no previous cookie sync, so we should sync the cookie
|
|
648
656
|
return !b||new Date().getTime()>new Date(b).getTime()+a*DAYS_IN_MILLISECONDS;// Otherwise, compare the last sync date to determine if it should do a cookie sync again
|
|
649
657
|
};
|
|
650
658
|
|
package/dist/mparticle.esm.js
CHANGED
|
@@ -15,7 +15,7 @@ map:function map(a,b){var c,d,e;if(null===this)throw new TypeError(" this is nul
|
|
|
15
15
|
filter:function filter(a/*, thisArg*/){if(void 0===this||null===this)throw new TypeError;var b=Object(this),c=b.length>>>0;if("function"!=typeof a)throw new TypeError;for(var d=[],e=2<=arguments.length?arguments[1]:void 0,f=0;f<c;f++)if(f in b){var g=b[f];a.call(e,g,f,b)&&d.push(g);}return d},// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
|
|
16
16
|
isArray:function isArray(a){return "[object Array]"===Object.prototype.toString.call(a)},Base64:Base64$1};
|
|
17
17
|
|
|
18
|
-
var version = "2.
|
|
18
|
+
var version = "2.78.0";
|
|
19
19
|
|
|
20
20
|
var Constants={sdkVersion:version,sdkVendor:"mparticle",platform:"web",Messages:{DeprecationMessages:{MethodHasBeenDeprecated:"has been deprecated.",MethodMarkedForDeprecationPostfix:"is a deprecated method and will be removed in future releases.",AlternativeMethodPrefix:"Please use the alternate method:"},ErrorMessages:{NoToken:"A token must be specified.",EventNameInvalidType:"Event name must be a valid string value.",EventDataInvalidType:"Event data must be a valid object hash.",LoggingDisabled:"Event logging is currently disabled.",CookieParseError:"Could not parse cookie",EventEmpty:"Event object is null or undefined, cancelling send",APIRequestEmpty:"APIRequest is null or undefined, cancelling send",NoEventType:"Event type must be specified.",TransactionIdRequired:"Transaction ID is required",TransactionRequired:"A transaction attributes object is required",PromotionIdRequired:"Promotion ID is required",BadAttribute:"Attribute value cannot be object or array",BadKey:"Key value cannot be object or array",BadLogPurchase:"Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions",AudienceAPINotEnabled:"Your workspace is not enabled to retrieve user audiences."},InformationMessages:{CookieSearch:"Searching for cookie",CookieFound:"Cookie found, parsing values",CookieNotFound:"Cookies not found",CookieSet:"Setting cookie",CookieSync:"Performing cookie sync",SendBegin:"Starting to send event",SendIdentityBegin:"Starting to send event to identity server",SendWindowsPhone:"Sending event to Windows Phone container",SendIOS:"Calling iOS path: ",SendAndroid:"Calling Android JS interface method: ",SendHttp:"Sending event to mParticle HTTP service",SendAliasHttp:"Sending alias request to mParticle HTTP service",SendIdentityHttp:"Sending event to mParticle HTTP service",StartingNewSession:"Starting new Session",StartingLogEvent:"Starting to log event",StartingLogOptOut:"Starting to log user opt in/out",StartingEndSession:"Starting to end session",StartingInitialization:"Starting to initialize",StartingLogCommerceEvent:"Starting to log commerce event",StartingAliasRequest:"Starting to Alias MPIDs",LoadingConfig:"Loading configuration options",AbandonLogEvent:"Cannot log event, logging disabled or developer token not set",AbandonAliasUsers:"Cannot Alias Users, logging disabled or developer token not set",AbandonStartSession:"Cannot start session, logging disabled or developer token not set",AbandonEndSession:"Cannot end session, logging disabled or developer token not set",NoSessionToEnd:"Cannot end session, no active session found"},ValidationMessages:{ModifyIdentityRequestUserIdentitiesPresent:"identityRequests to modify require userIdentities to be present. Request not sent to server. Please fix and try again",IdentityRequesetInvalidKey:"There is an invalid key on your identityRequest object. It can only contain a `userIdentities` object and a `onUserAlias` function. Request not sent to server. Please fix and try again.",OnUserAliasType:"The onUserAlias value must be a function.",UserIdentities:"The userIdentities key must be an object with keys of identityTypes and values of strings. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidKey:"There is an invalid identity key on your `userIdentities` object within the identityRequest. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidValues:"All user identity values must be strings or null. Request not sent to server. Please fix and try again.",AliasMissingMpid:"Alias Request must contain both a destinationMpid and a sourceMpid",AliasNonUniqueMpid:"Alias Request's destinationMpid and sourceMpid must be unique",AliasMissingTime:"Alias Request must have both a startTime and an endTime",AliasStartBeforeEndTime:"Alias Request's endTime must be later than its startTime"}},NativeSdkPaths:{LogEvent:"logEvent",SetUserTag:"setUserTag",RemoveUserTag:"removeUserTag",SetUserAttribute:"setUserAttribute",RemoveUserAttribute:"removeUserAttribute",SetSessionAttribute:"setSessionAttribute",AddToCart:"addToCart",RemoveFromCart:"removeFromCart",ClearCart:"clearCart",LogOut:"logOut",SetUserAttributeList:"setUserAttributeList",RemoveAllUserAttributes:"removeAllUserAttributes",GetUserAttributesLists:"getUserAttributesLists",GetAllUserAttributes:"getAllUserAttributes",Identify:"identify",Logout:"logout",Login:"login",Modify:"modify",Alias:"aliasUsers",Upload:"upload"},StorageNames:{localStorageName:"mprtcl-api",localStorageNameV3:"mprtcl-v3",cookieName:"mprtcl-api",cookieNameV2:"mprtcl-v2",cookieNameV3:"mprtcl-v3",localStorageNameV4:"mprtcl-v4",localStorageProductsV4:"mprtcl-prodv4",cookieNameV4:"mprtcl-v4",currentStorageName:"mprtcl-v4",currentStorageProductsName:"mprtcl-prodv4"},DefaultConfig:{cookieDomain:null,cookieExpiration:365,logLevel:null,timeout:300,sessionTimeout:30,maxProducts:20,forwarderStatsTimeout:5e3,integrationDelayTimeout:5e3,maxCookieSize:3e3,aliasMaxWindow:90,uploadInterval:0// Maximum milliseconds in between batch uploads, below 500 will mean immediate upload. The server returns this as a string, but we are using it as a number internally
|
|
21
21
|
},DefaultBaseUrls:{v1SecureServiceUrl:"jssdks.mparticle.com/v1/JS/",v2SecureServiceUrl:"jssdks.mparticle.com/v2/JS/",v3SecureServiceUrl:"jssdks.mparticle.com/v3/JS/",configUrl:"jssdkcdns.mparticle.com/JS/v2/",identityUrl:"identity.mparticle.com/v1/",aliasUrl:"jssdks.mparticle.com/v1/identity/",userAudienceUrl:"nativesdks.mparticle.com/v1/"},// These are the paths that are used to construct the CNAME urls
|
|
@@ -147,7 +147,7 @@ var Messages$a=Constants.Messages,createCookieString=function(a){return replaceC
|
|
|
147
147
|
// -1e11 -> //-100000000000,
|
|
148
148
|
"".concat(1e7,"-").concat(1e3,"-").concat(4e3,"-").concat(8e3,"-").concat(1e11).replace(/[018]/g,// zeroes, ones, and eights with
|
|
149
149
|
generateUniqueId// random hex digits
|
|
150
|
-
)},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},parseSettingsString=function(a){try{return a?JSON.parse(a.replace(/"/g,"\"")):[]}catch(a){throw new Error("Settings string contains invalid JSON")}},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,"'")},replaceMPID=function(a,b){return a.replace("%%mpid%%",b)},replaceAmpWithAmpersand=function(a){return a.replace(/&/g,"&")},createCookieSyncUrl=function(a,b,c,d){var
|
|
150
|
+
)},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},parseSettingsString=function(a){try{return a?JSON.parse(a.replace(/"/g,"\"")):[]}catch(a){throw new Error("Settings string contains invalid JSON")}},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,"'")},replaceMPID=function(a,b){return a.replace("%%mpid%%",b)},replaceAmpWithAmpersand=function(a){return a.replace(/&/g,"&")},createCookieSyncUrl=function(a,b,c,d,e){var f=replaceAmpWithAmpersand(b),g=c?replaceAmpWithAmpersand(c):null,h=replaceMPID(f,a),i=g?replaceMPID(g,a):"",j=h+encodeURIComponent(i);if(d){var k=j.includes("?")?"&":"?";j+="".concat(k,"domain=").concat(d);}if(e){var k=j.includes("?")?"&":"?";j+="".concat(k,"google_hm=").concat(e);}return j},WEB_SAFE_BASE64_REPLACEMENTS={"+":"-","/":"_","=":""},toWebSafeBase64=function(a){return btoa(a).replace(/[+/=]/g,function(a){return WEB_SAFE_BASE64_REPLACEMENTS[a]})},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},isValidAttributeValue=function(a){return a!==void 0&&!isObject(a)&&!Array.isArray(a)},isValidCustomFlagProperty=function(a){return isNumber(a)||isString(a)||isBoolean(a)},toDataPlanSlug=function(a){// Make sure we are only acting on strings or numbers
|
|
151
151
|
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={},e={};if(!a)return d;if("undefined"!=typeof URL&&"undefined"!=typeof URLSearchParams){var f=new URL(a);c=new URLSearchParams(f.search);}else c=queryStringParserFallback(a);return (c.forEach(function(a,b){e[b.toLowerCase()]=a;}),isEmpty(b))?e:(b.forEach(function(a){var b=e[a.toLowerCase()];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.slice(1),f=e.join("=");if(d&&void 0!==f)try{b[d]=decodeURIComponent(f||"");}catch(a){console.error("Failed to decode value for key ".concat(d,": ").concat(a));}}),{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
|
|
152
152
|
var b=function parseCookies(){try{return "undefined"==typeof window?[]:window.document.cookie.split(";").map(function(a){return a.trim()})}catch(a){return console.error("Unable to parse cookies",a),[]}}();// Helper function to filter cookies by keys
|
|
153
153
|
// Parse cookies from document.cookie
|
|
@@ -158,7 +158,11 @@ if(Array.isArray(a))return a.map(function(a){return obfuscateData(a)});// Handle
|
|
|
158
158
|
if(isObject(a)){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[c]=obfuscateData(a[c]));return b}// For primitives and other types, return the type as a string
|
|
159
159
|
return _typeof$1(a)},obfuscateDevData=function(a,b){return b?a:obfuscateData(a)};/**
|
|
160
160
|
* Returns a value between 1-100 inclusive.
|
|
161
|
-
*/ //
|
|
161
|
+
*/ // Google's cookie matching service requires `google_hm` values to be web-safe
|
|
162
|
+
// base64 (RFC 4648 §5) without padding, otherwise the write to the hosted
|
|
163
|
+
// match table fails: https://developers.google.com/authorized-buyers/rtb/cookie-guide
|
|
164
|
+
// (String#replaceAll is not available in our ES5 browser targets.)
|
|
165
|
+
// FIXME: REFACTOR for V3
|
|
162
166
|
// only used in store.js to sanitize server-side formatting of
|
|
163
167
|
// booleans when checking for `isDevelopmentMode`
|
|
164
168
|
// Should be removed in v3
|
|
@@ -632,19 +636,23 @@ var PARTNER_MODULE_IDS={AdobeEventForwarder:11,DoubleclickDFP:41,AppNexus:50,Lot
|
|
|
632
636
|
// Private
|
|
633
637
|
this.attemptCookieSync=function(c,d){var e,f=a._Store,g=f.pixelConfigurations,h=f.webviewBridgeEnabled;if(c&&!h&&(null===(e=a._CookieConsentManager)||void 0===e||!e.getNoFunctional()))// When noFunctional is true, persistence is not saved, so we cannot track cookie sync
|
|
634
638
|
// dates. Skip cookie sync to avoid running it on every page load.
|
|
635
|
-
{var i=a._Persistence.getPersistence();isEmpty(i)||g.forEach(function(e){var f,g,h=!1,
|
|
636
|
-
|
|
639
|
+
{var i=a._Persistence.getPersistence();isEmpty(i)||g.forEach(function(e){var f,g,h,j=!1,k=e.filteringConsentRuleValues,l=e.pixelUrl,m=e.redirectUrl,n=e.moduleId,o=e.settings,// Tells you how often we should do a cookie sync (in days)
|
|
640
|
+
p=e.frequencyCap,q=(k||{}).values;// set requiresConsent to false to start each additional pixel configuration
|
|
637
641
|
// set to true only if filteringConsenRuleValues.values.length exists
|
|
638
642
|
// Filtering rules as defined in UI
|
|
639
|
-
if(!isEmpty(
|
|
643
|
+
if(!isEmpty(l)&&(isEmpty(q)||(j=!0),!(j&&d))&&!(n===PARTNER_MODULE_IDS.Rokt&&a._CookieConsentManager.getNoTargeting()))// For Rokt, block cookie sync when noTargeting privacy flag is true
|
|
640
644
|
// If MPID is new to cookies, we should not try to perform the cookie sync
|
|
641
645
|
// because a cookie sync can only occur once a user either consents or doesn't.
|
|
642
646
|
// we should not check if it's enabled if the user has a blank consent
|
|
643
647
|
// The Trade Desk requires a URL parameter for GDPR enabled users.
|
|
644
648
|
// It is optional but to simplify the code, we add it for all Trade
|
|
645
649
|
// // Desk cookie syncs.
|
|
646
|
-
//
|
|
647
|
-
|
|
650
|
+
// Google Marketing Platform accepts a web-safe base64-encoded MPID via the
|
|
651
|
+
// `google_hm` query parameter, but only for accounts provisioned for Google
|
|
652
|
+
// Hosted Matching — Google returns errors otherwise. It is therefore gated
|
|
653
|
+
// behind the opt-in `enableHmTag` setting (off by default), which the server
|
|
654
|
+
// delivers as the string 'True' when the UI toggle is enabled.
|
|
655
|
+
{var r=a._Consent.isEnabledForUserConsent;if(r(k,a.Identity.getCurrentUser())){var s=null!==(g=null===(f=i[c])||void 0===f?void 0:f.csd)&&void 0!==g?g:{},t=s[n]||null;if(isLastSyncDateExpired(p,t)){var u=n===PARTNER_MODULE_IDS.TradeDesk?window.location.hostname:void 0,v="true"===(null===(h=null===o||void 0===o?void 0:o.enableHmTag)||void 0===h?void 0:h.toLowerCase()),w=n===PARTNER_MODULE_IDS.DoubleclickDFP,x=w&&v?toWebSafeBase64(c):void 0,y=createCookieSyncUrl(c,l,m,u,x);b.performCookieSync(y,n.toString(),c,s);}}}});}},this.performCookieSync=function(b,c,d,e){var f=document.createElement("img");a.Logger.verbose(InformationMessages.CookieSync),f.onload=function(){e[c]=new Date().getTime(),a._Persistence.saveUserCookieSyncDatesToPersistence(d,e);},f.src=b;};}var isLastSyncDateExpired=function(a,b){// If there is no lastSyncDate, then there is no previous cookie sync, so we should sync the cookie
|
|
648
656
|
return !b||new Date().getTime()>new Date(b).getTime()+a*DAYS_IN_MILLISECONDS;// Otherwise, compare the last sync date to determine if it should do a cookie sync again
|
|
649
657
|
};
|
|
650
658
|
|
package/dist/mparticle.js
CHANGED
|
@@ -203,7 +203,7 @@ var mParticle = (function () {
|
|
|
203
203
|
Base64: Base64$1
|
|
204
204
|
};
|
|
205
205
|
|
|
206
|
-
var version = "2.
|
|
206
|
+
var version = "2.78.0";
|
|
207
207
|
|
|
208
208
|
var Constants = {
|
|
209
209
|
sdkVersion: version,
|
|
@@ -684,7 +684,7 @@ var mParticle = (function () {
|
|
|
684
684
|
var replaceAmpWithAmpersand = function replaceAmpWithAmpersand(value) {
|
|
685
685
|
return value.replace(/&/g, '&');
|
|
686
686
|
};
|
|
687
|
-
var createCookieSyncUrl = function createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain) {
|
|
687
|
+
var createCookieSyncUrl = function createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain, base64Mpid) {
|
|
688
688
|
var modifiedPixelUrl = replaceAmpWithAmpersand(pixelUrl);
|
|
689
689
|
var modifiedDirectUrl = redirectUrl ? replaceAmpWithAmpersand(redirectUrl) : null;
|
|
690
690
|
var url = replaceMPID(modifiedPixelUrl, mpid);
|
|
@@ -694,8 +694,26 @@ var mParticle = (function () {
|
|
|
694
694
|
var separator = fullUrl.includes('?') ? '&' : '?';
|
|
695
695
|
fullUrl += "".concat(separator, "domain=").concat(domain);
|
|
696
696
|
}
|
|
697
|
+
if (base64Mpid) {
|
|
698
|
+
var separator = fullUrl.includes('?') ? '&' : '?';
|
|
699
|
+
fullUrl += "".concat(separator, "google_hm=").concat(base64Mpid);
|
|
700
|
+
}
|
|
697
701
|
return fullUrl;
|
|
698
702
|
};
|
|
703
|
+
// Google's cookie matching service requires `google_hm` values to be web-safe
|
|
704
|
+
// base64 (RFC 4648 §5) without padding, otherwise the write to the hosted
|
|
705
|
+
// match table fails: https://developers.google.com/authorized-buyers/rtb/cookie-guide
|
|
706
|
+
// (String#replaceAll is not available in our ES5 browser targets.)
|
|
707
|
+
var WEB_SAFE_BASE64_REPLACEMENTS = {
|
|
708
|
+
'+': '-',
|
|
709
|
+
'/': '_',
|
|
710
|
+
'=': ''
|
|
711
|
+
};
|
|
712
|
+
var toWebSafeBase64 = function toWebSafeBase64(value) {
|
|
713
|
+
return btoa(value).replace(/[+/=]/g, function (c) {
|
|
714
|
+
return WEB_SAFE_BASE64_REPLACEMENTS[c];
|
|
715
|
+
});
|
|
716
|
+
};
|
|
699
717
|
// FIXME: REFACTOR for V3
|
|
700
718
|
// only used in store.js to sanitize server-side formatting of
|
|
701
719
|
// booleans when checking for `isDevelopmentMode`
|
|
@@ -4190,7 +4208,7 @@ var mParticle = (function () {
|
|
|
4190
4208
|
return;
|
|
4191
4209
|
}
|
|
4192
4210
|
pixelConfigurations.forEach(function (pixelSettings) {
|
|
4193
|
-
var _a, _b;
|
|
4211
|
+
var _a, _b, _c;
|
|
4194
4212
|
// set requiresConsent to false to start each additional pixel configuration
|
|
4195
4213
|
// set to true only if filteringConsenRuleValues.values.length exists
|
|
4196
4214
|
var requiresConsent = false;
|
|
@@ -4199,6 +4217,7 @@ var mParticle = (function () {
|
|
|
4199
4217
|
pixelUrl = pixelSettings.pixelUrl,
|
|
4200
4218
|
redirectUrl = pixelSettings.redirectUrl,
|
|
4201
4219
|
moduleId = pixelSettings.moduleId,
|
|
4220
|
+
settings = pixelSettings.settings,
|
|
4202
4221
|
// Tells you how often we should do a cookie sync (in days)
|
|
4203
4222
|
frequencyCap = pixelSettings.frequencyCap;
|
|
4204
4223
|
var values = (filteringConsentRuleValues || {}).values;
|
|
@@ -4231,8 +4250,15 @@ var mParticle = (function () {
|
|
|
4231
4250
|
// It is optional but to simplify the code, we add it for all Trade
|
|
4232
4251
|
// // Desk cookie syncs.
|
|
4233
4252
|
var domain = moduleId === PARTNER_MODULE_IDS.TradeDesk ? window.location.hostname : undefined;
|
|
4234
|
-
//
|
|
4235
|
-
|
|
4253
|
+
// Google Marketing Platform accepts a web-safe base64-encoded MPID via the
|
|
4254
|
+
// `google_hm` query parameter, but only for accounts provisioned for Google
|
|
4255
|
+
// Hosted Matching — Google returns errors otherwise. It is therefore gated
|
|
4256
|
+
// behind the opt-in `enableHmTag` setting (off by default), which the server
|
|
4257
|
+
// delivers as the string 'True' when the UI toggle is enabled.
|
|
4258
|
+
var enableHmTag = ((_c = settings === null || settings === void 0 ? void 0 : settings.enableHmTag) === null || _c === void 0 ? void 0 : _c.toLowerCase()) === 'true';
|
|
4259
|
+
var isDoubleClickModule = moduleId === PARTNER_MODULE_IDS.DoubleclickDFP;
|
|
4260
|
+
var base64Mpid = isDoubleClickModule && enableHmTag ? toWebSafeBase64(mpid) : undefined;
|
|
4261
|
+
var fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain, base64Mpid);
|
|
4236
4262
|
self.performCookieSync(fullUrl, moduleId.toString(), mpid, cookieSyncDates);
|
|
4237
4263
|
});
|
|
4238
4264
|
};
|
|
@@ -27,7 +27,8 @@ declare const replaceApostrophesWithQuotes: (value: string) => string;
|
|
|
27
27
|
declare const replaceQuotesWithApostrophes: (value: string) => string;
|
|
28
28
|
declare const replaceMPID: (value: string, mpid: MPID) => string;
|
|
29
29
|
declare const replaceAmpWithAmpersand: (value: string) => string;
|
|
30
|
-
declare const createCookieSyncUrl: (mpid: MPID, pixelUrl: string, redirectUrl?: string, domain?: string) => string;
|
|
30
|
+
declare const createCookieSyncUrl: (mpid: MPID, pixelUrl: string, redirectUrl?: string, domain?: string, base64Mpid?: string) => string;
|
|
31
|
+
declare const toWebSafeBase64: (value: string) => string;
|
|
31
32
|
declare const returnConvertedBoolean: (data: string | boolean | number) => boolean;
|
|
32
33
|
declare const decoded: (s: string) => string;
|
|
33
34
|
declare const converted: (s: string) => string;
|
|
@@ -81,4 +82,4 @@ declare const obfuscateData: (value: any) => any;
|
|
|
81
82
|
declare const obfuscateDevData: (data: any, isDevelopmentMode?: boolean) => any;
|
|
82
83
|
declare function extend(...args: any[]): any;
|
|
83
84
|
declare const getErrorMessage: (e: unknown, fallback?: string) => string;
|
|
84
|
-
export { createCookieString, revertCookieString, createCookieSyncUrl, valueof, AttributeValue, converted, decoded, obfuscateDevData, filterDictionaryWithHash, findKeyInObject, generateDeprecationMessage, generateHash, generateUniqueId, getErrorMessage, getRampNumber, inArray, isObject, isStringOrNumber, obfuscateData, parseConfig, parseNumber, parseSettingsString, parseStringOrNumber, replaceCommasWithPipes, replacePipesWithCommas, replaceApostrophesWithQuotes, replaceQuotesWithApostrophes, returnConvertedBoolean, toDataPlanSlug, isString, isNumber, isFunction, isDataPlanSlug, isEmpty, isValidAttributeValue, isValidCustomFlagProperty, mergeObjects, moveElementToEnd, queryStringParser, getCookies, getHref, replaceMPID, replaceAmpWithAmpersand, extend, };
|
|
85
|
+
export { createCookieString, revertCookieString, createCookieSyncUrl, toWebSafeBase64, valueof, AttributeValue, converted, decoded, obfuscateDevData, filterDictionaryWithHash, findKeyInObject, generateDeprecationMessage, generateHash, generateUniqueId, getErrorMessage, getRampNumber, inArray, isObject, isStringOrNumber, obfuscateData, parseConfig, parseNumber, parseSettingsString, parseStringOrNumber, replaceCommasWithPipes, replacePipesWithCommas, replaceApostrophesWithQuotes, replaceQuotesWithApostrophes, returnConvertedBoolean, toDataPlanSlug, isString, isNumber, isFunction, isDataPlanSlug, isEmpty, isValidAttributeValue, isValidCustomFlagProperty, mergeObjects, moveElementToEnd, queryStringParser, getCookies, getHref, replaceMPID, replaceAmpWithAmpersand, extend, };
|
package/package.json
CHANGED
package/src/cookieSyncManager.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
Dictionary,
|
|
3
3
|
isEmpty,
|
|
4
4
|
createCookieSyncUrl,
|
|
5
|
+
toWebSafeBase64,
|
|
5
6
|
} from './utils';
|
|
6
7
|
import Constants from './constants';
|
|
7
8
|
import { MPID } from '@mparticle/web-sdk';
|
|
@@ -95,6 +96,7 @@ export default function CookieSyncManager(
|
|
|
95
96
|
pixelUrl,
|
|
96
97
|
redirectUrl,
|
|
97
98
|
moduleId,
|
|
99
|
+
settings,
|
|
98
100
|
// Tells you how often we should do a cookie sync (in days)
|
|
99
101
|
frequencyCap,
|
|
100
102
|
} = pixelSettings;
|
|
@@ -137,8 +139,17 @@ export default function CookieSyncManager(
|
|
|
137
139
|
// It is optional but to simplify the code, we add it for all Trade
|
|
138
140
|
// // Desk cookie syncs.
|
|
139
141
|
const domain = moduleId === PARTNER_MODULE_IDS.TradeDesk ? window.location.hostname : undefined;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
+
|
|
143
|
+
// Google Marketing Platform accepts a web-safe base64-encoded MPID via the
|
|
144
|
+
// `google_hm` query parameter, but only for accounts provisioned for Google
|
|
145
|
+
// Hosted Matching — Google returns errors otherwise. It is therefore gated
|
|
146
|
+
// behind the opt-in `enableHmTag` setting (off by default), which the server
|
|
147
|
+
// delivers as the string 'True' when the UI toggle is enabled.
|
|
148
|
+
const enableHmTag = settings?.enableHmTag?.toLowerCase() === 'true';
|
|
149
|
+
const isDoubleClickModule = moduleId === PARTNER_MODULE_IDS.DoubleclickDFP;
|
|
150
|
+
const base64Mpid = isDoubleClickModule && enableHmTag ? toWebSafeBase64(mpid) : undefined;
|
|
151
|
+
|
|
152
|
+
const fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain, base64Mpid);
|
|
142
153
|
|
|
143
154
|
self.performCookieSync(
|
|
144
155
|
fullUrl,
|
package/src/utils.ts
CHANGED
|
@@ -207,7 +207,8 @@ const createCookieSyncUrl = (
|
|
|
207
207
|
mpid: MPID,
|
|
208
208
|
pixelUrl: string,
|
|
209
209
|
redirectUrl?: string,
|
|
210
|
-
domain?: string
|
|
210
|
+
domain?: string,
|
|
211
|
+
base64Mpid?: string
|
|
211
212
|
): string => {
|
|
212
213
|
const modifiedPixelUrl = replaceAmpWithAmpersand(pixelUrl);
|
|
213
214
|
const modifiedDirectUrl = redirectUrl
|
|
@@ -215,21 +216,39 @@ const createCookieSyncUrl = (
|
|
|
215
216
|
: null;
|
|
216
217
|
|
|
217
218
|
let url = replaceMPID(modifiedPixelUrl, mpid);
|
|
218
|
-
|
|
219
|
+
|
|
219
220
|
const redirect = modifiedDirectUrl
|
|
220
221
|
? replaceMPID(modifiedDirectUrl, mpid)
|
|
221
222
|
: '';
|
|
222
|
-
|
|
223
|
+
|
|
223
224
|
let fullUrl = url + encodeURIComponent(redirect);
|
|
224
|
-
|
|
225
|
+
|
|
225
226
|
if (domain) {
|
|
226
227
|
const separator = fullUrl.includes('?') ? '&' : '?';
|
|
227
228
|
fullUrl += `${separator}domain=${domain}`;
|
|
228
229
|
}
|
|
229
|
-
|
|
230
|
+
|
|
231
|
+
if (base64Mpid) {
|
|
232
|
+
const separator = fullUrl.includes('?') ? '&' : '?';
|
|
233
|
+
fullUrl += `${separator}google_hm=${base64Mpid}`;
|
|
234
|
+
}
|
|
235
|
+
|
|
230
236
|
return fullUrl;
|
|
231
237
|
};
|
|
232
238
|
|
|
239
|
+
// Google's cookie matching service requires `google_hm` values to be web-safe
|
|
240
|
+
// base64 (RFC 4648 §5) without padding, otherwise the write to the hosted
|
|
241
|
+
// match table fails: https://developers.google.com/authorized-buyers/rtb/cookie-guide
|
|
242
|
+
// (String#replaceAll is not available in our ES5 browser targets.)
|
|
243
|
+
const WEB_SAFE_BASE64_REPLACEMENTS: Dictionary<string> = {
|
|
244
|
+
'+': '-',
|
|
245
|
+
'/': '_',
|
|
246
|
+
'=': '',
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const toWebSafeBase64 = (value: string): string =>
|
|
250
|
+
btoa(value).replace(/[+/=]/g, c => WEB_SAFE_BASE64_REPLACEMENTS[c]);
|
|
251
|
+
|
|
233
252
|
// FIXME: REFACTOR for V3
|
|
234
253
|
// only used in store.js to sanitize server-side formatting of
|
|
235
254
|
// booleans when checking for `isDevelopmentMode`
|
|
@@ -650,6 +669,7 @@ export {
|
|
|
650
669
|
createCookieString,
|
|
651
670
|
revertCookieString,
|
|
652
671
|
createCookieSyncUrl,
|
|
672
|
+
toWebSafeBase64,
|
|
653
673
|
valueof,
|
|
654
674
|
AttributeValue,
|
|
655
675
|
converted,
|