@rudderstack/analytics-js 3.25.1 → 3.26.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.
@@ -519,7 +519,7 @@ error.stack=`${stack}\n${MANUAL_ERROR_IDENTIFIER}`;break;case stacktrace:// esli
519
519
  error.stacktrace=`${stacktrace}\n${MANUAL_ERROR_IDENTIFIER}`;break;case operaSourceloc:default:// eslint-disable-next-line no-param-reassign
520
520
  error['opera#sourceloc']=`${operaSourceloc}\n${MANUAL_ERROR_IDENTIFIER}`;break;}}}globalThis.dispatchEvent(new ErrorEvent('error',{error,bubbles:true,cancelable:true,composed:true}));};
521
521
 
522
- const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.25.1';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
522
+ const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.26.0';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
523
523
 
524
524
  const QUERY_PARAM_TRAIT_PREFIX='ajs_trait_';const QUERY_PARAM_PROPERTY_PREFIX='ajs_prop_';const QUERY_PARAM_ANONYMOUS_ID_KEY='ajs_aid';const QUERY_PARAM_USER_ID_KEY='ajs_uid';const QUERY_PARAM_TRACK_EVENT_NAME_KEY='ajs_event';
525
525
 
@@ -547,8 +547,9 @@ data[dataKey]=params.get(key);}});return data;};/**
547
547
  * Parse query string into preload buffer events & push into existing array before any other events
548
548
  */const retrieveEventsFromQueryString=(argumentsArray=[])=>{// Mapping for trait and properties values based on key prefix
549
549
  const eventArgumentToQueryParamMap={trait:QUERY_PARAM_TRAIT_PREFIX,properties:QUERY_PARAM_PROPERTY_PREFIX};const queryObject=new URLSearchParams(globalThis.location.search);// Add track events with name and properties
550
- if(queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY)){argumentsArray.unshift(['track',queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.properties)]);}// Set userId and user traits
551
- if(queryObject.get(QUERY_PARAM_USER_ID_KEY)){argumentsArray.unshift(['identify',queryObject.get(QUERY_PARAM_USER_ID_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.trait)]);}// Set anonymousID
550
+ if(queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY)){argumentsArray.unshift(['track',queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.properties)]);}// Send identify event
551
+ const userId=queryObject.get(QUERY_PARAM_USER_ID_KEY);const userTraits=getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.trait);if(userId||isNonEmptyObject(userTraits)){// In identify API, user ID is optional
552
+ const identifyApiArgs=[...(userId?[userId]:[]),userTraits];argumentsArray.unshift(['identify',...identifyApiArgs]);}// Set anonymousID
552
553
  if(queryObject.get(QUERY_PARAM_ANONYMOUS_ID_KEY)){argumentsArray.unshift(['setAnonymousId',queryObject.get(QUERY_PARAM_ANONYMOUS_ID_KEY)]);}};/**
553
554
  * Retrieve an existing buffered load method call and remove from the existing array
554
555
  */const getPreloadedLoadEvent=preloadedEventsArray=>{const loadMethodName='load';let loadEvent=[];/**
@@ -3293,7 +3294,9 @@ enrichedEvent.userId=to??enrichedEvent.userId;return enrichedEvent;}/**
3293
3294
  * @param event Incoming event data
3294
3295
  */addEvent(event){this.userSessionManager.refreshSession();const rudderEvent=this.eventFactory.create(event);this.eventRepository.enqueue(rudderEvent,event.callback);}}
3295
3296
 
3296
- class UserSessionManager{constructor(pluginsManager,storeManager,httpClient,errorHandler,logger){this.storeManager=storeManager;this.pluginsManager=pluginsManager;this.logger=logger;this.errorHandler=errorHandler;this.httpClient=httpClient;this.onError=this.onError.bind(this);this.serverSideCookieDebounceFuncs={};}/**
3297
+ class UserSessionManager{/**
3298
+ * Tracks whether a server-side cookie setting request is in progress or not.
3299
+ */constructor(pluginsManager,storeManager,httpClient,errorHandler,logger){this.storeManager=storeManager;this.pluginsManager=pluginsManager;this.logger=logger;this.errorHandler=errorHandler;this.httpClient=httpClient;this.onError=this.onError.bind(this);this.serverSideCookieDebounceFuncs={};this.serverSideCookiesRequestInProgress={};}/**
3297
3300
  * Initialize User session with values from storage
3298
3301
  */init(){this.syncStorageDataToState();// Register the effect to sync with storage
3299
3302
  this.registerEffects();}syncStorageDataToState(){this.migrateStorageIfNeeded();this.migrateDataFromPreviousStorage();// get the values from storage and set it again
@@ -3323,20 +3326,31 @@ cutOffDuration=DEFAULT_SESSION_CUT_OFF_DURATION_MS;}else if(cutOffDuration<sessi
3323
3326
  * @param callback
3324
3327
  */makeRequestToSetCookie(encryptedCookieData,callback){this.httpClient?.getAsyncData({url:state.serverCookies.dataServiceUrl.value,options:{method:'POST',data:stringifyWithoutCircular({reqType:'setCookies',workspaceId:state.source.value?.workspaceId,data:{options:{maxAge:state.storage.cookie.value?.maxage,path:state.storage.cookie.value?.path,domain:state.storage.cookie.value?.domain,sameSite:state.storage.cookie.value?.samesite,secure:state.storage.cookie.value?.secure,expires:state.storage.cookie.value?.expires},cookies:encryptedCookieData}}),sendRawData:true,withCredentials:true},isRawResponse:true,callback});}/**
3325
3328
  * A function to make an external request to set the cookie from server side
3326
- * @param key cookie name
3327
- * @param value encrypted cookie value
3328
- */setServerSideCookies(cookiesData,cb,store){try{// encrypt cookies values
3329
- const encryptedCookieData=this.getEncryptedCookieData(cookiesData,store);if(encryptedCookieData.length>0){// make request to data service to set the cookie from server side
3330
- this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{if(details?.xhr?.status===200){cookiesData.forEach(cData=>{const cookieValue=store?.get(cData.name);const before=stringifyWithoutCircular(cData.value,false,[]);const after=stringifyWithoutCircular(cookieValue,false,[]);if(after!==before){this.logger.error(FAILED_SETTING_COOKIE_FROM_SERVER_ERROR(cData.name));if(cb){cb(cData.name,cData.value);}}});}else {this.logger.error(DATA_SERVER_REQUEST_FAIL_ERROR(details?.xhr?.status));cookiesData.forEach(each=>{if(cb){cb(each.name,each.value);}});}});}}catch(e){this.onError(e,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR);cookiesData.forEach(each=>{if(cb){cb(each.name,each.value);}});}}/**
3329
+ * @param sessionToCookiesMap map of session key to cookie name
3330
+ * @param cb callback function to be called when the cookie is set
3331
+ * @param store store to be used to get the cookie value
3332
+ */setServerSideCookies(sessionToCookiesMap,cb,store){// Retrieve the cookie value from the state
3333
+ const sessionKeys=Object.keys(sessionToCookiesMap);const getCurrentCookieValuesFromState=()=>{return sessionKeys.map(sessionKey=>{return {name:sessionToCookiesMap[sessionKey].name,value:state.session[sessionKey].value};});};// Preserve the current cookie values
3334
+ const originalCookieValues={};sessionKeys.forEach(sessionKey=>{originalCookieValues[sessionToCookiesMap[sessionKey].name]=store?.get(sessionToCookiesMap[sessionKey].name);});const clearInProgressFlags=()=>{sessionKeys.forEach(sessionKey=>{this.serverSideCookiesRequestInProgress[sessionKey]=false;});};const setCookiesClientSide=()=>{getCurrentCookieValuesFromState().forEach(each=>{if(cb){cb(each.name,each.value);}});};try{const expectedCookieValues={};sessionKeys.forEach(sessionKey=>{expectedCookieValues[sessionToCookiesMap[sessionKey].name]=state.session[sessionKey].value;});// encrypt cookies values
3335
+ const encryptedCookieData=this.getEncryptedCookieData(getCurrentCookieValuesFromState(),store);if(encryptedCookieData.length>0){// make request to data service to set the cookie from server side
3336
+ this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{// Mark the cookie req status as done
3337
+ clearInProgressFlags();if(details?.xhr?.status===200){getCurrentCookieValuesFromState().forEach(cData=>{const originalCookieVal=originalCookieValues[cData.name];const currentCookieVal=store?.get(cData.name);// Check if the expected cookie values are set.
3338
+ if(stringifyWithoutCircular(expectedCookieValues[cData.name],false,[])!==stringifyWithoutCircular(currentCookieVal,false,[])){// It's fine if the values don't match as other active SDK sessions might have updated the cookie values
3339
+ // or other cookie requests might have updated the cookie value.
3340
+ // Log an error only when cookie didn't exist previously and currently also doesn't exist.
3341
+ if(isNull(originalCookieVal)&&isNull(currentCookieVal)){this.logger.error(FAILED_SETTING_COOKIE_FROM_SERVER_ERROR(cData.name));}if(cb){cb(cData.name,cData.value);}}});}else {this.logger.error(DATA_SERVER_REQUEST_FAIL_ERROR(details?.xhr?.status));setCookiesClientSide();}});}else {setCookiesClientSide();// Mark the cookie req status as done
3342
+ clearInProgressFlags();}}catch(e){this.onError(e,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR);setCookiesClientSide();// Mark the cookie req status as done
3343
+ clearInProgressFlags();}}/**
3331
3344
  * A function to sync values in storage
3332
3345
  * @param sessionKey
3333
- * @param value
3334
- */syncValueToStorage(sessionKey,value){const entries=state.storage.entries.value;const storageType=entries[sessionKey]?.type;if(isStorageTypeValidForStoringData(storageType)){const curStore=this.storeManager?.getStore(storageClientDataStoreNameMap[storageType]);const key=entries[sessionKey]?.key;if(value&&(isString(value)||isNonEmptyObject(value))){// if useServerSideCookies load option is set to true
3346
+ */syncValueToStorage(sessionKey){const entries=state.storage.entries.value;const storageType=entries[sessionKey]?.type;if(isStorageTypeValidForStoringData(storageType)){const curStore=this.storeManager.getStore(storageClientDataStoreNameMap[storageType]);const cookieName=entries[sessionKey]?.key;const cookieValue=state.session[sessionKey].value;if(cookieValue&&(isString(cookieValue)||isNonEmptyObject(cookieValue))){// if useServerSideCookies load option is set to true
3335
3347
  // set the cookie from server side
3336
- if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){if(this.serverSideCookieDebounceFuncs[sessionKey]){globalThis.clearTimeout(this.serverSideCookieDebounceFuncs[sessionKey]);}this.serverSideCookieDebounceFuncs[sessionKey]=globalThis.setTimeout(()=>{this.setServerSideCookies([{name:key,value}],(cookieName,cookieValue)=>{curStore?.set(cookieName,cookieValue);},curStore);},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {curStore?.set(key,value);}}else {curStore?.remove(key);}}}/**
3348
+ if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){// Mark the requests as in progress.
3349
+ this.serverSideCookiesRequestInProgress[sessionKey]=true;if(this.serverSideCookieDebounceFuncs[sessionKey]){globalThis.clearTimeout(this.serverSideCookieDebounceFuncs[sessionKey]);}this.serverSideCookieDebounceFuncs[sessionKey]=globalThis.setTimeout(()=>{// Create a map of session key to cookie name
3350
+ const sessionToCookiesMap={[sessionKey]:{name:cookieName}};this.setServerSideCookies(sessionToCookiesMap,(cookieName,cookieValue)=>{curStore?.set(cookieName,cookieValue);},curStore);},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {curStore?.set(cookieName,cookieValue);}}else {curStore?.remove(cookieName);}}}/**
3337
3351
  * Function to update storage whenever state value changes
3338
3352
  */registerEffects(){// This will work as long as the user session entry key names are same as the state keys
3339
- USER_SESSION_KEYS.forEach(sessionKey=>{E(()=>{this.syncValueToStorage(sessionKey,state.session[sessionKey].value);});});}/**
3353
+ USER_SESSION_KEYS.forEach(sessionKey=>{E(()=>{this.syncValueToStorage(sessionKey);});});}/**
3340
3354
  * Sets anonymous id in the following precedence:
3341
3355
  *
3342
3356
  * 1. anonymousId: Id directly provided to the function.
@@ -3353,30 +3367,37 @@ const autoCapturedAnonymousId=this.pluginsManager?.invokeSingle('storage.getAnon
3353
3367
  // This is needed for entries that are fetched from the storage
3354
3368
  // during the current session (for example, session info)
3355
3369
  this.migrateStorageIfNeeded([store],[sessionKey]);const storageKey=entries[sessionKey]?.key;return store?.get(storageKey)??null;}return null;}getExternalAnonymousIdByCookieName(key){const storageEngine=getStorageEngine(COOKIE_STORAGE);if(storageEngine?.isEnabled){return storageEngine.getItem(key)??null;}return null;}/**
3370
+ * Fetches the value for a session key. Preferably from storage, if the server-side
3371
+ * cookies request is not in progress. Otherwise, from the state.
3372
+ * @param sessionKey - The session key to fetch the value for
3373
+ * @returns - The value for the session key
3374
+ */getUserSessionValue(sessionKey){// If the server-side cookies request is in progress, fetch the value from the state.
3375
+ if(this.serverSideCookiesRequestInProgress[sessionKey]){return state.session[sessionKey].value;}// Otherwise, fetch the value from storage.
3376
+ return this.getEntryValue(sessionKey);}/**
3356
3377
  * Fetches User Id
3357
3378
  * @returns
3358
- */getUserId(){return this.getEntryValue('userId');}/**
3379
+ */getUserId(){return this.getUserSessionValue('userId');}/**
3359
3380
  * Fetches User Traits
3360
3381
  * @returns
3361
- */getUserTraits(){return this.getEntryValue('userTraits');}/**
3382
+ */getUserTraits(){return this.getUserSessionValue('userTraits');}/**
3362
3383
  * Fetches Group Id
3363
3384
  * @returns
3364
- */getGroupId(){return this.getEntryValue('groupId');}/**
3385
+ */getGroupId(){return this.getUserSessionValue('groupId');}/**
3365
3386
  * Fetches Group Traits
3366
3387
  * @returns
3367
- */getGroupTraits(){return this.getEntryValue('groupTraits');}/**
3388
+ */getGroupTraits(){return this.getUserSessionValue('groupTraits');}/**
3368
3389
  * Fetches Initial Referrer
3369
3390
  * @returns
3370
- */getInitialReferrer(){return this.getEntryValue('initialReferrer');}/**
3391
+ */getInitialReferrer(){return this.getUserSessionValue('initialReferrer');}/**
3371
3392
  * Fetches Initial Referring domain
3372
3393
  * @returns
3373
- */getInitialReferringDomain(){return this.getEntryValue('initialReferringDomain');}/**
3394
+ */getInitialReferringDomain(){return this.getUserSessionValue('initialReferringDomain');}/**
3374
3395
  * Fetches session tracking information from storage
3375
3396
  * @returns
3376
- */getSessionInfo(){return this.getEntryValue('sessionInfo');}/**
3397
+ */getSessionInfo(){return this.getUserSessionValue('sessionInfo');}/**
3377
3398
  * Fetches auth token from storage
3378
3399
  * @returns
3379
- */getAuthToken(){return this.getEntryValue('authToken');}/**
3400
+ */getAuthToken(){return this.getUserSessionValue('authToken');}/**
3380
3401
  * If session is active it returns the sessionId
3381
3402
  * @returns
3382
3403
  */getSessionId(){const sessionInfo=this.getSessionInfo()??DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack&&!hasSessionExpired(sessionInfo)||sessionInfo.manualTrack){return sessionInfo.id??null;}return null;}/**
@@ -3392,7 +3413,7 @@ this.migrateStorageIfNeeded([store],[sessionKey]);const storageKey=entries[sessi
3392
3413
  if(sessionInfo.sessionStart===undefined){sessionInfo={...sessionInfo,sessionStart:true};}else if(sessionInfo.sessionStart){sessionInfo={...sessionInfo,sessionStart:false};}}// Always write to state (in-turn to storage) to keep the session info up to date.
3393
3414
  state.session.sessionInfo.value=sessionInfo;if(state.lifecycle.status.value!=='readyExecuted'){// Force update the storage as the 'effect' blocks are not getting triggered
3394
3415
  // when processing preload buffered requests
3395
- this.syncValueToStorage('sessionInfo',sessionInfo);}}resetAndStartNewSession(){const session=state.session;const{manualTrack,autoTrack,timeout,cutOff}=session.sessionInfo.value;if(autoTrack){const sessionInfo={...DEFAULT_USER_SESSION_VALUES.sessionInfo,timeout};if(cutOff){sessionInfo.cutOff={enabled:cutOff.enabled,duration:cutOff.duration};}session.sessionInfo.value=sessionInfo;this.startOrRenewAutoTracking(session.sessionInfo.value);}else if(manualTrack){this.startManualTrackingInternal();}}/**
3416
+ this.syncValueToStorage('sessionInfo');}}resetAndStartNewSession(){const session=state.session;const{manualTrack,autoTrack,timeout,cutOff}=session.sessionInfo.value;if(autoTrack){const sessionInfo={...DEFAULT_USER_SESSION_VALUES.sessionInfo,timeout};if(cutOff){sessionInfo.cutOff={enabled:cutOff.enabled,duration:cutOff.duration};}session.sessionInfo.value=sessionInfo;this.startOrRenewAutoTracking(session.sessionInfo.value);}else if(manualTrack){this.startManualTrackingInternal();}}/**
3396
3417
  * Reset state values
3397
3418
  * @param options options for reset
3398
3419
  * @returns
@@ -515,7 +515,7 @@ error.stack=`${stack}\n${MANUAL_ERROR_IDENTIFIER}`;break;case stacktrace:// esli
515
515
  error.stacktrace=`${stacktrace}\n${MANUAL_ERROR_IDENTIFIER}`;break;case operaSourceloc:default:// eslint-disable-next-line no-param-reassign
516
516
  error['opera#sourceloc']=`${operaSourceloc}\n${MANUAL_ERROR_IDENTIFIER}`;break;}}}globalThis.dispatchEvent(new ErrorEvent('error',{error,bubbles:true,cancelable:true,composed:true}));};
517
517
 
518
- const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.25.1';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
518
+ const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.26.0';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
519
519
 
520
520
  const QUERY_PARAM_TRAIT_PREFIX='ajs_trait_';const QUERY_PARAM_PROPERTY_PREFIX='ajs_prop_';const QUERY_PARAM_ANONYMOUS_ID_KEY='ajs_aid';const QUERY_PARAM_USER_ID_KEY='ajs_uid';const QUERY_PARAM_TRACK_EVENT_NAME_KEY='ajs_event';
521
521
 
@@ -543,8 +543,9 @@ data[dataKey]=params.get(key);}});return data;};/**
543
543
  * Parse query string into preload buffer events & push into existing array before any other events
544
544
  */const retrieveEventsFromQueryString=(argumentsArray=[])=>{// Mapping for trait and properties values based on key prefix
545
545
  const eventArgumentToQueryParamMap={trait:QUERY_PARAM_TRAIT_PREFIX,properties:QUERY_PARAM_PROPERTY_PREFIX};const queryObject=new URLSearchParams(globalThis.location.search);// Add track events with name and properties
546
- if(queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY)){argumentsArray.unshift(['track',queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.properties)]);}// Set userId and user traits
547
- if(queryObject.get(QUERY_PARAM_USER_ID_KEY)){argumentsArray.unshift(['identify',queryObject.get(QUERY_PARAM_USER_ID_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.trait)]);}// Set anonymousID
546
+ if(queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY)){argumentsArray.unshift(['track',queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.properties)]);}// Send identify event
547
+ const userId=queryObject.get(QUERY_PARAM_USER_ID_KEY);const userTraits=getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.trait);if(userId||isNonEmptyObject(userTraits)){// In identify API, user ID is optional
548
+ const identifyApiArgs=[...(userId?[userId]:[]),userTraits];argumentsArray.unshift(['identify',...identifyApiArgs]);}// Set anonymousID
548
549
  if(queryObject.get(QUERY_PARAM_ANONYMOUS_ID_KEY)){argumentsArray.unshift(['setAnonymousId',queryObject.get(QUERY_PARAM_ANONYMOUS_ID_KEY)]);}};/**
549
550
  * Retrieve an existing buffered load method call and remove from the existing array
550
551
  */const getPreloadedLoadEvent=preloadedEventsArray=>{const loadMethodName='load';let loadEvent=[];/**
@@ -3289,7 +3290,9 @@ enrichedEvent.userId=to??enrichedEvent.userId;return enrichedEvent;}/**
3289
3290
  * @param event Incoming event data
3290
3291
  */addEvent(event){this.userSessionManager.refreshSession();const rudderEvent=this.eventFactory.create(event);this.eventRepository.enqueue(rudderEvent,event.callback);}}
3291
3292
 
3292
- class UserSessionManager{constructor(pluginsManager,storeManager,httpClient,errorHandler,logger){this.storeManager=storeManager;this.pluginsManager=pluginsManager;this.logger=logger;this.errorHandler=errorHandler;this.httpClient=httpClient;this.onError=this.onError.bind(this);this.serverSideCookieDebounceFuncs={};}/**
3293
+ class UserSessionManager{/**
3294
+ * Tracks whether a server-side cookie setting request is in progress or not.
3295
+ */constructor(pluginsManager,storeManager,httpClient,errorHandler,logger){this.storeManager=storeManager;this.pluginsManager=pluginsManager;this.logger=logger;this.errorHandler=errorHandler;this.httpClient=httpClient;this.onError=this.onError.bind(this);this.serverSideCookieDebounceFuncs={};this.serverSideCookiesRequestInProgress={};}/**
3293
3296
  * Initialize User session with values from storage
3294
3297
  */init(){this.syncStorageDataToState();// Register the effect to sync with storage
3295
3298
  this.registerEffects();}syncStorageDataToState(){this.migrateStorageIfNeeded();this.migrateDataFromPreviousStorage();// get the values from storage and set it again
@@ -3319,20 +3322,31 @@ cutOffDuration=DEFAULT_SESSION_CUT_OFF_DURATION_MS;}else if(cutOffDuration<sessi
3319
3322
  * @param callback
3320
3323
  */makeRequestToSetCookie(encryptedCookieData,callback){this.httpClient?.getAsyncData({url:state.serverCookies.dataServiceUrl.value,options:{method:'POST',data:stringifyWithoutCircular({reqType:'setCookies',workspaceId:state.source.value?.workspaceId,data:{options:{maxAge:state.storage.cookie.value?.maxage,path:state.storage.cookie.value?.path,domain:state.storage.cookie.value?.domain,sameSite:state.storage.cookie.value?.samesite,secure:state.storage.cookie.value?.secure,expires:state.storage.cookie.value?.expires},cookies:encryptedCookieData}}),sendRawData:true,withCredentials:true},isRawResponse:true,callback});}/**
3321
3324
  * A function to make an external request to set the cookie from server side
3322
- * @param key cookie name
3323
- * @param value encrypted cookie value
3324
- */setServerSideCookies(cookiesData,cb,store){try{// encrypt cookies values
3325
- const encryptedCookieData=this.getEncryptedCookieData(cookiesData,store);if(encryptedCookieData.length>0){// make request to data service to set the cookie from server side
3326
- this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{if(details?.xhr?.status===200){cookiesData.forEach(cData=>{const cookieValue=store?.get(cData.name);const before=stringifyWithoutCircular(cData.value,false,[]);const after=stringifyWithoutCircular(cookieValue,false,[]);if(after!==before){this.logger.error(FAILED_SETTING_COOKIE_FROM_SERVER_ERROR(cData.name));if(cb){cb(cData.name,cData.value);}}});}else {this.logger.error(DATA_SERVER_REQUEST_FAIL_ERROR(details?.xhr?.status));cookiesData.forEach(each=>{if(cb){cb(each.name,each.value);}});}});}}catch(e){this.onError(e,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR);cookiesData.forEach(each=>{if(cb){cb(each.name,each.value);}});}}/**
3325
+ * @param sessionToCookiesMap map of session key to cookie name
3326
+ * @param cb callback function to be called when the cookie is set
3327
+ * @param store store to be used to get the cookie value
3328
+ */setServerSideCookies(sessionToCookiesMap,cb,store){// Retrieve the cookie value from the state
3329
+ const sessionKeys=Object.keys(sessionToCookiesMap);const getCurrentCookieValuesFromState=()=>{return sessionKeys.map(sessionKey=>{return {name:sessionToCookiesMap[sessionKey].name,value:state.session[sessionKey].value};});};// Preserve the current cookie values
3330
+ const originalCookieValues={};sessionKeys.forEach(sessionKey=>{originalCookieValues[sessionToCookiesMap[sessionKey].name]=store?.get(sessionToCookiesMap[sessionKey].name);});const clearInProgressFlags=()=>{sessionKeys.forEach(sessionKey=>{this.serverSideCookiesRequestInProgress[sessionKey]=false;});};const setCookiesClientSide=()=>{getCurrentCookieValuesFromState().forEach(each=>{if(cb){cb(each.name,each.value);}});};try{const expectedCookieValues={};sessionKeys.forEach(sessionKey=>{expectedCookieValues[sessionToCookiesMap[sessionKey].name]=state.session[sessionKey].value;});// encrypt cookies values
3331
+ const encryptedCookieData=this.getEncryptedCookieData(getCurrentCookieValuesFromState(),store);if(encryptedCookieData.length>0){// make request to data service to set the cookie from server side
3332
+ this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{// Mark the cookie req status as done
3333
+ clearInProgressFlags();if(details?.xhr?.status===200){getCurrentCookieValuesFromState().forEach(cData=>{const originalCookieVal=originalCookieValues[cData.name];const currentCookieVal=store?.get(cData.name);// Check if the expected cookie values are set.
3334
+ if(stringifyWithoutCircular(expectedCookieValues[cData.name],false,[])!==stringifyWithoutCircular(currentCookieVal,false,[])){// It's fine if the values don't match as other active SDK sessions might have updated the cookie values
3335
+ // or other cookie requests might have updated the cookie value.
3336
+ // Log an error only when cookie didn't exist previously and currently also doesn't exist.
3337
+ if(isNull(originalCookieVal)&&isNull(currentCookieVal)){this.logger.error(FAILED_SETTING_COOKIE_FROM_SERVER_ERROR(cData.name));}if(cb){cb(cData.name,cData.value);}}});}else {this.logger.error(DATA_SERVER_REQUEST_FAIL_ERROR(details?.xhr?.status));setCookiesClientSide();}});}else {setCookiesClientSide();// Mark the cookie req status as done
3338
+ clearInProgressFlags();}}catch(e){this.onError(e,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR);setCookiesClientSide();// Mark the cookie req status as done
3339
+ clearInProgressFlags();}}/**
3327
3340
  * A function to sync values in storage
3328
3341
  * @param sessionKey
3329
- * @param value
3330
- */syncValueToStorage(sessionKey,value){const entries=state.storage.entries.value;const storageType=entries[sessionKey]?.type;if(isStorageTypeValidForStoringData(storageType)){const curStore=this.storeManager?.getStore(storageClientDataStoreNameMap[storageType]);const key=entries[sessionKey]?.key;if(value&&(isString(value)||isNonEmptyObject(value))){// if useServerSideCookies load option is set to true
3342
+ */syncValueToStorage(sessionKey){const entries=state.storage.entries.value;const storageType=entries[sessionKey]?.type;if(isStorageTypeValidForStoringData(storageType)){const curStore=this.storeManager.getStore(storageClientDataStoreNameMap[storageType]);const cookieName=entries[sessionKey]?.key;const cookieValue=state.session[sessionKey].value;if(cookieValue&&(isString(cookieValue)||isNonEmptyObject(cookieValue))){// if useServerSideCookies load option is set to true
3331
3343
  // set the cookie from server side
3332
- if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){if(this.serverSideCookieDebounceFuncs[sessionKey]){globalThis.clearTimeout(this.serverSideCookieDebounceFuncs[sessionKey]);}this.serverSideCookieDebounceFuncs[sessionKey]=globalThis.setTimeout(()=>{this.setServerSideCookies([{name:key,value}],(cookieName,cookieValue)=>{curStore?.set(cookieName,cookieValue);},curStore);},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {curStore?.set(key,value);}}else {curStore?.remove(key);}}}/**
3344
+ if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){// Mark the requests as in progress.
3345
+ this.serverSideCookiesRequestInProgress[sessionKey]=true;if(this.serverSideCookieDebounceFuncs[sessionKey]){globalThis.clearTimeout(this.serverSideCookieDebounceFuncs[sessionKey]);}this.serverSideCookieDebounceFuncs[sessionKey]=globalThis.setTimeout(()=>{// Create a map of session key to cookie name
3346
+ const sessionToCookiesMap={[sessionKey]:{name:cookieName}};this.setServerSideCookies(sessionToCookiesMap,(cookieName,cookieValue)=>{curStore?.set(cookieName,cookieValue);},curStore);},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {curStore?.set(cookieName,cookieValue);}}else {curStore?.remove(cookieName);}}}/**
3333
3347
  * Function to update storage whenever state value changes
3334
3348
  */registerEffects(){// This will work as long as the user session entry key names are same as the state keys
3335
- USER_SESSION_KEYS.forEach(sessionKey=>{E(()=>{this.syncValueToStorage(sessionKey,state.session[sessionKey].value);});});}/**
3349
+ USER_SESSION_KEYS.forEach(sessionKey=>{E(()=>{this.syncValueToStorage(sessionKey);});});}/**
3336
3350
  * Sets anonymous id in the following precedence:
3337
3351
  *
3338
3352
  * 1. anonymousId: Id directly provided to the function.
@@ -3349,30 +3363,37 @@ const autoCapturedAnonymousId=this.pluginsManager?.invokeSingle('storage.getAnon
3349
3363
  // This is needed for entries that are fetched from the storage
3350
3364
  // during the current session (for example, session info)
3351
3365
  this.migrateStorageIfNeeded([store],[sessionKey]);const storageKey=entries[sessionKey]?.key;return store?.get(storageKey)??null;}return null;}getExternalAnonymousIdByCookieName(key){const storageEngine=getStorageEngine(COOKIE_STORAGE);if(storageEngine?.isEnabled){return storageEngine.getItem(key)??null;}return null;}/**
3366
+ * Fetches the value for a session key. Preferably from storage, if the server-side
3367
+ * cookies request is not in progress. Otherwise, from the state.
3368
+ * @param sessionKey - The session key to fetch the value for
3369
+ * @returns - The value for the session key
3370
+ */getUserSessionValue(sessionKey){// If the server-side cookies request is in progress, fetch the value from the state.
3371
+ if(this.serverSideCookiesRequestInProgress[sessionKey]){return state.session[sessionKey].value;}// Otherwise, fetch the value from storage.
3372
+ return this.getEntryValue(sessionKey);}/**
3352
3373
  * Fetches User Id
3353
3374
  * @returns
3354
- */getUserId(){return this.getEntryValue('userId');}/**
3375
+ */getUserId(){return this.getUserSessionValue('userId');}/**
3355
3376
  * Fetches User Traits
3356
3377
  * @returns
3357
- */getUserTraits(){return this.getEntryValue('userTraits');}/**
3378
+ */getUserTraits(){return this.getUserSessionValue('userTraits');}/**
3358
3379
  * Fetches Group Id
3359
3380
  * @returns
3360
- */getGroupId(){return this.getEntryValue('groupId');}/**
3381
+ */getGroupId(){return this.getUserSessionValue('groupId');}/**
3361
3382
  * Fetches Group Traits
3362
3383
  * @returns
3363
- */getGroupTraits(){return this.getEntryValue('groupTraits');}/**
3384
+ */getGroupTraits(){return this.getUserSessionValue('groupTraits');}/**
3364
3385
  * Fetches Initial Referrer
3365
3386
  * @returns
3366
- */getInitialReferrer(){return this.getEntryValue('initialReferrer');}/**
3387
+ */getInitialReferrer(){return this.getUserSessionValue('initialReferrer');}/**
3367
3388
  * Fetches Initial Referring domain
3368
3389
  * @returns
3369
- */getInitialReferringDomain(){return this.getEntryValue('initialReferringDomain');}/**
3390
+ */getInitialReferringDomain(){return this.getUserSessionValue('initialReferringDomain');}/**
3370
3391
  * Fetches session tracking information from storage
3371
3392
  * @returns
3372
- */getSessionInfo(){return this.getEntryValue('sessionInfo');}/**
3393
+ */getSessionInfo(){return this.getUserSessionValue('sessionInfo');}/**
3373
3394
  * Fetches auth token from storage
3374
3395
  * @returns
3375
- */getAuthToken(){return this.getEntryValue('authToken');}/**
3396
+ */getAuthToken(){return this.getUserSessionValue('authToken');}/**
3376
3397
  * If session is active it returns the sessionId
3377
3398
  * @returns
3378
3399
  */getSessionId(){const sessionInfo=this.getSessionInfo()??DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack&&!hasSessionExpired(sessionInfo)||sessionInfo.manualTrack){return sessionInfo.id??null;}return null;}/**
@@ -3388,7 +3409,7 @@ this.migrateStorageIfNeeded([store],[sessionKey]);const storageKey=entries[sessi
3388
3409
  if(sessionInfo.sessionStart===undefined){sessionInfo={...sessionInfo,sessionStart:true};}else if(sessionInfo.sessionStart){sessionInfo={...sessionInfo,sessionStart:false};}}// Always write to state (in-turn to storage) to keep the session info up to date.
3389
3410
  state.session.sessionInfo.value=sessionInfo;if(state.lifecycle.status.value!=='readyExecuted'){// Force update the storage as the 'effect' blocks are not getting triggered
3390
3411
  // when processing preload buffered requests
3391
- this.syncValueToStorage('sessionInfo',sessionInfo);}}resetAndStartNewSession(){const session=state.session;const{manualTrack,autoTrack,timeout,cutOff}=session.sessionInfo.value;if(autoTrack){const sessionInfo={...DEFAULT_USER_SESSION_VALUES.sessionInfo,timeout};if(cutOff){sessionInfo.cutOff={enabled:cutOff.enabled,duration:cutOff.duration};}session.sessionInfo.value=sessionInfo;this.startOrRenewAutoTracking(session.sessionInfo.value);}else if(manualTrack){this.startManualTrackingInternal();}}/**
3412
+ this.syncValueToStorage('sessionInfo');}}resetAndStartNewSession(){const session=state.session;const{manualTrack,autoTrack,timeout,cutOff}=session.sessionInfo.value;if(autoTrack){const sessionInfo={...DEFAULT_USER_SESSION_VALUES.sessionInfo,timeout};if(cutOff){sessionInfo.cutOff={enabled:cutOff.enabled,duration:cutOff.duration};}session.sessionInfo.value=sessionInfo;this.startOrRenewAutoTracking(session.sessionInfo.value);}else if(manualTrack){this.startManualTrackingInternal();}}/**
3392
3413
  * Reset state values
3393
3414
  * @param options options for reset
3394
3415
  * @returns
@@ -521,7 +521,7 @@
521
521
  error.stacktrace=`${stacktrace}\n${MANUAL_ERROR_IDENTIFIER}`;break;case operaSourceloc:default:// eslint-disable-next-line no-param-reassign
522
522
  error['opera#sourceloc']=`${operaSourceloc}\n${MANUAL_ERROR_IDENTIFIER}`;break;}}}globalThis.dispatchEvent(new ErrorEvent('error',{error,bubbles:true,cancelable:true,composed:true}));};
523
523
 
524
- const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.25.1';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
524
+ const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.26.0';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
525
525
 
526
526
  const QUERY_PARAM_TRAIT_PREFIX='ajs_trait_';const QUERY_PARAM_PROPERTY_PREFIX='ajs_prop_';const QUERY_PARAM_ANONYMOUS_ID_KEY='ajs_aid';const QUERY_PARAM_USER_ID_KEY='ajs_uid';const QUERY_PARAM_TRACK_EVENT_NAME_KEY='ajs_event';
527
527
 
@@ -549,8 +549,9 @@
549
549
  * Parse query string into preload buffer events & push into existing array before any other events
550
550
  */const retrieveEventsFromQueryString=(argumentsArray=[])=>{// Mapping for trait and properties values based on key prefix
551
551
  const eventArgumentToQueryParamMap={trait:QUERY_PARAM_TRAIT_PREFIX,properties:QUERY_PARAM_PROPERTY_PREFIX};const queryObject=new URLSearchParams(globalThis.location.search);// Add track events with name and properties
552
- if(queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY)){argumentsArray.unshift(['track',queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.properties)]);}// Set userId and user traits
553
- if(queryObject.get(QUERY_PARAM_USER_ID_KEY)){argumentsArray.unshift(['identify',queryObject.get(QUERY_PARAM_USER_ID_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.trait)]);}// Set anonymousID
552
+ if(queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY)){argumentsArray.unshift(['track',queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.properties)]);}// Send identify event
553
+ const userId=queryObject.get(QUERY_PARAM_USER_ID_KEY);const userTraits=getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.trait);if(userId||isNonEmptyObject(userTraits)){// In identify API, user ID is optional
554
+ const identifyApiArgs=[...(userId?[userId]:[]),userTraits];argumentsArray.unshift(['identify',...identifyApiArgs]);}// Set anonymousID
554
555
  if(queryObject.get(QUERY_PARAM_ANONYMOUS_ID_KEY)){argumentsArray.unshift(['setAnonymousId',queryObject.get(QUERY_PARAM_ANONYMOUS_ID_KEY)]);}};/**
555
556
  * Retrieve an existing buffered load method call and remove from the existing array
556
557
  */const getPreloadedLoadEvent=preloadedEventsArray=>{const loadMethodName='load';let loadEvent=[];/**
@@ -3295,7 +3296,9 @@
3295
3296
  * @param event Incoming event data
3296
3297
  */addEvent(event){this.userSessionManager.refreshSession();const rudderEvent=this.eventFactory.create(event);this.eventRepository.enqueue(rudderEvent,event.callback);}}
3297
3298
 
3298
- class UserSessionManager{constructor(pluginsManager,storeManager,httpClient,errorHandler,logger){this.storeManager=storeManager;this.pluginsManager=pluginsManager;this.logger=logger;this.errorHandler=errorHandler;this.httpClient=httpClient;this.onError=this.onError.bind(this);this.serverSideCookieDebounceFuncs={};}/**
3299
+ class UserSessionManager{/**
3300
+ * Tracks whether a server-side cookie setting request is in progress or not.
3301
+ */constructor(pluginsManager,storeManager,httpClient,errorHandler,logger){this.storeManager=storeManager;this.pluginsManager=pluginsManager;this.logger=logger;this.errorHandler=errorHandler;this.httpClient=httpClient;this.onError=this.onError.bind(this);this.serverSideCookieDebounceFuncs={};this.serverSideCookiesRequestInProgress={};}/**
3299
3302
  * Initialize User session with values from storage
3300
3303
  */init(){this.syncStorageDataToState();// Register the effect to sync with storage
3301
3304
  this.registerEffects();}syncStorageDataToState(){this.migrateStorageIfNeeded();this.migrateDataFromPreviousStorage();// get the values from storage and set it again
@@ -3325,20 +3328,31 @@
3325
3328
  * @param callback
3326
3329
  */makeRequestToSetCookie(encryptedCookieData,callback){this.httpClient?.getAsyncData({url:state.serverCookies.dataServiceUrl.value,options:{method:'POST',data:stringifyWithoutCircular({reqType:'setCookies',workspaceId:state.source.value?.workspaceId,data:{options:{maxAge:state.storage.cookie.value?.maxage,path:state.storage.cookie.value?.path,domain:state.storage.cookie.value?.domain,sameSite:state.storage.cookie.value?.samesite,secure:state.storage.cookie.value?.secure,expires:state.storage.cookie.value?.expires},cookies:encryptedCookieData}}),sendRawData:true,withCredentials:true},isRawResponse:true,callback});}/**
3327
3330
  * A function to make an external request to set the cookie from server side
3328
- * @param key cookie name
3329
- * @param value encrypted cookie value
3330
- */setServerSideCookies(cookiesData,cb,store){try{// encrypt cookies values
3331
- const encryptedCookieData=this.getEncryptedCookieData(cookiesData,store);if(encryptedCookieData.length>0){// make request to data service to set the cookie from server side
3332
- this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{if(details?.xhr?.status===200){cookiesData.forEach(cData=>{const cookieValue=store?.get(cData.name);const before=stringifyWithoutCircular(cData.value,false,[]);const after=stringifyWithoutCircular(cookieValue,false,[]);if(after!==before){this.logger.error(FAILED_SETTING_COOKIE_FROM_SERVER_ERROR(cData.name));if(cb){cb(cData.name,cData.value);}}});}else {this.logger.error(DATA_SERVER_REQUEST_FAIL_ERROR(details?.xhr?.status));cookiesData.forEach(each=>{if(cb){cb(each.name,each.value);}});}});}}catch(e){this.onError(e,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR);cookiesData.forEach(each=>{if(cb){cb(each.name,each.value);}});}}/**
3331
+ * @param sessionToCookiesMap map of session key to cookie name
3332
+ * @param cb callback function to be called when the cookie is set
3333
+ * @param store store to be used to get the cookie value
3334
+ */setServerSideCookies(sessionToCookiesMap,cb,store){// Retrieve the cookie value from the state
3335
+ const sessionKeys=Object.keys(sessionToCookiesMap);const getCurrentCookieValuesFromState=()=>{return sessionKeys.map(sessionKey=>{return {name:sessionToCookiesMap[sessionKey].name,value:state.session[sessionKey].value};});};// Preserve the current cookie values
3336
+ const originalCookieValues={};sessionKeys.forEach(sessionKey=>{originalCookieValues[sessionToCookiesMap[sessionKey].name]=store?.get(sessionToCookiesMap[sessionKey].name);});const clearInProgressFlags=()=>{sessionKeys.forEach(sessionKey=>{this.serverSideCookiesRequestInProgress[sessionKey]=false;});};const setCookiesClientSide=()=>{getCurrentCookieValuesFromState().forEach(each=>{if(cb){cb(each.name,each.value);}});};try{const expectedCookieValues={};sessionKeys.forEach(sessionKey=>{expectedCookieValues[sessionToCookiesMap[sessionKey].name]=state.session[sessionKey].value;});// encrypt cookies values
3337
+ const encryptedCookieData=this.getEncryptedCookieData(getCurrentCookieValuesFromState(),store);if(encryptedCookieData.length>0){// make request to data service to set the cookie from server side
3338
+ this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{// Mark the cookie req status as done
3339
+ clearInProgressFlags();if(details?.xhr?.status===200){getCurrentCookieValuesFromState().forEach(cData=>{const originalCookieVal=originalCookieValues[cData.name];const currentCookieVal=store?.get(cData.name);// Check if the expected cookie values are set.
3340
+ if(stringifyWithoutCircular(expectedCookieValues[cData.name],false,[])!==stringifyWithoutCircular(currentCookieVal,false,[])){// It's fine if the values don't match as other active SDK sessions might have updated the cookie values
3341
+ // or other cookie requests might have updated the cookie value.
3342
+ // Log an error only when cookie didn't exist previously and currently also doesn't exist.
3343
+ if(isNull(originalCookieVal)&&isNull(currentCookieVal)){this.logger.error(FAILED_SETTING_COOKIE_FROM_SERVER_ERROR(cData.name));}if(cb){cb(cData.name,cData.value);}}});}else {this.logger.error(DATA_SERVER_REQUEST_FAIL_ERROR(details?.xhr?.status));setCookiesClientSide();}});}else {setCookiesClientSide();// Mark the cookie req status as done
3344
+ clearInProgressFlags();}}catch(e){this.onError(e,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR);setCookiesClientSide();// Mark the cookie req status as done
3345
+ clearInProgressFlags();}}/**
3333
3346
  * A function to sync values in storage
3334
3347
  * @param sessionKey
3335
- * @param value
3336
- */syncValueToStorage(sessionKey,value){const entries=state.storage.entries.value;const storageType=entries[sessionKey]?.type;if(isStorageTypeValidForStoringData(storageType)){const curStore=this.storeManager?.getStore(storageClientDataStoreNameMap[storageType]);const key=entries[sessionKey]?.key;if(value&&(isString(value)||isNonEmptyObject(value))){// if useServerSideCookies load option is set to true
3348
+ */syncValueToStorage(sessionKey){const entries=state.storage.entries.value;const storageType=entries[sessionKey]?.type;if(isStorageTypeValidForStoringData(storageType)){const curStore=this.storeManager.getStore(storageClientDataStoreNameMap[storageType]);const cookieName=entries[sessionKey]?.key;const cookieValue=state.session[sessionKey].value;if(cookieValue&&(isString(cookieValue)||isNonEmptyObject(cookieValue))){// if useServerSideCookies load option is set to true
3337
3349
  // set the cookie from server side
3338
- if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){if(this.serverSideCookieDebounceFuncs[sessionKey]){globalThis.clearTimeout(this.serverSideCookieDebounceFuncs[sessionKey]);}this.serverSideCookieDebounceFuncs[sessionKey]=globalThis.setTimeout(()=>{this.setServerSideCookies([{name:key,value}],(cookieName,cookieValue)=>{curStore?.set(cookieName,cookieValue);},curStore);},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {curStore?.set(key,value);}}else {curStore?.remove(key);}}}/**
3350
+ if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){// Mark the requests as in progress.
3351
+ this.serverSideCookiesRequestInProgress[sessionKey]=true;if(this.serverSideCookieDebounceFuncs[sessionKey]){globalThis.clearTimeout(this.serverSideCookieDebounceFuncs[sessionKey]);}this.serverSideCookieDebounceFuncs[sessionKey]=globalThis.setTimeout(()=>{// Create a map of session key to cookie name
3352
+ const sessionToCookiesMap={[sessionKey]:{name:cookieName}};this.setServerSideCookies(sessionToCookiesMap,(cookieName,cookieValue)=>{curStore?.set(cookieName,cookieValue);},curStore);},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {curStore?.set(cookieName,cookieValue);}}else {curStore?.remove(cookieName);}}}/**
3339
3353
  * Function to update storage whenever state value changes
3340
3354
  */registerEffects(){// This will work as long as the user session entry key names are same as the state keys
3341
- USER_SESSION_KEYS.forEach(sessionKey=>{E(()=>{this.syncValueToStorage(sessionKey,state.session[sessionKey].value);});});}/**
3355
+ USER_SESSION_KEYS.forEach(sessionKey=>{E(()=>{this.syncValueToStorage(sessionKey);});});}/**
3342
3356
  * Sets anonymous id in the following precedence:
3343
3357
  *
3344
3358
  * 1. anonymousId: Id directly provided to the function.
@@ -3355,30 +3369,37 @@
3355
3369
  // This is needed for entries that are fetched from the storage
3356
3370
  // during the current session (for example, session info)
3357
3371
  this.migrateStorageIfNeeded([store],[sessionKey]);const storageKey=entries[sessionKey]?.key;return store?.get(storageKey)??null;}return null;}getExternalAnonymousIdByCookieName(key){const storageEngine=getStorageEngine(COOKIE_STORAGE);if(storageEngine?.isEnabled){return storageEngine.getItem(key)??null;}return null;}/**
3372
+ * Fetches the value for a session key. Preferably from storage, if the server-side
3373
+ * cookies request is not in progress. Otherwise, from the state.
3374
+ * @param sessionKey - The session key to fetch the value for
3375
+ * @returns - The value for the session key
3376
+ */getUserSessionValue(sessionKey){// If the server-side cookies request is in progress, fetch the value from the state.
3377
+ if(this.serverSideCookiesRequestInProgress[sessionKey]){return state.session[sessionKey].value;}// Otherwise, fetch the value from storage.
3378
+ return this.getEntryValue(sessionKey);}/**
3358
3379
  * Fetches User Id
3359
3380
  * @returns
3360
- */getUserId(){return this.getEntryValue('userId');}/**
3381
+ */getUserId(){return this.getUserSessionValue('userId');}/**
3361
3382
  * Fetches User Traits
3362
3383
  * @returns
3363
- */getUserTraits(){return this.getEntryValue('userTraits');}/**
3384
+ */getUserTraits(){return this.getUserSessionValue('userTraits');}/**
3364
3385
  * Fetches Group Id
3365
3386
  * @returns
3366
- */getGroupId(){return this.getEntryValue('groupId');}/**
3387
+ */getGroupId(){return this.getUserSessionValue('groupId');}/**
3367
3388
  * Fetches Group Traits
3368
3389
  * @returns
3369
- */getGroupTraits(){return this.getEntryValue('groupTraits');}/**
3390
+ */getGroupTraits(){return this.getUserSessionValue('groupTraits');}/**
3370
3391
  * Fetches Initial Referrer
3371
3392
  * @returns
3372
- */getInitialReferrer(){return this.getEntryValue('initialReferrer');}/**
3393
+ */getInitialReferrer(){return this.getUserSessionValue('initialReferrer');}/**
3373
3394
  * Fetches Initial Referring domain
3374
3395
  * @returns
3375
- */getInitialReferringDomain(){return this.getEntryValue('initialReferringDomain');}/**
3396
+ */getInitialReferringDomain(){return this.getUserSessionValue('initialReferringDomain');}/**
3376
3397
  * Fetches session tracking information from storage
3377
3398
  * @returns
3378
- */getSessionInfo(){return this.getEntryValue('sessionInfo');}/**
3399
+ */getSessionInfo(){return this.getUserSessionValue('sessionInfo');}/**
3379
3400
  * Fetches auth token from storage
3380
3401
  * @returns
3381
- */getAuthToken(){return this.getEntryValue('authToken');}/**
3402
+ */getAuthToken(){return this.getUserSessionValue('authToken');}/**
3382
3403
  * If session is active it returns the sessionId
3383
3404
  * @returns
3384
3405
  */getSessionId(){const sessionInfo=this.getSessionInfo()??DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack&&!hasSessionExpired(sessionInfo)||sessionInfo.manualTrack){return sessionInfo.id??null;}return null;}/**
@@ -3394,7 +3415,7 @@
3394
3415
  if(sessionInfo.sessionStart===undefined){sessionInfo={...sessionInfo,sessionStart:true};}else if(sessionInfo.sessionStart){sessionInfo={...sessionInfo,sessionStart:false};}}// Always write to state (in-turn to storage) to keep the session info up to date.
3395
3416
  state.session.sessionInfo.value=sessionInfo;if(state.lifecycle.status.value!=='readyExecuted'){// Force update the storage as the 'effect' blocks are not getting triggered
3396
3417
  // when processing preload buffered requests
3397
- this.syncValueToStorage('sessionInfo',sessionInfo);}}resetAndStartNewSession(){const session=state.session;const{manualTrack,autoTrack,timeout,cutOff}=session.sessionInfo.value;if(autoTrack){const sessionInfo={...DEFAULT_USER_SESSION_VALUES.sessionInfo,timeout};if(cutOff){sessionInfo.cutOff={enabled:cutOff.enabled,duration:cutOff.duration};}session.sessionInfo.value=sessionInfo;this.startOrRenewAutoTracking(session.sessionInfo.value);}else if(manualTrack){this.startManualTrackingInternal();}}/**
3418
+ this.syncValueToStorage('sessionInfo');}}resetAndStartNewSession(){const session=state.session;const{manualTrack,autoTrack,timeout,cutOff}=session.sessionInfo.value;if(autoTrack){const sessionInfo={...DEFAULT_USER_SESSION_VALUES.sessionInfo,timeout};if(cutOff){sessionInfo.cutOff={enabled:cutOff.enabled,duration:cutOff.duration};}session.sessionInfo.value=sessionInfo;this.startOrRenewAutoTracking(session.sessionInfo.value);}else if(manualTrack){this.startManualTrackingInternal();}}/**
3398
3419
  * Reset state values
3399
3420
  * @param options options for reset
3400
3421
  * @returns
@@ -510,7 +510,7 @@ error.stack=`${stack}\n${MANUAL_ERROR_IDENTIFIER}`;break;case stacktrace:// esli
510
510
  error.stacktrace=`${stacktrace}\n${MANUAL_ERROR_IDENTIFIER}`;break;case operaSourceloc:default:// eslint-disable-next-line no-param-reassign
511
511
  error['opera#sourceloc']=`${operaSourceloc}\n${MANUAL_ERROR_IDENTIFIER}`;break;}}}globalThis.dispatchEvent(new ErrorEvent('error',{error,bubbles:true,cancelable:true,composed:true}));};
512
512
 
513
- const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.25.1';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
513
+ const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.26.0';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
514
514
 
515
515
  const QUERY_PARAM_TRAIT_PREFIX='ajs_trait_';const QUERY_PARAM_PROPERTY_PREFIX='ajs_prop_';const QUERY_PARAM_ANONYMOUS_ID_KEY='ajs_aid';const QUERY_PARAM_USER_ID_KEY='ajs_uid';const QUERY_PARAM_TRACK_EVENT_NAME_KEY='ajs_event';
516
516
 
@@ -538,8 +538,9 @@ data[dataKey]=params.get(key);}});return data;};/**
538
538
  * Parse query string into preload buffer events & push into existing array before any other events
539
539
  */const retrieveEventsFromQueryString=(argumentsArray=[])=>{// Mapping for trait and properties values based on key prefix
540
540
  const eventArgumentToQueryParamMap={trait:QUERY_PARAM_TRAIT_PREFIX,properties:QUERY_PARAM_PROPERTY_PREFIX};const queryObject=new URLSearchParams(globalThis.location.search);// Add track events with name and properties
541
- if(queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY)){argumentsArray.unshift(['track',queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.properties)]);}// Set userId and user traits
542
- if(queryObject.get(QUERY_PARAM_USER_ID_KEY)){argumentsArray.unshift(['identify',queryObject.get(QUERY_PARAM_USER_ID_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.trait)]);}// Set anonymousID
541
+ if(queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY)){argumentsArray.unshift(['track',queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.properties)]);}// Send identify event
542
+ const userId=queryObject.get(QUERY_PARAM_USER_ID_KEY);const userTraits=getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.trait);if(userId||isNonEmptyObject(userTraits)){// In identify API, user ID is optional
543
+ const identifyApiArgs=[...(userId?[userId]:[]),userTraits];argumentsArray.unshift(['identify',...identifyApiArgs]);}// Set anonymousID
543
544
  if(queryObject.get(QUERY_PARAM_ANONYMOUS_ID_KEY)){argumentsArray.unshift(['setAnonymousId',queryObject.get(QUERY_PARAM_ANONYMOUS_ID_KEY)]);}};/**
544
545
  * Retrieve an existing buffered load method call and remove from the existing array
545
546
  */const getPreloadedLoadEvent=preloadedEventsArray=>{const loadMethodName='load';let loadEvent=[];/**
@@ -1585,7 +1586,9 @@ enrichedEvent.userId=to??enrichedEvent.userId;return enrichedEvent;}/**
1585
1586
  * @param event Incoming event data
1586
1587
  */addEvent(event){this.userSessionManager.refreshSession();const rudderEvent=this.eventFactory.create(event);this.eventRepository.enqueue(rudderEvent,event.callback);}}
1587
1588
 
1588
- class UserSessionManager{constructor(pluginsManager,storeManager,httpClient,errorHandler,logger){this.storeManager=storeManager;this.pluginsManager=pluginsManager;this.logger=logger;this.errorHandler=errorHandler;this.httpClient=httpClient;this.onError=this.onError.bind(this);this.serverSideCookieDebounceFuncs={};}/**
1589
+ class UserSessionManager{/**
1590
+ * Tracks whether a server-side cookie setting request is in progress or not.
1591
+ */constructor(pluginsManager,storeManager,httpClient,errorHandler,logger){this.storeManager=storeManager;this.pluginsManager=pluginsManager;this.logger=logger;this.errorHandler=errorHandler;this.httpClient=httpClient;this.onError=this.onError.bind(this);this.serverSideCookieDebounceFuncs={};this.serverSideCookiesRequestInProgress={};}/**
1589
1592
  * Initialize User session with values from storage
1590
1593
  */init(){this.syncStorageDataToState();// Register the effect to sync with storage
1591
1594
  this.registerEffects();}syncStorageDataToState(){this.migrateStorageIfNeeded();this.migrateDataFromPreviousStorage();// get the values from storage and set it again
@@ -1615,20 +1618,31 @@ cutOffDuration=DEFAULT_SESSION_CUT_OFF_DURATION_MS;}else if(cutOffDuration<sessi
1615
1618
  * @param callback
1616
1619
  */makeRequestToSetCookie(encryptedCookieData,callback){this.httpClient?.getAsyncData({url:state.serverCookies.dataServiceUrl.value,options:{method:'POST',data:stringifyWithoutCircular({reqType:'setCookies',workspaceId:state.source.value?.workspaceId,data:{options:{maxAge:state.storage.cookie.value?.maxage,path:state.storage.cookie.value?.path,domain:state.storage.cookie.value?.domain,sameSite:state.storage.cookie.value?.samesite,secure:state.storage.cookie.value?.secure,expires:state.storage.cookie.value?.expires},cookies:encryptedCookieData}}),sendRawData:true,withCredentials:true},isRawResponse:true,callback});}/**
1617
1620
  * A function to make an external request to set the cookie from server side
1618
- * @param key cookie name
1619
- * @param value encrypted cookie value
1620
- */setServerSideCookies(cookiesData,cb,store){try{// encrypt cookies values
1621
- const encryptedCookieData=this.getEncryptedCookieData(cookiesData,store);if(encryptedCookieData.length>0){// make request to data service to set the cookie from server side
1622
- this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{if(details?.xhr?.status===200){cookiesData.forEach(cData=>{const cookieValue=store?.get(cData.name);const before=stringifyWithoutCircular(cData.value,false,[]);const after=stringifyWithoutCircular(cookieValue,false,[]);if(after!==before){this.logger.error(FAILED_SETTING_COOKIE_FROM_SERVER_ERROR(cData.name));if(cb){cb(cData.name,cData.value);}}});}else {this.logger.error(DATA_SERVER_REQUEST_FAIL_ERROR(details?.xhr?.status));cookiesData.forEach(each=>{if(cb){cb(each.name,each.value);}});}});}}catch(e){this.onError(e,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR);cookiesData.forEach(each=>{if(cb){cb(each.name,each.value);}});}}/**
1621
+ * @param sessionToCookiesMap map of session key to cookie name
1622
+ * @param cb callback function to be called when the cookie is set
1623
+ * @param store store to be used to get the cookie value
1624
+ */setServerSideCookies(sessionToCookiesMap,cb,store){// Retrieve the cookie value from the state
1625
+ const sessionKeys=Object.keys(sessionToCookiesMap);const getCurrentCookieValuesFromState=()=>{return sessionKeys.map(sessionKey=>{return {name:sessionToCookiesMap[sessionKey].name,value:state.session[sessionKey].value};});};// Preserve the current cookie values
1626
+ const originalCookieValues={};sessionKeys.forEach(sessionKey=>{originalCookieValues[sessionToCookiesMap[sessionKey].name]=store?.get(sessionToCookiesMap[sessionKey].name);});const clearInProgressFlags=()=>{sessionKeys.forEach(sessionKey=>{this.serverSideCookiesRequestInProgress[sessionKey]=false;});};const setCookiesClientSide=()=>{getCurrentCookieValuesFromState().forEach(each=>{if(cb){cb(each.name,each.value);}});};try{const expectedCookieValues={};sessionKeys.forEach(sessionKey=>{expectedCookieValues[sessionToCookiesMap[sessionKey].name]=state.session[sessionKey].value;});// encrypt cookies values
1627
+ const encryptedCookieData=this.getEncryptedCookieData(getCurrentCookieValuesFromState(),store);if(encryptedCookieData.length>0){// make request to data service to set the cookie from server side
1628
+ this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{// Mark the cookie req status as done
1629
+ clearInProgressFlags();if(details?.xhr?.status===200){getCurrentCookieValuesFromState().forEach(cData=>{const originalCookieVal=originalCookieValues[cData.name];const currentCookieVal=store?.get(cData.name);// Check if the expected cookie values are set.
1630
+ if(stringifyWithoutCircular(expectedCookieValues[cData.name],false,[])!==stringifyWithoutCircular(currentCookieVal,false,[])){// It's fine if the values don't match as other active SDK sessions might have updated the cookie values
1631
+ // or other cookie requests might have updated the cookie value.
1632
+ // Log an error only when cookie didn't exist previously and currently also doesn't exist.
1633
+ if(isNull(originalCookieVal)&&isNull(currentCookieVal)){this.logger.error(FAILED_SETTING_COOKIE_FROM_SERVER_ERROR(cData.name));}if(cb){cb(cData.name,cData.value);}}});}else {this.logger.error(DATA_SERVER_REQUEST_FAIL_ERROR(details?.xhr?.status));setCookiesClientSide();}});}else {setCookiesClientSide();// Mark the cookie req status as done
1634
+ clearInProgressFlags();}}catch(e){this.onError(e,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR);setCookiesClientSide();// Mark the cookie req status as done
1635
+ clearInProgressFlags();}}/**
1623
1636
  * A function to sync values in storage
1624
1637
  * @param sessionKey
1625
- * @param value
1626
- */syncValueToStorage(sessionKey,value){const entries=state.storage.entries.value;const storageType=entries[sessionKey]?.type;if(isStorageTypeValidForStoringData(storageType)){const curStore=this.storeManager?.getStore(storageClientDataStoreNameMap[storageType]);const key=entries[sessionKey]?.key;if(value&&(isString(value)||isNonEmptyObject(value))){// if useServerSideCookies load option is set to true
1638
+ */syncValueToStorage(sessionKey){const entries=state.storage.entries.value;const storageType=entries[sessionKey]?.type;if(isStorageTypeValidForStoringData(storageType)){const curStore=this.storeManager.getStore(storageClientDataStoreNameMap[storageType]);const cookieName=entries[sessionKey]?.key;const cookieValue=state.session[sessionKey].value;if(cookieValue&&(isString(cookieValue)||isNonEmptyObject(cookieValue))){// if useServerSideCookies load option is set to true
1627
1639
  // set the cookie from server side
1628
- if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){if(this.serverSideCookieDebounceFuncs[sessionKey]){globalThis.clearTimeout(this.serverSideCookieDebounceFuncs[sessionKey]);}this.serverSideCookieDebounceFuncs[sessionKey]=globalThis.setTimeout(()=>{this.setServerSideCookies([{name:key,value}],(cookieName,cookieValue)=>{curStore?.set(cookieName,cookieValue);},curStore);},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {curStore?.set(key,value);}}else {curStore?.remove(key);}}}/**
1640
+ if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){// Mark the requests as in progress.
1641
+ this.serverSideCookiesRequestInProgress[sessionKey]=true;if(this.serverSideCookieDebounceFuncs[sessionKey]){globalThis.clearTimeout(this.serverSideCookieDebounceFuncs[sessionKey]);}this.serverSideCookieDebounceFuncs[sessionKey]=globalThis.setTimeout(()=>{// Create a map of session key to cookie name
1642
+ const sessionToCookiesMap={[sessionKey]:{name:cookieName}};this.setServerSideCookies(sessionToCookiesMap,(cookieName,cookieValue)=>{curStore?.set(cookieName,cookieValue);},curStore);},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {curStore?.set(cookieName,cookieValue);}}else {curStore?.remove(cookieName);}}}/**
1629
1643
  * Function to update storage whenever state value changes
1630
1644
  */registerEffects(){// This will work as long as the user session entry key names are same as the state keys
1631
- USER_SESSION_KEYS.forEach(sessionKey=>{E(()=>{this.syncValueToStorage(sessionKey,state.session[sessionKey].value);});});}/**
1645
+ USER_SESSION_KEYS.forEach(sessionKey=>{E(()=>{this.syncValueToStorage(sessionKey);});});}/**
1632
1646
  * Sets anonymous id in the following precedence:
1633
1647
  *
1634
1648
  * 1. anonymousId: Id directly provided to the function.
@@ -1645,30 +1659,37 @@ const autoCapturedAnonymousId=this.pluginsManager?.invokeSingle('storage.getAnon
1645
1659
  // This is needed for entries that are fetched from the storage
1646
1660
  // during the current session (for example, session info)
1647
1661
  this.migrateStorageIfNeeded([store],[sessionKey]);const storageKey=entries[sessionKey]?.key;return store?.get(storageKey)??null;}return null;}getExternalAnonymousIdByCookieName(key){const storageEngine=getStorageEngine(COOKIE_STORAGE);if(storageEngine?.isEnabled){return storageEngine.getItem(key)??null;}return null;}/**
1662
+ * Fetches the value for a session key. Preferably from storage, if the server-side
1663
+ * cookies request is not in progress. Otherwise, from the state.
1664
+ * @param sessionKey - The session key to fetch the value for
1665
+ * @returns - The value for the session key
1666
+ */getUserSessionValue(sessionKey){// If the server-side cookies request is in progress, fetch the value from the state.
1667
+ if(this.serverSideCookiesRequestInProgress[sessionKey]){return state.session[sessionKey].value;}// Otherwise, fetch the value from storage.
1668
+ return this.getEntryValue(sessionKey);}/**
1648
1669
  * Fetches User Id
1649
1670
  * @returns
1650
- */getUserId(){return this.getEntryValue('userId');}/**
1671
+ */getUserId(){return this.getUserSessionValue('userId');}/**
1651
1672
  * Fetches User Traits
1652
1673
  * @returns
1653
- */getUserTraits(){return this.getEntryValue('userTraits');}/**
1674
+ */getUserTraits(){return this.getUserSessionValue('userTraits');}/**
1654
1675
  * Fetches Group Id
1655
1676
  * @returns
1656
- */getGroupId(){return this.getEntryValue('groupId');}/**
1677
+ */getGroupId(){return this.getUserSessionValue('groupId');}/**
1657
1678
  * Fetches Group Traits
1658
1679
  * @returns
1659
- */getGroupTraits(){return this.getEntryValue('groupTraits');}/**
1680
+ */getGroupTraits(){return this.getUserSessionValue('groupTraits');}/**
1660
1681
  * Fetches Initial Referrer
1661
1682
  * @returns
1662
- */getInitialReferrer(){return this.getEntryValue('initialReferrer');}/**
1683
+ */getInitialReferrer(){return this.getUserSessionValue('initialReferrer');}/**
1663
1684
  * Fetches Initial Referring domain
1664
1685
  * @returns
1665
- */getInitialReferringDomain(){return this.getEntryValue('initialReferringDomain');}/**
1686
+ */getInitialReferringDomain(){return this.getUserSessionValue('initialReferringDomain');}/**
1666
1687
  * Fetches session tracking information from storage
1667
1688
  * @returns
1668
- */getSessionInfo(){return this.getEntryValue('sessionInfo');}/**
1689
+ */getSessionInfo(){return this.getUserSessionValue('sessionInfo');}/**
1669
1690
  * Fetches auth token from storage
1670
1691
  * @returns
1671
- */getAuthToken(){return this.getEntryValue('authToken');}/**
1692
+ */getAuthToken(){return this.getUserSessionValue('authToken');}/**
1672
1693
  * If session is active it returns the sessionId
1673
1694
  * @returns
1674
1695
  */getSessionId(){const sessionInfo=this.getSessionInfo()??DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack&&!hasSessionExpired(sessionInfo)||sessionInfo.manualTrack){return sessionInfo.id??null;}return null;}/**
@@ -1684,7 +1705,7 @@ this.migrateStorageIfNeeded([store],[sessionKey]);const storageKey=entries[sessi
1684
1705
  if(sessionInfo.sessionStart===undefined){sessionInfo={...sessionInfo,sessionStart:true};}else if(sessionInfo.sessionStart){sessionInfo={...sessionInfo,sessionStart:false};}}// Always write to state (in-turn to storage) to keep the session info up to date.
1685
1706
  state.session.sessionInfo.value=sessionInfo;if(state.lifecycle.status.value!=='readyExecuted'){// Force update the storage as the 'effect' blocks are not getting triggered
1686
1707
  // when processing preload buffered requests
1687
- this.syncValueToStorage('sessionInfo',sessionInfo);}}resetAndStartNewSession(){const session=state.session;const{manualTrack,autoTrack,timeout,cutOff}=session.sessionInfo.value;if(autoTrack){const sessionInfo={...DEFAULT_USER_SESSION_VALUES.sessionInfo,timeout};if(cutOff){sessionInfo.cutOff={enabled:cutOff.enabled,duration:cutOff.duration};}session.sessionInfo.value=sessionInfo;this.startOrRenewAutoTracking(session.sessionInfo.value);}else if(manualTrack){this.startManualTrackingInternal();}}/**
1708
+ this.syncValueToStorage('sessionInfo');}}resetAndStartNewSession(){const session=state.session;const{manualTrack,autoTrack,timeout,cutOff}=session.sessionInfo.value;if(autoTrack){const sessionInfo={...DEFAULT_USER_SESSION_VALUES.sessionInfo,timeout};if(cutOff){sessionInfo.cutOff={enabled:cutOff.enabled,duration:cutOff.duration};}session.sessionInfo.value=sessionInfo;this.startOrRenewAutoTracking(session.sessionInfo.value);}else if(manualTrack){this.startManualTrackingInternal();}}/**
1688
1709
  * Reset state values
1689
1710
  * @param options options for reset
1690
1711
  * @returns