Skip to content

Commit 7344b53

Browse files
authored
Merge branch 'development' into feat/SDKE-786-log-custom-event-for-selectPlacements
2 parents 72244d3 + 3a43bbe commit 7344b53

11 files changed

Lines changed: 1027 additions & 238 deletions

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
## [2.54.1](https://github.com/mParticle/mparticle-web-sdk/compare/v2.54.0...v2.54.1) (2026-01-26)
2+
3+
4+
### Bug Fixes
5+
6+
* SDKE-846 - User Identity through selectPlacements ([#1146](https://github.com/mParticle/mparticle-web-sdk/issues/1146)) ([60c1ca6](https://github.com/mParticle/mparticle-web-sdk/commit/60c1ca6742e3edb23e9fef4c87d9b4af378eb25f))
7+
8+
# [2.54.0](https://github.com/mParticle/mparticle-web-sdk/compare/v2.53.1...v2.54.0) (2026-01-26)
9+
10+
11+
### Features
12+
13+
* SDKE-852 add joint sdk select placements timestamp ([#1151](https://github.com/mParticle/mparticle-web-sdk/issues/1151)) ([085ab44](https://github.com/mParticle/mparticle-web-sdk/commit/085ab442f5a0c7a2b8a45b0aa83610d1f0ba823c))
14+
115
## [2.53.1](https://github.com/mParticle/mparticle-web-sdk/compare/v2.53.0...v2.53.1) (2026-01-20)
216

317

dist/mparticle.common.js

Lines changed: 13 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/mparticle.esm.js

Lines changed: 13 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/mparticle.js

Lines changed: 72 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ var mParticle = (function () {
203203
Base64: Base64$1
204204
};
205205

206-
var version = "2.53.1";
206+
var version = "2.54.1";
207207

208208
var Constants = {
209209
sdkVersion: version,
@@ -1213,7 +1213,8 @@ var mParticle = (function () {
12131213
AppInit: 1
12141214
};
12151215
var PerformanceMarkType = {
1216-
SdkStart: 'mp:sdkStart'
1216+
SdkStart: 'mp:sdkStart',
1217+
JointSdkSelectPlacements: 'mp:jointSdkSelectPlacements'
12171218
};
12181219
var Types = {
12191220
MessageType: MessageType$1,
@@ -8223,9 +8224,7 @@ var mParticle = (function () {
82238224
mpInstance.Logger.error('Error parsing JSON response from Identity server: ' + e);
82248225
}
82258226
mpInstance._Store.isInitialized = true;
8226-
if (mpInstance._RoktManager.isReady()) {
8227-
mpInstance._RoktManager.currentUser = mpInstance.Identity.getCurrentUser();
8228-
}
8227+
mpInstance._RoktManager.onIdentityComplete();
82298228
mpInstance._preInit.readyQueue = processReadyQueue(mpInstance._preInit.readyQueue);
82308229
};
82318230

@@ -9703,10 +9702,11 @@ var mParticle = (function () {
97039702
* @param {SDKIdentityApi} identityService - The mParticle Identity instance
97049703
* @param {SDKLoggerApi} logger - The mParticle Logger instance
97059704
* @param {IRoktOptions} options - Options for the RoktManager
9705+
* @param {Function} captureTiming - Function to capture performance timing marks
97069706
*
97079707
* @throws Logs error to console if placementAttributesMapping parsing fails
97089708
*/
9709-
RoktManager.prototype.init = function (roktConfig, filteredUser, identityService, store, logger, options) {
9709+
RoktManager.prototype.init = function (roktConfig, filteredUser, identityService, store, logger, options, captureTiming) {
97109710
var _a;
97119711
var _b = roktConfig || {},
97129712
userAttributeFilters = _b.userAttributeFilters,
@@ -9718,6 +9718,7 @@ var mParticle = (function () {
97189718
this.identityService = identityService;
97199719
this.store = store;
97209720
this.logger = logger;
9721+
this.captureTiming = captureTiming;
97219722
this.filters = {
97229723
userAttributeFilters: userAttributeFilters,
97239724
filterUserAttributes: KitFilterHelper.filterUserAttributes,
@@ -9762,31 +9763,34 @@ var mParticle = (function () {
97629763
* });
97639764
*/
97649765
RoktManager.prototype.selectPlacements = function (options) {
9765-
var _a, _b;
9766+
var _a, _b, _c, _d, _e;
97669767
return __awaiter(this, void 0, void 0, function () {
9767-
var attributes, sandboxValue, mappedAttributes, currentUserIdentities_1, currentEmail, newEmail, currentHashedEmail, newHashedEmail, emailChanged, hashedEmailChanged, newIdentities_1, error_1, enrichedAttributes, enrichedOptions, error_2;
9768+
var attributes, sandboxValue, mappedAttributes, currentUserIdentities_1, currentEmail, newEmail, currentHashedEmail, newHashedEmail, isValidHashedEmailIdentityType, emailChanged, hashedEmailChanged, newIdentities_1, error_1, finalUserIdentities, enrichedAttributes, hashedEmail, enrichedOptions, error_2;
97689769
var _this = this;
9769-
return __generator(this, function (_c) {
9770-
switch (_c.label) {
9770+
return __generator(this, function (_f) {
9771+
switch (_f.label) {
97719772
case 0:
9772-
if (!this.isReady()) {
9773+
if (this.captureTiming) {
9774+
this.captureTiming(PerformanceMarkType.JointSdkSelectPlacements);
9775+
}
9776+
// Queue if kit isn't ready OR if identity is in flight
9777+
if (!this.isReady() || ((_a = this.store) === null || _a === void 0 ? void 0 : _a.identityCallInFlight)) {
97739778
return [2 /*return*/, this.deferredCall('selectPlacements', options)];
97749779
}
9775-
_c.label = 1;
9780+
_f.label = 1;
97769781
case 1:
9777-
_c.trys.push([1, 6,, 7]);
9782+
_f.trys.push([1, 6,, 7]);
97789783
attributes = options.attributes;
97799784
sandboxValue = (attributes === null || attributes === void 0 ? void 0 : attributes.sandbox) || null;
97809785
mappedAttributes = this.mapPlacementAttributes(attributes, this.placementAttributesMapping);
9781-
// Get current user identities
97829786
this.currentUser = this.identityService.getCurrentUser();
9783-
currentUserIdentities_1 = ((_b = (_a = this.currentUser) === null || _a === void 0 ? void 0 : _a.getUserIdentities()) === null || _b === void 0 ? void 0 : _b.userIdentities) || {};
9787+
currentUserIdentities_1 = ((_c = (_b = this.currentUser) === null || _b === void 0 ? void 0 : _b.getUserIdentities()) === null || _c === void 0 ? void 0 : _c.userIdentities) || {};
97849788
currentEmail = currentUserIdentities_1.email;
97859789
newEmail = mappedAttributes.email;
97869790
currentHashedEmail = void 0;
97879791
newHashedEmail = void 0;
9788-
// Hashed email identity is valid if it is set to Other-Other10
9789-
if (this.mappedEmailShaIdentityType && IdentityType.getIdentityType(this.mappedEmailShaIdentityType) !== false) {
9792+
isValidHashedEmailIdentityType = this.mappedEmailShaIdentityType && IdentityType.getIdentityType(this.mappedEmailShaIdentityType) !== false;
9793+
if (isValidHashedEmailIdentityType) {
97909794
currentHashedEmail = currentUserIdentities_1[this.mappedEmailShaIdentityType];
97919795
newHashedEmail = mappedAttributes['emailsha256'] || mappedAttributes[this.mappedEmailShaIdentityType] || undefined;
97929796
}
@@ -9804,9 +9808,9 @@ var mParticle = (function () {
98049808
this.logger.warning("emailsha256 mismatch detected. Current mParticle hashedEmail differs from hashedEmail passed to selectPlacements call. Proceeding to call identify with hashedEmail from selectPlacements call. Please verify your implementation.");
98059809
}
98069810
if (!!isEmpty(newIdentities_1)) return [3 /*break*/, 5];
9807-
_c.label = 2;
9811+
_f.label = 2;
98089812
case 2:
9809-
_c.trys.push([2, 4,, 5]);
9813+
_f.trys.push([2, 4,, 5]);
98109814
return [4 /*yield*/, new Promise(function (resolve, reject) {
98119815
_this.identityService.identify({
98129816
userIdentities: __assign(__assign({}, currentUserIdentities_1), newIdentities_1)
@@ -9815,23 +9819,38 @@ var mParticle = (function () {
98159819
});
98169820
})];
98179821
case 3:
9818-
_c.sent();
9822+
_f.sent();
98199823
return [3 /*break*/, 5];
98209824
case 4:
9821-
error_1 = _c.sent();
9825+
error_1 = _f.sent();
98229826
this.logger.error('Failed to identify user with new email: ' + JSON.stringify(error_1));
98239827
return [3 /*break*/, 5];
98249828
case 5:
9829+
// Refresh current user identities to ensure we have the latest values before building enrichedAttributes
9830+
this.currentUser = this.identityService.getCurrentUser();
9831+
finalUserIdentities = ((_e = (_d = this.currentUser) === null || _d === void 0 ? void 0 : _d.getUserIdentities()) === null || _e === void 0 ? void 0 : _e.userIdentities) || {};
98259832
this.setUserAttributes(mappedAttributes);
98269833
enrichedAttributes = __assign(__assign({}, mappedAttributes), sandboxValue !== null ? {
98279834
sandbox: sandboxValue
98289835
} : {});
9836+
// Propagate email from current user identities if not already in attributes
9837+
if (finalUserIdentities.email && !enrichedAttributes.email) {
9838+
enrichedAttributes.email = finalUserIdentities.email;
9839+
}
9840+
// Propagate emailsha256 from current user identities if not already in attributes
9841+
if (isValidHashedEmailIdentityType) {
9842+
hashedEmail = finalUserIdentities[this.mappedEmailShaIdentityType];
9843+
if (hashedEmail && !enrichedAttributes.emailsha256 && !enrichedAttributes[this.mappedEmailShaIdentityType]) {
9844+
enrichedAttributes.emailsha256 = hashedEmail;
9845+
}
9846+
}
9847+
this.filters.filteredUser = this.currentUser || this.filters.filteredUser || null;
98299848
enrichedOptions = __assign(__assign({}, options), {
98309849
attributes: enrichedAttributes
98319850
});
98329851
return [2 /*return*/, this.kit.selectPlacements(enrichedOptions)];
98339852
case 6:
9834-
error_2 = _c.sent();
9853+
error_2 = _f.sent();
98359854
return [2 /*return*/, Promise.reject(error_2 instanceof Error ? error_2 : new Error('Unknown error occurred'))];
98369855
case 7:
98379856
return [2 /*return*/];
@@ -10004,31 +10023,53 @@ var mParticle = (function () {
1000410023
}
1000510024
return mappedAttributes;
1000610025
};
10026+
RoktManager.prototype.onIdentityComplete = function () {
10027+
if (this.isReady()) {
10028+
this.currentUser = this.identityService.getCurrentUser();
10029+
// Process any queued selectPlacements calls that were waiting for identity
10030+
this.processMessageQueue();
10031+
}
10032+
};
1000710033
RoktManager.prototype.processMessageQueue = function () {
1000810034
var _this = this;
1000910035
var _a;
1001010036
if (!this.isReady() || this.messageQueue.size === 0) {
1001110037
return;
1001210038
}
1001310039
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.verbose("RoktManager: Processing ".concat(this.messageQueue.size, " queued messages"));
10014-
this.messageQueue.forEach(function (message) {
10015-
var _a, _b, _c;
10040+
var messagesToProcess = Array.from(this.messageQueue.values());
10041+
// Clear the queue immediately to prevent re-processing
10042+
this.messageQueue.clear();
10043+
messagesToProcess.forEach(function (message) {
10044+
var _a, _b;
1001610045
if (!(message.methodName in _this) || !isFunction(_this[message.methodName])) {
1001710046
(_a = _this.logger) === null || _a === void 0 ? void 0 : _a.error("RoktManager: Method ".concat(message.methodName, " not found"));
1001810047
return;
1001910048
}
1002010049
(_b = _this.logger) === null || _b === void 0 ? void 0 : _b.verbose("RoktManager: Processing queued message: ".concat(message.methodName, " with payload: ").concat(JSON.stringify(message.payload)));
10050+
// Capture resolve/reject functions before async processing
10051+
var resolve = message.resolve;
10052+
var reject = message.reject;
10053+
var handleError = function handleError(error) {
10054+
var _a;
10055+
var errorMessage = error instanceof Error ? error.message : String(error);
10056+
(_a = _this.logger) === null || _a === void 0 ? void 0 : _a.error("RoktManager: Error processing message '".concat(message.methodName, "': ").concat(errorMessage));
10057+
if (reject) {
10058+
reject(error);
10059+
}
10060+
};
1002110061
try {
1002210062
var result = _this[message.methodName](message.payload);
10023-
_this.completePendingPromise(message.messageId, result);
10063+
// Handle both sync and async methods
10064+
Promise.resolve(result).then(function (resolvedResult) {
10065+
if (resolve) {
10066+
resolve(resolvedResult);
10067+
}
10068+
})["catch"](handleError);
1002410069
} catch (error) {
10025-
var errorMessage = error instanceof Error ? error.message : String(error);
10026-
(_c = _this.logger) === null || _c === void 0 ? void 0 : _c.error("RoktManager: Error processing message '".concat(message.methodName, "': ").concat(errorMessage));
10027-
_this.completePendingPromise(message.messageId, Promise.reject(error));
10070+
handleError(error);
1002810071
}
1002910072
});
10030-
// Clear the queue after processing all messages
10031-
this.messageQueue.clear();
1003210073
};
1003310074
RoktManager.prototype.queueMessage = function (message) {
1003410075
this.messageQueue.set(message.messageId, message);
@@ -10046,20 +10087,6 @@ var mParticle = (function () {
1004610087
});
1004710088
});
1004810089
};
10049-
RoktManager.prototype.completePendingPromise = function (messageId, resultOrError) {
10050-
if (!messageId || !this.messageQueue.has(messageId)) {
10051-
return;
10052-
}
10053-
var message = this.messageQueue.get(messageId);
10054-
if (message.resolve) {
10055-
Promise.resolve(resultOrError).then(function (result) {
10056-
return message.resolve(result);
10057-
})["catch"](function (error) {
10058-
return message.reject(error);
10059-
});
10060-
}
10061-
this.messageQueue["delete"](messageId);
10062-
};
1006310090
/**
1006410091
* Hashes a string input using SHA-256 and returns the hex digest
1006510092
* Uses the Web Crypto API for secure hashing
@@ -11149,7 +11176,7 @@ var mParticle = (function () {
1114911176
domain: config === null || config === void 0 ? void 0 : config.domain
1115011177
};
1115111178
// https://go.mparticle.com/work/SQDSDKS-7339
11152-
mpInstance._RoktManager.init(roktConfig, roktFilteredUser, mpInstance.Identity, mpInstance._Store, mpInstance.Logger, roktOptions);
11179+
mpInstance._RoktManager.init(roktConfig, roktFilteredUser, mpInstance.Identity, mpInstance._Store, mpInstance.Logger, roktOptions, mpInstance.captureTiming);
1115311180
}
1115411181
mpInstance._Forwarders.processForwarders(config, mpInstance._APIClient.prepareForwardingStats);
1115511182
mpInstance._Forwarders.processPixelConfigs(config);

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@mparticle/web-sdk",
3-
"version": "2.53.1",
3+
"version": "2.54.1",
44
"description": "mParticle core SDK for web applications",
55
"license": "Apache-2.0",
66
"keywords": [

src/identity.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,7 +1372,6 @@ export default function Identity(mpInstance) {
13721372
: {};
13731373
let mpidIsNotInCookies;
13741374
let identityApiResult;
1375-
13761375
let newUser;
13771376
let newIdentitiesByType = {};
13781377

@@ -1577,9 +1576,7 @@ export default function Identity(mpInstance) {
15771576
}
15781577
mpInstance._Store.isInitialized = true;
15791578

1580-
if (mpInstance._RoktManager.isReady()) {
1581-
mpInstance._RoktManager.currentUser = mpInstance.Identity.getCurrentUser();
1582-
}
1579+
mpInstance._RoktManager.onIdentityComplete();
15831580

15841581
mpInstance._preInit.readyQueue = processReadyQueue(
15851582
mpInstance._preInit.readyQueue

src/mp-instance.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1438,7 +1438,8 @@ function completeSDKInitialization(apiKey, config, mpInstance) {
14381438
mpInstance.Identity,
14391439
mpInstance._Store,
14401440
mpInstance.Logger,
1441-
roktOptions
1441+
roktOptions,
1442+
mpInstance.captureTiming
14421443
);
14431444
}
14441445

0 commit comments

Comments
 (0)