feat: send the mParticle device id as a selectPlacements attribute - #121
Merged
Conversation
The kit already sends mparticle_session_id, but the session id is short-lived: core mints a new one after sessionTimeout (30 minutes by default), when another tab starts a session, and on an explicit endSession(). That makes it a poor key for anything that needs to span a visit. The device application stamp (das, exposed as mParticle.getDeviceId()) is strictly stickier. nullifySession() clears the session id and its dates but never deviceId, and that is the function called on timeout, cross-tab rotation and endSession(). It also survives login/logout — the identity flows only read _Store.deviceId — and persists in localStorage/cookie for cookieExpiration days (365 by default). Send it as the mparticle_device_id attribute on each selectPlacements call. Reading it per call rather than pinning it at launcher creation means a partner's setDeviceId() reassignment is picked up on the next call. getDeviceId is typed optional on MParticleExtended, so a core that predates it omits the attribute instead of throwing. The attribute is also omitted when the accessor returns nothing, rather than sent as an empty string. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The aliased-reference-plus-.call() pattern was copied from readMpSessionId, where it is load-bearing: that helper picks between getSessionId and getSession, so it needs a local alias and an explicit receiver. readMpDeviceId has a single accessor, so optional chaining does the same job — ?.() still covers a core that predates getDeviceId, and the call keeps its natural mParticle receiver. No behaviour change; the empty-string-to-undefined normalization stays. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
rmi22186
approved these changes
Aug 19, 2026
github-actions Bot
pushed a commit
that referenced
this pull request
Aug 19, 2026
# [1.34.0](v1.33.4...v1.34.0) (2026-08-19) ### Features * send the mParticle device id as a selectPlacements attribute ([#121](#121)) ([bb754ca](bb754ca))
Collaborator
|
🎉 This PR is included in version 1.34.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The kit already sends
mparticle_session_idon everyselectPlacementscall, but the session id is short-lived: core mints a new one aftersessionTimeout(30 minutes by default), when another tab starts a session, and on an explicitendSession(). That makes it a poor key for anything that needs to span a visit.mParticle also carries a device application stamp (
das, exposed publicly asmParticle.getDeviceId()), which is strictly stickier. Verified againstmparticle-web-sdk:config.deviceId→gs.dasin storage → new GUID (persistence.js:135-137,persistence.js:175-178).persistence.js:294). Cookie TTL iscookieExpiration, 365 days by default (constants.ts:118); localStorage has no expiry.nullifySession()clearssessionId,sessionStartDate,dateLastEventSentand session attributes but neverdeviceId(store.ts:699-706) — and that is the function called on timeout, cross-tab rotation, andendSession()(sessionManager.ts:250-256)._Store.deviceIdto send asdevice_application_stamp(identity.js:265, 360, 450); nothing regenerates it.It changes only on explicit
setDeviceId()/config.deviceId,mParticle.reset(), or the user clearing browser storage.This PR sends it as the
mparticle_device_idattribute on eachselectPlacementscall:readMpDeviceId(), which readsmParticle.getDeviceId()per call rather than pinning it at launcher creation, so a partner'ssetDeviceId()reassignment is picked up on the next call.selectPlacementsAttributesnext tomparticle_session_id, omitted entirely when absent or empty rather than sent as an empty string.getDeviceIdas optional on the internalMParticleExtendedinterface, so a core that predates it simply omits the attribute instead of throwing.No public API change:
readMpDeviceIdis private and no new kit setting is introduced.Known caveat
Under
noFunctionalconsent,setCookieandsetLocalStoragebail early (persistence.js:234, 407), so nothing persists and the device id regenerates per page load. The session id isn't persisted in that mode either, so the device id is never less sticky than what we already send.Open question for review
The attribute is named
mparticle_device_idto match the public accessor (getDeviceId()) and to read naturally besidemparticle_session_id. mParticle's own canonical wire name isdevice_application_stamp/das. If the ingestion contract expects that spelling, it's a one-line change to theMPARTICLE_DEVICE_ID_KEYconstant.Screenshot
Testing Plan
npm test— 311/311 pass (307 existing + 4 new).npm run lintclean.npm run buildsucceeds.error TSdiagnostics fromvite-plugin-dts. These are pre-existing (IMParticleUsermissinggetMPID/getUserIdentities); diffed against a baseline build of the branch point, the set is identical with only line numbers shifted.selectPlacementscalls — the core claim of this PR;getDeviceIdis unavailable;getDeviceIdreturns nothing.toEqualassertions updated, since the attribute is now present on every call.getDeviceIdadded to the mParticle mocks intest/vitest.setup.tsand the#selectPlacementsbeforeEach, so tests that delete it don't leak into later ones.dist/is intentionally not included — the release workflow regenerates the bundle after merge.mparticle_device_idarrives across a session timeout and across a logout/login, and that it differs between two browser profiles.🤖 Generated with Claude Code