@mparticle/web-sdk 2.51.0 → 2.52.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/README.md +1 -1
- package/dist/mparticle.common.js +29 -15
- package/dist/mparticle.esm.js +29 -15
- package/dist/mparticle.js +216 -45
- package/package.json +1 -1
- package/src/cookieSyncManager.ts +16 -2
- package/src/identity.interfaces.ts +5 -2
- package/src/identity.js +3 -1
- package/src/mparticle-instance-manager.ts +2 -2
- package/src/roktManager.ts +97 -7
- package/src/sessionManager.ts +45 -40
- package/src/store.ts +1 -0
- package/src/stub/mparticle.stub.js +1 -0
- package/src/utils.ts +13 -3
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.52.0";
|
|
207
207
|
|
|
208
208
|
var Constants = {
|
|
209
209
|
sdkVersion: version,
|
|
@@ -667,12 +667,17 @@ var mParticle = (function () {
|
|
|
667
667
|
var replaceAmpWithAmpersand = function replaceAmpWithAmpersand(value) {
|
|
668
668
|
return value.replace(/&/g, '&');
|
|
669
669
|
};
|
|
670
|
-
var createCookieSyncUrl = function createCookieSyncUrl(mpid, pixelUrl, redirectUrl) {
|
|
670
|
+
var createCookieSyncUrl = function createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain) {
|
|
671
671
|
var modifiedPixelUrl = replaceAmpWithAmpersand(pixelUrl);
|
|
672
672
|
var modifiedDirectUrl = redirectUrl ? replaceAmpWithAmpersand(redirectUrl) : null;
|
|
673
673
|
var url = replaceMPID(modifiedPixelUrl, mpid);
|
|
674
674
|
var redirect = modifiedDirectUrl ? replaceMPID(modifiedDirectUrl, mpid) : '';
|
|
675
|
-
|
|
675
|
+
var fullUrl = url + encodeURIComponent(redirect);
|
|
676
|
+
if (domain) {
|
|
677
|
+
var separator = fullUrl.includes('?') ? '&' : '?';
|
|
678
|
+
fullUrl += "".concat(separator, "domain=").concat(domain);
|
|
679
|
+
}
|
|
680
|
+
return fullUrl;
|
|
676
681
|
};
|
|
677
682
|
// FIXME: REFACTOR for V3
|
|
678
683
|
// only used in store.js to sanitize server-side formatting of
|
|
@@ -3474,6 +3479,15 @@ var mParticle = (function () {
|
|
|
3474
3479
|
var Messages$7 = Constants.Messages;
|
|
3475
3480
|
var InformationMessages = Messages$7.InformationMessages;
|
|
3476
3481
|
var DAYS_IN_MILLISECONDS = 1000 * 60 * 60 * 24;
|
|
3482
|
+
// Partner module IDs for cookie sync configurations
|
|
3483
|
+
var PARTNER_MODULE_IDS = {
|
|
3484
|
+
AdobeEventForwarder: 11,
|
|
3485
|
+
DoubleclickDFP: 41,
|
|
3486
|
+
AppNexus: 50,
|
|
3487
|
+
Lotame: 58,
|
|
3488
|
+
TradeDesk: 103,
|
|
3489
|
+
VerizonMedia: 155
|
|
3490
|
+
};
|
|
3477
3491
|
function CookieSyncManager(mpInstance) {
|
|
3478
3492
|
var self = this;
|
|
3479
3493
|
// Public
|
|
@@ -3522,8 +3536,12 @@ var mParticle = (function () {
|
|
|
3522
3536
|
if (!isLastSyncDateExpired(frequencyCap, lastSyncDateForModule)) {
|
|
3523
3537
|
return;
|
|
3524
3538
|
}
|
|
3525
|
-
//
|
|
3526
|
-
|
|
3539
|
+
// The Trade Desk requires a URL parameter for GDPR enabled users.
|
|
3540
|
+
// It is optional but to simplify the code, we add it for all Trade
|
|
3541
|
+
// // Desk cookie syncs.
|
|
3542
|
+
var domain = moduleId === PARTNER_MODULE_IDS.TradeDesk ? window.location.hostname : undefined;
|
|
3543
|
+
// Add domain parameter for Trade Desk
|
|
3544
|
+
var fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain);
|
|
3527
3545
|
self.performCookieSync(fullUrl, moduleId.toString(), mpid, cookieSyncDates);
|
|
3528
3546
|
});
|
|
3529
3547
|
};
|
|
@@ -3710,17 +3728,20 @@ var mParticle = (function () {
|
|
|
3710
3728
|
var self = this;
|
|
3711
3729
|
this.initialize = function () {
|
|
3712
3730
|
if (mpInstance._Store.sessionId) {
|
|
3713
|
-
var
|
|
3714
|
-
|
|
3731
|
+
var _a = mpInstance._Store,
|
|
3732
|
+
dateLastEventSent = _a.dateLastEventSent,
|
|
3733
|
+
SDKConfig = _a.SDKConfig;
|
|
3734
|
+
var sessionTimeout = SDKConfig.sessionTimeout;
|
|
3735
|
+
if (hasSessionTimedOut(dateLastEventSent === null || dateLastEventSent === void 0 ? void 0 : dateLastEventSent.getTime(), sessionTimeout)) {
|
|
3715
3736
|
self.endSession();
|
|
3716
3737
|
self.startNewSession();
|
|
3717
3738
|
} else {
|
|
3718
3739
|
// https://go.mparticle.com/work/SQDSDKS-6045
|
|
3719
3740
|
// https://go.mparticle.com/work/SQDSDKS-6323
|
|
3720
3741
|
var currentUser = mpInstance.Identity.getCurrentUser();
|
|
3721
|
-
var sdkIdentityRequest =
|
|
3742
|
+
var sdkIdentityRequest = SDKConfig.identifyRequest;
|
|
3722
3743
|
if (hasIdentityRequestChanged(currentUser, sdkIdentityRequest)) {
|
|
3723
|
-
mpInstance.Identity.identify(
|
|
3744
|
+
mpInstance.Identity.identify(sdkIdentityRequest, SDKConfig.identityCallback);
|
|
3724
3745
|
mpInstance._Store.identifyCalled = true;
|
|
3725
3746
|
mpInstance._Store.SDKConfig.identityCallback = null;
|
|
3726
3747
|
}
|
|
@@ -3764,14 +3785,10 @@ var mParticle = (function () {
|
|
|
3764
3785
|
}
|
|
3765
3786
|
};
|
|
3766
3787
|
this.endSession = function (override) {
|
|
3767
|
-
var _a, _b, _c, _d
|
|
3788
|
+
var _a, _b, _c, _d;
|
|
3768
3789
|
mpInstance.Logger.verbose(Messages$6.InformationMessages.StartingEndSession);
|
|
3769
3790
|
if (override) {
|
|
3770
|
-
|
|
3771
|
-
messageType: Types.MessageType.SessionEnd
|
|
3772
|
-
});
|
|
3773
|
-
mpInstance._Store.nullifySession();
|
|
3774
|
-
(_a = mpInstance._timeOnSiteTimer) === null || _a === void 0 ? void 0 : _a.resetTimer();
|
|
3791
|
+
performSessionEnd();
|
|
3775
3792
|
return;
|
|
3776
3793
|
}
|
|
3777
3794
|
if (!mpInstance._Helpers.canLog()) {
|
|
@@ -3780,36 +3797,28 @@ var mParticle = (function () {
|
|
|
3780
3797
|
// - the devToken is undefined
|
|
3781
3798
|
// - webviewBridgeEnabled is set to false
|
|
3782
3799
|
mpInstance.Logger.verbose(Messages$6.InformationMessages.AbandonEndSession);
|
|
3783
|
-
(
|
|
3800
|
+
(_a = mpInstance._timeOnSiteTimer) === null || _a === void 0 ? void 0 : _a.resetTimer();
|
|
3784
3801
|
return;
|
|
3785
3802
|
}
|
|
3786
|
-
var sessionTimeoutInMilliseconds;
|
|
3787
|
-
var timeSinceLastEventSent;
|
|
3788
3803
|
var cookies = mpInstance._Persistence.getPersistence();
|
|
3789
3804
|
if (!cookies || cookies.gs && !cookies.gs.sid) {
|
|
3790
3805
|
mpInstance.Logger.verbose(Messages$6.InformationMessages.NoSessionToEnd);
|
|
3791
|
-
(
|
|
3806
|
+
(_b = mpInstance._timeOnSiteTimer) === null || _b === void 0 ? void 0 : _b.resetTimer();
|
|
3792
3807
|
return;
|
|
3793
3808
|
}
|
|
3794
3809
|
// sessionId is not equal to cookies.sid if cookies.sid is changed in another tab
|
|
3795
3810
|
if (cookies.gs.sid && mpInstance._Store.sessionId !== cookies.gs.sid) {
|
|
3796
3811
|
mpInstance._Store.sessionId = cookies.gs.sid;
|
|
3797
3812
|
}
|
|
3798
|
-
if ((
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
if (timeSinceLastEventSent < sessionTimeoutInMilliseconds) {
|
|
3803
|
-
self.setSessionTimer();
|
|
3813
|
+
if ((_c = cookies === null || cookies === void 0 ? void 0 : cookies.gs) === null || _c === void 0 ? void 0 : _c.les) {
|
|
3814
|
+
var sessionTimeout = mpInstance._Store.SDKConfig.sessionTimeout;
|
|
3815
|
+
if (hasSessionTimedOut(cookies.gs.les, sessionTimeout)) {
|
|
3816
|
+
performSessionEnd();
|
|
3804
3817
|
} else {
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
});
|
|
3808
|
-
mpInstance._Store.sessionStartDate = null;
|
|
3809
|
-
mpInstance._Store.nullifySession();
|
|
3818
|
+
self.setSessionTimer();
|
|
3819
|
+
(_d = mpInstance._timeOnSiteTimer) === null || _d === void 0 ? void 0 : _d.resetTimer();
|
|
3810
3820
|
}
|
|
3811
3821
|
}
|
|
3812
|
-
(_e = mpInstance._timeOnSiteTimer) === null || _e === void 0 ? void 0 : _e.resetTimer();
|
|
3813
3822
|
};
|
|
3814
3823
|
this.setSessionTimer = function () {
|
|
3815
3824
|
var sessionTimeoutInMilliseconds = mpInstance._Store.SDKConfig.sessionTimeout * 60000;
|
|
@@ -3842,6 +3851,34 @@ var mParticle = (function () {
|
|
|
3842
3851
|
}
|
|
3843
3852
|
}
|
|
3844
3853
|
};
|
|
3854
|
+
/**
|
|
3855
|
+
* Checks if the session has expired based on the last event timestamp
|
|
3856
|
+
* @param lastEventTimestamp - Unix timestamp in milliseconds of the last event
|
|
3857
|
+
* @param sessionTimeout - Session timeout in minutes
|
|
3858
|
+
* @returns true if the session has expired, false otherwise
|
|
3859
|
+
*/
|
|
3860
|
+
function hasSessionTimedOut(lastEventTimestamp, sessionTimeout) {
|
|
3861
|
+
if (!lastEventTimestamp || !sessionTimeout || sessionTimeout <= 0) {
|
|
3862
|
+
return false;
|
|
3863
|
+
}
|
|
3864
|
+
var sessionTimeoutInMilliseconds = sessionTimeout * 60000;
|
|
3865
|
+
var timeSinceLastEvent = Date.now() - lastEventTimestamp;
|
|
3866
|
+
return timeSinceLastEvent >= sessionTimeoutInMilliseconds;
|
|
3867
|
+
}
|
|
3868
|
+
/**
|
|
3869
|
+
* Performs session end operations:
|
|
3870
|
+
* - Logs a SessionEnd event
|
|
3871
|
+
* - Nullifies the session ID and related data
|
|
3872
|
+
* - Resets the time-on-site timer
|
|
3873
|
+
*/
|
|
3874
|
+
function performSessionEnd() {
|
|
3875
|
+
var _a;
|
|
3876
|
+
mpInstance._Events.logEvent({
|
|
3877
|
+
messageType: Types.MessageType.SessionEnd
|
|
3878
|
+
});
|
|
3879
|
+
mpInstance._Store.nullifySession();
|
|
3880
|
+
(_a = mpInstance._timeOnSiteTimer) === null || _a === void 0 ? void 0 : _a.resetTimer();
|
|
3881
|
+
}
|
|
3845
3882
|
}
|
|
3846
3883
|
|
|
3847
3884
|
var Messages$5 = Constants.Messages;
|
|
@@ -4702,6 +4739,7 @@ var mParticle = (function () {
|
|
|
4702
4739
|
this.nullifySession = function () {
|
|
4703
4740
|
_this.sessionId = null;
|
|
4704
4741
|
_this.dateLastEventSent = null;
|
|
4742
|
+
_this.sessionStartDate = null;
|
|
4705
4743
|
_this.sessionAttributes = {};
|
|
4706
4744
|
_this.localSessionAttributes = {};
|
|
4707
4745
|
mpInstance._Persistence.update();
|
|
@@ -7362,7 +7400,8 @@ var mParticle = (function () {
|
|
|
7362
7400
|
DestinationMpid: aliasRequest.destinationMpid,
|
|
7363
7401
|
SourceMpid: aliasRequest.sourceMpid,
|
|
7364
7402
|
StartUnixtimeMs: aliasRequest.startTime,
|
|
7365
|
-
EndUnixtimeMs: aliasRequest.endTime
|
|
7403
|
+
EndUnixtimeMs: aliasRequest.endTime,
|
|
7404
|
+
Scope: aliasRequest.scope
|
|
7366
7405
|
};
|
|
7367
7406
|
},
|
|
7368
7407
|
convertToNative: function convertToNative(identityApiData) {
|
|
@@ -7662,7 +7701,7 @@ var mParticle = (function () {
|
|
|
7662
7701
|
after applying this adjustment it will be impossible to create an aliasRequest passes the aliasUsers()
|
|
7663
7702
|
validation that the startTime must be less than the endTime
|
|
7664
7703
|
*/
|
|
7665
|
-
createAliasRequest: function createAliasRequest(sourceUser, destinationUser) {
|
|
7704
|
+
createAliasRequest: function createAliasRequest(sourceUser, destinationUser, scope) {
|
|
7666
7705
|
try {
|
|
7667
7706
|
if (!destinationUser || !sourceUser) {
|
|
7668
7707
|
mpInstance.Logger.error("'destinationUser' and 'sourceUser' must both be present");
|
|
@@ -7689,7 +7728,8 @@ var mParticle = (function () {
|
|
|
7689
7728
|
destinationMpid: destinationUser.getMPID(),
|
|
7690
7729
|
sourceMpid: sourceUser.getMPID(),
|
|
7691
7730
|
startTime: startTime,
|
|
7692
|
-
endTime: endTime
|
|
7731
|
+
endTime: endTime,
|
|
7732
|
+
scope: scope || 'device'
|
|
7693
7733
|
};
|
|
7694
7734
|
} catch (e) {
|
|
7695
7735
|
mpInstance.Logger.error('There was a problem with creating an alias request: ' + e);
|
|
@@ -9790,17 +9830,73 @@ var mParticle = (function () {
|
|
|
9790
9830
|
});
|
|
9791
9831
|
});
|
|
9792
9832
|
};
|
|
9793
|
-
|
|
9833
|
+
/**
|
|
9834
|
+
* Hashes attributes and returns both original and hashed versions
|
|
9835
|
+
* with Rokt-compatible key names (like emailsha256, mobilesha256)
|
|
9836
|
+
*
|
|
9837
|
+
*
|
|
9838
|
+
* @param {IRoktPartnerAttributes} attributes - Attributes to hash
|
|
9839
|
+
* @returns {Promise<IRoktPartnerAttributes>} Object with both original and hashed attributes
|
|
9840
|
+
*
|
|
9841
|
+
*/
|
|
9794
9842
|
RoktManager.prototype.hashAttributes = function (attributes) {
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
|
|
9801
|
-
|
|
9802
|
-
|
|
9843
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
9844
|
+
var keys, hashPromises, results, hashedAttributes, _i, results_1, _a, key, attributeValue, hashedValue, error_3, errorMessage;
|
|
9845
|
+
var _this = this;
|
|
9846
|
+
return __generator(this, function (_b) {
|
|
9847
|
+
switch (_b.label) {
|
|
9848
|
+
case 0:
|
|
9849
|
+
_b.trys.push([0, 2,, 3]);
|
|
9850
|
+
if (!attributes || _typeof$1(attributes) !== 'object') {
|
|
9851
|
+
return [2 /*return*/, {}];
|
|
9852
|
+
}
|
|
9853
|
+
keys = Object.keys(attributes);
|
|
9854
|
+
if (keys.length === 0) {
|
|
9855
|
+
return [2 /*return*/, {}];
|
|
9856
|
+
}
|
|
9857
|
+
hashPromises = keys.map(function (key) {
|
|
9858
|
+
return __awaiter(_this, void 0, void 0, function () {
|
|
9859
|
+
var attributeValue, hashedValue;
|
|
9860
|
+
return __generator(this, function (_a) {
|
|
9861
|
+
switch (_a.label) {
|
|
9862
|
+
case 0:
|
|
9863
|
+
attributeValue = attributes[key];
|
|
9864
|
+
return [4 /*yield*/, this.hashSha256(attributeValue)];
|
|
9865
|
+
case 1:
|
|
9866
|
+
hashedValue = _a.sent();
|
|
9867
|
+
return [2 /*return*/, {
|
|
9868
|
+
key: key,
|
|
9869
|
+
attributeValue: attributeValue,
|
|
9870
|
+
hashedValue: hashedValue
|
|
9871
|
+
}];
|
|
9872
|
+
}
|
|
9873
|
+
});
|
|
9874
|
+
});
|
|
9875
|
+
});
|
|
9876
|
+
return [4 /*yield*/, Promise.all(hashPromises)];
|
|
9877
|
+
case 1:
|
|
9878
|
+
results = _b.sent();
|
|
9879
|
+
hashedAttributes = {};
|
|
9880
|
+
for (_i = 0, results_1 = results; _i < results_1.length; _i++) {
|
|
9881
|
+
_a = results_1[_i], key = _a.key, attributeValue = _a.attributeValue, hashedValue = _a.hashedValue;
|
|
9882
|
+
hashedAttributes[key] = attributeValue;
|
|
9883
|
+
if (hashedValue) {
|
|
9884
|
+
hashedAttributes["".concat(key, "sha256")] = hashedValue;
|
|
9885
|
+
}
|
|
9886
|
+
}
|
|
9887
|
+
return [2 /*return*/, hashedAttributes];
|
|
9888
|
+
case 2:
|
|
9889
|
+
error_3 = _b.sent();
|
|
9890
|
+
errorMessage = error_3 instanceof Error ? error_3.message : String(error_3);
|
|
9891
|
+
this.logger.error("Failed to hashAttributes, returning an empty object: ".concat(errorMessage));
|
|
9892
|
+
return [2 /*return*/, {}];
|
|
9893
|
+
case 3:
|
|
9894
|
+
return [2 /*return*/];
|
|
9895
|
+
}
|
|
9896
|
+
});
|
|
9897
|
+
});
|
|
9803
9898
|
};
|
|
9899
|
+
|
|
9804
9900
|
RoktManager.prototype.setExtensionData = function (extensionData) {
|
|
9805
9901
|
if (!this.isReady()) {
|
|
9806
9902
|
this.deferredCall('setExtensionData', extensionData);
|
|
@@ -9823,6 +9919,42 @@ var mParticle = (function () {
|
|
|
9823
9919
|
return Promise.reject(error instanceof Error ? error : new Error('Error using extension: ' + name));
|
|
9824
9920
|
}
|
|
9825
9921
|
};
|
|
9922
|
+
/**
|
|
9923
|
+
* Hashes an attribute using SHA-256
|
|
9924
|
+
*
|
|
9925
|
+
* @param {string | number | boolean | undefined | null} attribute - The value to hash
|
|
9926
|
+
* @returns {Promise<string | undefined | null>} SHA-256 hashed value or undefined/null
|
|
9927
|
+
*
|
|
9928
|
+
*/
|
|
9929
|
+
RoktManager.prototype.hashSha256 = function (attribute) {
|
|
9930
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
9931
|
+
var normalizedValue, error_4, errorMessage;
|
|
9932
|
+
return __generator(this, function (_a) {
|
|
9933
|
+
switch (_a.label) {
|
|
9934
|
+
case 0:
|
|
9935
|
+
if (attribute === null || attribute === undefined) {
|
|
9936
|
+
this.logger.warning("hashSha256 received null/undefined as input");
|
|
9937
|
+
return [2 /*return*/, attribute];
|
|
9938
|
+
}
|
|
9939
|
+
_a.label = 1;
|
|
9940
|
+
case 1:
|
|
9941
|
+
_a.trys.push([1, 3,, 4]);
|
|
9942
|
+
normalizedValue = String(attribute).trim().toLocaleLowerCase();
|
|
9943
|
+
return [4 /*yield*/, this.sha256Hex(normalizedValue)];
|
|
9944
|
+
case 2:
|
|
9945
|
+
return [2 /*return*/, _a.sent()];
|
|
9946
|
+
case 3:
|
|
9947
|
+
error_4 = _a.sent();
|
|
9948
|
+
errorMessage = error_4 instanceof Error ? error_4.message : String(error_4);
|
|
9949
|
+
this.logger.error("Failed to hashSha256, returning undefined: ".concat(errorMessage));
|
|
9950
|
+
return [2 /*return*/, undefined];
|
|
9951
|
+
case 4:
|
|
9952
|
+
return [2 /*return*/];
|
|
9953
|
+
}
|
|
9954
|
+
});
|
|
9955
|
+
});
|
|
9956
|
+
};
|
|
9957
|
+
|
|
9826
9958
|
RoktManager.prototype.getLocalSessionAttributes = function () {
|
|
9827
9959
|
return this.store.getLocalSessionAttributes();
|
|
9828
9960
|
};
|
|
@@ -9918,6 +10050,45 @@ var mParticle = (function () {
|
|
|
9918
10050
|
}
|
|
9919
10051
|
this.messageQueue["delete"](messageId);
|
|
9920
10052
|
};
|
|
10053
|
+
/**
|
|
10054
|
+
* Hashes a string input using SHA-256 and returns the hex digest
|
|
10055
|
+
* Uses the Web Crypto API for secure hashing
|
|
10056
|
+
*
|
|
10057
|
+
* @param {string} input - The string to hash
|
|
10058
|
+
* @returns {Promise<string>} The SHA-256 hash as a hexadecimal string
|
|
10059
|
+
*/
|
|
10060
|
+
RoktManager.prototype.sha256Hex = function (input) {
|
|
10061
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
10062
|
+
var encoder, encodedInput, digest;
|
|
10063
|
+
return __generator(this, function (_a) {
|
|
10064
|
+
switch (_a.label) {
|
|
10065
|
+
case 0:
|
|
10066
|
+
encoder = new TextEncoder();
|
|
10067
|
+
encodedInput = encoder.encode(input);
|
|
10068
|
+
return [4 /*yield*/, crypto.subtle.digest('SHA-256', encodedInput)];
|
|
10069
|
+
case 1:
|
|
10070
|
+
digest = _a.sent();
|
|
10071
|
+
return [2 /*return*/, this.arrayBufferToHex(digest)];
|
|
10072
|
+
}
|
|
10073
|
+
});
|
|
10074
|
+
});
|
|
10075
|
+
};
|
|
10076
|
+
/**
|
|
10077
|
+
* Converts an ArrayBuffer to a hexadecimal string representation
|
|
10078
|
+
* Each byte is converted to a 2-character hex string with leading zeros
|
|
10079
|
+
*
|
|
10080
|
+
* @param {ArrayBuffer} buffer - The buffer to convert
|
|
10081
|
+
* @returns {string} The hexadecimal string representation
|
|
10082
|
+
*/
|
|
10083
|
+
RoktManager.prototype.arrayBufferToHex = function (buffer) {
|
|
10084
|
+
var bytes = new Uint8Array(buffer);
|
|
10085
|
+
var hexString = '';
|
|
10086
|
+
for (var i = 0; i < bytes.length; i++) {
|
|
10087
|
+
var hexByte = bytes[i].toString(16).padStart(2, '0');
|
|
10088
|
+
hexString += hexByte;
|
|
10089
|
+
}
|
|
10090
|
+
return hexString;
|
|
10091
|
+
};
|
|
9921
10092
|
/**
|
|
9922
10093
|
* Checks if an identity value has changed by comparing current and new values
|
|
9923
10094
|
*
|
|
@@ -11467,8 +11638,8 @@ var mParticle = (function () {
|
|
|
11467
11638
|
aliasUsers: function aliasUsers(aliasRequest, callback) {
|
|
11468
11639
|
self.getInstance().Identity.aliasUsers(aliasRequest, callback);
|
|
11469
11640
|
},
|
|
11470
|
-
createAliasRequest: function createAliasRequest(sourceUser, destinationUser) {
|
|
11471
|
-
return self.getInstance().Identity.createAliasRequest(sourceUser, destinationUser);
|
|
11641
|
+
createAliasRequest: function createAliasRequest(sourceUser, destinationUser, scope) {
|
|
11642
|
+
return self.getInstance().Identity.createAliasRequest(sourceUser, destinationUser, scope);
|
|
11472
11643
|
},
|
|
11473
11644
|
getCurrentUser: function getCurrentUser() {
|
|
11474
11645
|
return self.getInstance().Identity.getCurrentUser();
|
package/package.json
CHANGED
package/src/cookieSyncManager.ts
CHANGED
|
@@ -13,6 +13,16 @@ const { InformationMessages } = Messages;
|
|
|
13
13
|
|
|
14
14
|
export const DAYS_IN_MILLISECONDS = 1000 * 60 * 60 * 24;
|
|
15
15
|
|
|
16
|
+
// Partner module IDs for cookie sync configurations
|
|
17
|
+
export const PARTNER_MODULE_IDS = {
|
|
18
|
+
AdobeEventForwarder: 11,
|
|
19
|
+
DoubleclickDFP: 41,
|
|
20
|
+
AppNexus: 50,
|
|
21
|
+
Lotame: 58,
|
|
22
|
+
TradeDesk: 103,
|
|
23
|
+
VerizonMedia: 155,
|
|
24
|
+
} as const;
|
|
25
|
+
|
|
16
26
|
export type CookieSyncDates = Dictionary<number>;
|
|
17
27
|
|
|
18
28
|
export interface IPixelConfiguration {
|
|
@@ -111,8 +121,12 @@ export default function CookieSyncManager(
|
|
|
111
121
|
return;
|
|
112
122
|
}
|
|
113
123
|
|
|
114
|
-
//
|
|
115
|
-
|
|
124
|
+
// The Trade Desk requires a URL parameter for GDPR enabled users.
|
|
125
|
+
// It is optional but to simplify the code, we add it for all Trade
|
|
126
|
+
// // Desk cookie syncs.
|
|
127
|
+
const domain = moduleId === PARTNER_MODULE_IDS.TradeDesk ? window.location.hostname : undefined;
|
|
128
|
+
// Add domain parameter for Trade Desk
|
|
129
|
+
const fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain);
|
|
116
130
|
|
|
117
131
|
self.performCookieSync(
|
|
118
132
|
fullUrl,
|
|
@@ -107,12 +107,14 @@ export interface IIdentityRequest {
|
|
|
107
107
|
): IdentityPreProcessResult;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
export type AliasRequestScope = 'device' | 'mpid';
|
|
111
|
+
|
|
110
112
|
export interface IAliasRequest {
|
|
111
113
|
destinationMpid: MPID;
|
|
112
114
|
sourceMpid: MPID;
|
|
113
115
|
startTime: number;
|
|
114
116
|
endTime: number;
|
|
115
|
-
scope?:
|
|
117
|
+
scope?: AliasRequestScope;
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
export interface IAliasCallback {
|
|
@@ -151,7 +153,8 @@ export interface SDKIdentityApi {
|
|
|
151
153
|
): void;
|
|
152
154
|
createAliasRequest?(
|
|
153
155
|
sourceUser: IMParticleUser,
|
|
154
|
-
destinationUser: IMParticleUser
|
|
156
|
+
destinationUser: IMParticleUser,
|
|
157
|
+
scope?: AliasRequestScope
|
|
155
158
|
): IAliasRequest;
|
|
156
159
|
}
|
|
157
160
|
|
package/src/identity.js
CHANGED
|
@@ -195,6 +195,7 @@ export default function Identity(mpInstance) {
|
|
|
195
195
|
SourceMpid: aliasRequest.sourceMpid,
|
|
196
196
|
StartUnixtimeMs: aliasRequest.startTime,
|
|
197
197
|
EndUnixtimeMs: aliasRequest.endTime,
|
|
198
|
+
Scope: aliasRequest.scope,
|
|
198
199
|
};
|
|
199
200
|
},
|
|
200
201
|
|
|
@@ -744,7 +745,7 @@ export default function Identity(mpInstance) {
|
|
|
744
745
|
after applying this adjustment it will be impossible to create an aliasRequest passes the aliasUsers()
|
|
745
746
|
validation that the startTime must be less than the endTime
|
|
746
747
|
*/
|
|
747
|
-
createAliasRequest: function(sourceUser, destinationUser) {
|
|
748
|
+
createAliasRequest: function(sourceUser, destinationUser, scope) {
|
|
748
749
|
try {
|
|
749
750
|
if (!destinationUser || !sourceUser) {
|
|
750
751
|
mpInstance.Logger.error(
|
|
@@ -788,6 +789,7 @@ export default function Identity(mpInstance) {
|
|
|
788
789
|
sourceMpid: sourceUser.getMPID(),
|
|
789
790
|
startTime: startTime,
|
|
790
791
|
endTime: endTime,
|
|
792
|
+
scope: scope || 'device',
|
|
791
793
|
};
|
|
792
794
|
} catch (e) {
|
|
793
795
|
mpInstance.Logger.error(
|
|
@@ -368,10 +368,10 @@ function mParticleInstanceManager(this: IMParticleInstanceManager) {
|
|
|
368
368
|
aliasUsers: function(aliasRequest, callback) {
|
|
369
369
|
self.getInstance().Identity.aliasUsers(aliasRequest, callback);
|
|
370
370
|
},
|
|
371
|
-
createAliasRequest: function(sourceUser, destinationUser) {
|
|
371
|
+
createAliasRequest: function(sourceUser, destinationUser, scope) {
|
|
372
372
|
return self
|
|
373
373
|
.getInstance()
|
|
374
|
-
.Identity.createAliasRequest(sourceUser, destinationUser);
|
|
374
|
+
.Identity.createAliasRequest(sourceUser, destinationUser, scope);
|
|
375
375
|
},
|
|
376
376
|
getCurrentUser: function() {
|
|
377
377
|
return self.getInstance().Identity.getCurrentUser();
|
package/src/roktManager.ts
CHANGED
|
@@ -252,15 +252,51 @@ export default class RoktManager {
|
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
255
|
+
/**
|
|
256
|
+
* Hashes attributes and returns both original and hashed versions
|
|
257
|
+
* with Rokt-compatible key names (like emailsha256, mobilesha256)
|
|
258
|
+
*
|
|
259
|
+
*
|
|
260
|
+
* @param {IRoktPartnerAttributes} attributes - Attributes to hash
|
|
261
|
+
* @returns {Promise<IRoktPartnerAttributes>} Object with both original and hashed attributes
|
|
262
|
+
*
|
|
263
|
+
*/
|
|
264
|
+
public async hashAttributes(attributes: IRoktPartnerAttributes): Promise<IRoktPartnerAttributes> {
|
|
260
265
|
try {
|
|
261
|
-
|
|
266
|
+
if (!attributes || typeof attributes !== 'object') {
|
|
267
|
+
return {};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Get own property keys only
|
|
271
|
+
const keys = Object.keys(attributes);
|
|
272
|
+
|
|
273
|
+
if (keys.length === 0) {
|
|
274
|
+
return {};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Hash all attributes in parallel
|
|
278
|
+
const hashPromises = keys.map(async (key) => {
|
|
279
|
+
const attributeValue = attributes[key];
|
|
280
|
+
const hashedValue = await this.hashSha256(attributeValue);
|
|
281
|
+
return { key, attributeValue, hashedValue };
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const results = await Promise.all(hashPromises);
|
|
285
|
+
|
|
286
|
+
// Build the result object
|
|
287
|
+
const hashedAttributes: IRoktPartnerAttributes = {};
|
|
288
|
+
for (const { key, attributeValue, hashedValue } of results) {
|
|
289
|
+
hashedAttributes[key] = attributeValue;
|
|
290
|
+
if (hashedValue) {
|
|
291
|
+
hashedAttributes[`${key}sha256`] = hashedValue;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return hashedAttributes;
|
|
295
|
+
|
|
262
296
|
} catch (error) {
|
|
263
|
-
|
|
297
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
298
|
+
this.logger.error(`Failed to hashAttributes, returning an empty object: ${errorMessage}`);
|
|
299
|
+
return {};
|
|
264
300
|
}
|
|
265
301
|
}
|
|
266
302
|
|
|
@@ -290,6 +326,29 @@ export default class RoktManager {
|
|
|
290
326
|
}
|
|
291
327
|
}
|
|
292
328
|
|
|
329
|
+
/**
|
|
330
|
+
* Hashes an attribute using SHA-256
|
|
331
|
+
*
|
|
332
|
+
* @param {string | number | boolean | undefined | null} attribute - The value to hash
|
|
333
|
+
* @returns {Promise<string | undefined | null>} SHA-256 hashed value or undefined/null
|
|
334
|
+
*
|
|
335
|
+
*/
|
|
336
|
+
public async hashSha256(attribute: string | number | boolean | undefined | null): Promise<string | undefined | null> {
|
|
337
|
+
if (attribute === null || attribute === undefined) {
|
|
338
|
+
this.logger.warning(`hashSha256 received null/undefined as input`);
|
|
339
|
+
return attribute as null | undefined;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
try {
|
|
343
|
+
const normalizedValue = String(attribute).trim().toLocaleLowerCase();
|
|
344
|
+
return await this.sha256Hex(normalizedValue);
|
|
345
|
+
} catch (error) {
|
|
346
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
347
|
+
this.logger.error(`Failed to hashSha256, returning undefined: ${errorMessage}`);
|
|
348
|
+
return undefined;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
293
352
|
public getLocalSessionAttributes(): LocalSessionAttributes {
|
|
294
353
|
return this.store.getLocalSessionAttributes();
|
|
295
354
|
}
|
|
@@ -400,6 +459,37 @@ export default class RoktManager {
|
|
|
400
459
|
this.messageQueue.delete(messageId);
|
|
401
460
|
}
|
|
402
461
|
|
|
462
|
+
/**
|
|
463
|
+
* Hashes a string input using SHA-256 and returns the hex digest
|
|
464
|
+
* Uses the Web Crypto API for secure hashing
|
|
465
|
+
*
|
|
466
|
+
* @param {string} input - The string to hash
|
|
467
|
+
* @returns {Promise<string>} The SHA-256 hash as a hexadecimal string
|
|
468
|
+
*/
|
|
469
|
+
private async sha256Hex(input: string): Promise<string> {
|
|
470
|
+
const encoder = new TextEncoder();
|
|
471
|
+
const encodedInput = encoder.encode(input);
|
|
472
|
+
const digest = await crypto.subtle.digest('SHA-256', encodedInput);
|
|
473
|
+
return this.arrayBufferToHex(digest);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Converts an ArrayBuffer to a hexadecimal string representation
|
|
478
|
+
* Each byte is converted to a 2-character hex string with leading zeros
|
|
479
|
+
*
|
|
480
|
+
* @param {ArrayBuffer} buffer - The buffer to convert
|
|
481
|
+
* @returns {string} The hexadecimal string representation
|
|
482
|
+
*/
|
|
483
|
+
private arrayBufferToHex(buffer: ArrayBuffer): string {
|
|
484
|
+
const bytes = new Uint8Array(buffer);
|
|
485
|
+
let hexString = '';
|
|
486
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
487
|
+
const hexByte = bytes[i].toString(16).padStart(2, '0');
|
|
488
|
+
hexString += hexByte;
|
|
489
|
+
}
|
|
490
|
+
return hexString;
|
|
491
|
+
}
|
|
492
|
+
|
|
403
493
|
/**
|
|
404
494
|
* Checks if an identity value has changed by comparing current and new values
|
|
405
495
|
*
|