@rudderstack/analytics-js 3.25.1-beta.pr.2607.9d63b74 → 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.
- package/CHANGELOG.md +12 -0
- package/dist/npm/legacy/bundled/cjs/index.cjs +44 -43
- package/dist/npm/legacy/bundled/esm/index.mjs +44 -43
- package/dist/npm/legacy/bundled/umd/index.js +44 -43
- package/dist/npm/legacy/cjs/index.cjs +44 -43
- package/dist/npm/legacy/content-script/cjs/index.cjs +44 -43
- package/dist/npm/legacy/content-script/esm/index.mjs +44 -43
- package/dist/npm/legacy/content-script/umd/index.js +44 -43
- package/dist/npm/legacy/esm/index.mjs +44 -43
- package/dist/npm/legacy/umd/index.js +44 -43
- package/dist/npm/modern/bundled/cjs/index.cjs +43 -42
- package/dist/npm/modern/bundled/esm/index.mjs +43 -42
- package/dist/npm/modern/bundled/umd/index.js +43 -42
- package/dist/npm/modern/cjs/index.cjs +43 -42
- package/dist/npm/modern/content-script/cjs/index.cjs +43 -42
- package/dist/npm/modern/content-script/esm/index.mjs +43 -42
- package/dist/npm/modern/content-script/umd/index.js +43 -42
- package/dist/npm/modern/esm/index.mjs +43 -42
- package/dist/npm/modern/umd/index.js +43 -42
- package/package.json +1 -1
|
@@ -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.
|
|
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)]);}//
|
|
547
|
-
|
|
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=[];/**
|
|
@@ -653,7 +654,7 @@ const BUILD_TYPE='modern';const SDK_CDN_BASE_URL='https://cdn.rudderlabs.com';co
|
|
|
653
654
|
|
|
654
655
|
const DEFAULT_STORAGE_ENCRYPTION_VERSION='v3';const DEFAULT_DATA_PLANE_EVENTS_TRANSPORT='xhr';const ConsentManagersToPluginNameMap={iubenda:'IubendaConsentManager',oneTrust:'OneTrustConsentManager',ketch:'KetchConsentManager',custom:'CustomConsentManager'};const StorageEncryptionVersionsToPluginNameMap={[DEFAULT_STORAGE_ENCRYPTION_VERSION]:'StorageEncryption',legacy:'StorageEncryptionLegacy'};const DataPlaneEventsTransportToPluginNameMap={[DEFAULT_DATA_PLANE_EVENTS_TRANSPORT]:'XhrQueue',beacon:'BeaconQueue'};const DEFAULT_DATA_SERVICE_ENDPOINT='rsaRequest';const METRICS_SERVICE_ENDPOINT='rsaMetrics';const CUSTOM_DEVICE_MODE_DESTINATION_DISPLAY_NAME='Custom Device Mode';
|
|
655
656
|
|
|
656
|
-
const defaultLoadOptions={configUrl:DEFAULT_CONFIG_BE_URL,loadIntegration:true,sessions:{autoTrack:true,timeout:DEFAULT_SESSION_TIMEOUT_MS,cutOff:{enabled:false}},sameSiteCookie:'Lax',polyfillIfRequired:true,integrations:DEFAULT_INTEGRATIONS_CONFIG,useBeacon:false,beaconQueueOptions:{},destinationsQueueOptions:{},queueOptions:{},lockIntegrationsVersion:
|
|
657
|
+
const defaultLoadOptions={configUrl:DEFAULT_CONFIG_BE_URL,loadIntegration:true,sessions:{autoTrack:true,timeout:DEFAULT_SESSION_TIMEOUT_MS,cutOff:{enabled:false}},sameSiteCookie:'Lax',polyfillIfRequired:true,integrations:DEFAULT_INTEGRATIONS_CONFIG,useBeacon:false,beaconQueueOptions:{},destinationsQueueOptions:{},queueOptions:{},lockIntegrationsVersion:true,lockPluginsVersion:true,uaChTrackLevel:'none',plugins:[],useGlobalIntegrationsConfigInEvents:false,bufferDataPlaneEventsUntilReady:false,dataPlaneEventsBufferTimeout:DEFAULT_DATA_PLANE_EVENTS_BUFFER_TIMEOUT_MS,storage:{encryption:{version:DEFAULT_STORAGE_ENCRYPTION_VERSION},migrate:true,cookie:{}},sendAdblockPage:false,sameDomainCookiesOnly:false,secureCookie:false,sendAdblockPageOptions:{},useServerSideCookies:false};const loadOptionsState=d$1(clone(defaultLoadOptions));
|
|
657
658
|
|
|
658
659
|
const DEFAULT_USER_SESSION_VALUES=deepFreeze({userId:'',userTraits:{},anonymousId:'',groupId:'',groupTraits:{},initialReferrer:'',initialReferringDomain:'',sessionInfo:{},authToken:null});const DEFAULT_RESET_OPTIONS=deepFreeze({entries:{userId:true,userTraits:true,groupId:true,groupTraits:true,sessionInfo:true,authToken:true,// These are not reset by default
|
|
659
660
|
anonymousId:false,initialReferrer:false,initialReferringDomain:false}});const SERVER_SIDE_COOKIES_DEBOUNCE_TIME=10;// milliseconds
|
|
@@ -790,8 +791,8 @@ throw err;}};
|
|
|
790
791
|
const getErrInstance=(err,errorType)=>{switch(errorType){case ErrorType.UNHANDLEDEXCEPTION:{const{error}=err;return error||err;}case ErrorType.UNHANDLEDREJECTION:{return err.reason;}case ErrorType.HANDLEDEXCEPTION:default:return err;}};const createNewBreadcrumb=message=>({type:'manual',name:message,timestamp:new Date(),metaData:{}});/**
|
|
791
792
|
* A function to get the Bugsnag release stage for the current environment
|
|
792
793
|
* @param getHostName Optional function to get the hostname (primarily for testing)
|
|
793
|
-
* @returns 'development' if the host is empty (for file:// protocol etc.) or a dev host (localhost, 127.0.0.1, etc.), otherwise ''
|
|
794
|
-
*/const getReleaseStage=(getHostName=()=>window.location.hostname)=>{const host=getHostName();return !host||host&&DEV_HOSTS.includes(host)?'development':'
|
|
794
|
+
* @returns 'development' if the host is empty (for file:// protocol etc.) or a dev host (localhost, 127.0.0.1, etc.), otherwise ''production'' (it'll be replaced with the actual release stage during the build)
|
|
795
|
+
*/const getReleaseStage=(getHostName=()=>window.location.hostname)=>{const host=getHostName();return !host||host&&DEV_HOSTS.includes(host)?'development':'production';};const getAppStateForMetadata=state=>{const stateStr=stringifyWithoutCircular(state,false,APP_STATE_EXCLUDE_KEYS);return stateStr!==null?JSON.parse(stateStr):{};};const getURLWithoutQueryString=()=>{const url=globalThis.location.href.split('?');return url[0];};const getUserDetails=(source,session,lifecycle,autoTrack)=>({id:`${source.value?.id??lifecycle.writeKey.value}..${session.sessionInfo.value.id??'NA'}..${autoTrack.pageLifecycle.pageViewId.value??'NA'}`,name:source.value?.name??'NA'});const getDeviceDetails=(locale,userAgent)=>({locale:locale.value??'NA',userAgent:userAgent.value??'NA',time:new Date()});const getBugsnagErrorEvent=(exception,errorState,state,groupingHash)=>{const{context,lifecycle,session,source,reporting,autoTrack}=state;const{app,locale,userAgent,timezone,screen,library}=context;return {payloadVersion:'5',notifier:{name:NOTIFIER_NAME,version:app.value.version,url:SDK_GITHUB_URL},events:[{exceptions:[clone(exception)],severity:errorState.severity,unhandled:errorState.unhandled,severityReason:errorState.severityReason,app:{version:app.value.version,releaseStage:getReleaseStage(),type:app.value.installType},device:getDeviceDetails(locale,userAgent),request:{url:getURLWithoutQueryString(),clientIp:'[NOT COLLECTED]'},breadcrumbs:clone(reporting.breadcrumbs.value),context:exception.message,groupingHash,metaData:{app:{snippetVersion:library.value.snippetVersion},device:{...screen.value,timezone:timezone.value},// Add rest of the state groups as metadata
|
|
795
796
|
// so that they show up as separate tabs in the dashboard
|
|
796
797
|
...getAppStateForMetadata(state)},user:getUserDetails(source,session,lifecycle,autoTrack)}]};};/**
|
|
797
798
|
* A function to check if adblockers are active. The promise's resolve function
|
|
@@ -3290,10 +3291,8 @@ enrichedEvent.userId=to??enrichedEvent.userId;return enrichedEvent;}/**
|
|
|
3290
3291
|
*/addEvent(event){this.userSessionManager.refreshSession();const rudderEvent=this.eventFactory.create(event);this.eventRepository.enqueue(rudderEvent,event.callback);}}
|
|
3291
3292
|
|
|
3292
3293
|
class UserSessionManager{/**
|
|
3293
|
-
* Tracks whether
|
|
3294
|
-
|
|
3295
|
-
* Tracks the number of queued cookie set requests
|
|
3296
|
-
*/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={};this.serverSideCookieSetRequests={};}/**
|
|
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={};}/**
|
|
3297
3296
|
* Initialize User session with values from storage
|
|
3298
3297
|
*/init(){this.syncStorageDataToState();// Register the effect to sync with storage
|
|
3299
3298
|
this.registerEffects();}syncStorageDataToState(){this.migrateStorageIfNeeded();this.migrateDataFromPreviousStorage();// get the values from storage and set it again
|
|
@@ -3323,32 +3322,28 @@ cutOffDuration=DEFAULT_SESSION_CUT_OFF_DURATION_MS;}else if(cutOffDuration<sessi
|
|
|
3323
3322
|
* @param callback
|
|
3324
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});}/**
|
|
3325
3324
|
* A function to make an external request to set the cookie from server side
|
|
3326
|
-
* @param key
|
|
3327
|
-
* @param
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
const
|
|
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
|
|
3331
3332
|
this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{// Mark the cookie req status as done
|
|
3332
|
-
clearInProgressFlags();if(details?.xhr?.status===200){
|
|
3333
|
-
|
|
3334
|
-
|
|
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();}}/**
|
|
3335
3340
|
* A function to sync values in storage
|
|
3336
3341
|
* @param sessionKey
|
|
3337
|
-
|
|
3338
|
-
*/syncValueToStorage(sessionKey,stateValue){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;// Determine the final user session entry value
|
|
3339
|
-
const value=stateValue??state.session[sessionKey].value;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
|
|
3340
3343
|
// set the cookie from server side
|
|
3341
3344
|
if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){// Mark the requests as in progress.
|
|
3342
|
-
this.serverSideCookiesRequestInProgress[sessionKey]=true;
|
|
3343
|
-
|
|
3344
|
-
// The first request is sent immediately to prevent events from missing session info.
|
|
3345
|
-
// Subsequent changes within the debounce window are consolidated into a single request
|
|
3346
|
-
// that sends the latest value after the debounce delay. Intermediate values are not persisted.
|
|
3347
|
-
if(!this.serverSideCookieDebounceFuncs[sessionKey]){this.serverSideCookieSetRequests[sessionKey]=0;// For the first time, make the cookie request anyway.
|
|
3348
|
-
setCookieFunc();this.serverSideCookieDebounceFuncs[sessionKey]=globalThis.setTimeout(()=>{delete this.serverSideCookieDebounceFuncs[sessionKey];// In the debounce function, make the cookie request only when cookie requests are waiting
|
|
3349
|
-
// in the queue. The first request would have been sent already.
|
|
3350
|
-
if(this.serverSideCookieSetRequests[sessionKey]>0){setCookieFunc();this.serverSideCookieSetRequests[sessionKey]=0;}},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {// Increment the queued cookie set actions
|
|
3351
|
-
this.serverSideCookieSetRequests[sessionKey]+=1;}}else {curStore?.set(key,value);}}else {curStore?.remove(key);}}}/**
|
|
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);}}}/**
|
|
3352
3347
|
* Function to update storage whenever state value changes
|
|
3353
3348
|
*/registerEffects(){// This will work as long as the user session entry key names are same as the state keys
|
|
3354
3349
|
USER_SESSION_KEYS.forEach(sessionKey=>{E(()=>{this.syncValueToStorage(sessionKey);});});}/**
|
|
@@ -3368,37 +3363,43 @@ const autoCapturedAnonymousId=this.pluginsManager?.invokeSingle('storage.getAnon
|
|
|
3368
3363
|
// This is needed for entries that are fetched from the storage
|
|
3369
3364
|
// during the current session (for example, session info)
|
|
3370
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);}/**
|
|
3371
3373
|
* Fetches User Id
|
|
3372
3374
|
* @returns
|
|
3373
|
-
*/getUserId(){return this.
|
|
3375
|
+
*/getUserId(){return this.getUserSessionValue('userId');}/**
|
|
3374
3376
|
* Fetches User Traits
|
|
3375
3377
|
* @returns
|
|
3376
|
-
*/getUserTraits(){return this.
|
|
3378
|
+
*/getUserTraits(){return this.getUserSessionValue('userTraits');}/**
|
|
3377
3379
|
* Fetches Group Id
|
|
3378
3380
|
* @returns
|
|
3379
|
-
*/getGroupId(){return this.
|
|
3381
|
+
*/getGroupId(){return this.getUserSessionValue('groupId');}/**
|
|
3380
3382
|
* Fetches Group Traits
|
|
3381
3383
|
* @returns
|
|
3382
|
-
*/getGroupTraits(){return this.
|
|
3384
|
+
*/getGroupTraits(){return this.getUserSessionValue('groupTraits');}/**
|
|
3383
3385
|
* Fetches Initial Referrer
|
|
3384
3386
|
* @returns
|
|
3385
|
-
*/getInitialReferrer(){return this.
|
|
3387
|
+
*/getInitialReferrer(){return this.getUserSessionValue('initialReferrer');}/**
|
|
3386
3388
|
* Fetches Initial Referring domain
|
|
3387
3389
|
* @returns
|
|
3388
|
-
*/getInitialReferringDomain(){return this.
|
|
3390
|
+
*/getInitialReferringDomain(){return this.getUserSessionValue('initialReferringDomain');}/**
|
|
3389
3391
|
* Fetches session tracking information from storage
|
|
3390
3392
|
* @returns
|
|
3391
|
-
*/getSessionInfo(){return this.
|
|
3393
|
+
*/getSessionInfo(){return this.getUserSessionValue('sessionInfo');}/**
|
|
3392
3394
|
* Fetches auth token from storage
|
|
3393
3395
|
* @returns
|
|
3394
|
-
*/getAuthToken(){return this.
|
|
3396
|
+
*/getAuthToken(){return this.getUserSessionValue('authToken');}/**
|
|
3395
3397
|
* If session is active it returns the sessionId
|
|
3396
3398
|
* @returns
|
|
3397
3399
|
*/getSessionId(){const sessionInfo=this.getSessionInfo()??DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack&&!hasSessionExpired(sessionInfo)||sessionInfo.manualTrack){return sessionInfo.id??null;}return null;}/**
|
|
3398
3400
|
* A function to keep the session information up to date in the state
|
|
3399
3401
|
* before using it for building event payloads.
|
|
3400
|
-
*/refreshSession(){let
|
|
3401
|
-
if(initialSessionInfo===null&&this.serverSideCookiesRequestInProgress['sessionInfo']){initialSessionInfo=state.session.sessionInfo.value;}let sessionInfo=initialSessionInfo??DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack||sessionInfo.manualTrack){if(sessionInfo.autoTrack){this.startOrRenewAutoTracking(sessionInfo);sessionInfo=state.session.sessionInfo.value;}// Note that if sessionStart is false, then it's an active session.
|
|
3402
|
+
*/refreshSession(){let sessionInfo=this.getSessionInfo()??DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack||sessionInfo.manualTrack){if(sessionInfo.autoTrack){this.startOrRenewAutoTracking(sessionInfo);sessionInfo=state.session.sessionInfo.value;}// Note that if sessionStart is false, then it's an active session.
|
|
3402
3403
|
// So, we needn't update the session info.
|
|
3403
3404
|
//
|
|
3404
3405
|
// For other scenarios,
|
|
@@ -3408,7 +3409,7 @@ if(initialSessionInfo===null&&this.serverSideCookiesRequestInProgress['sessionIn
|
|
|
3408
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.
|
|
3409
3410
|
state.session.sessionInfo.value=sessionInfo;if(state.lifecycle.status.value!=='readyExecuted'){// Force update the storage as the 'effect' blocks are not getting triggered
|
|
3410
3411
|
// when processing preload buffered requests
|
|
3411
|
-
this.syncValueToStorage('sessionInfo'
|
|
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();}}/**
|
|
3412
3413
|
* Reset state values
|
|
3413
3414
|
* @param options options for reset
|
|
3414
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.
|
|
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)]);}//
|
|
553
|
-
|
|
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=[];/**
|
|
@@ -659,7 +660,7 @@
|
|
|
659
660
|
|
|
660
661
|
const DEFAULT_STORAGE_ENCRYPTION_VERSION='v3';const DEFAULT_DATA_PLANE_EVENTS_TRANSPORT='xhr';const ConsentManagersToPluginNameMap={iubenda:'IubendaConsentManager',oneTrust:'OneTrustConsentManager',ketch:'KetchConsentManager',custom:'CustomConsentManager'};const StorageEncryptionVersionsToPluginNameMap={[DEFAULT_STORAGE_ENCRYPTION_VERSION]:'StorageEncryption',legacy:'StorageEncryptionLegacy'};const DataPlaneEventsTransportToPluginNameMap={[DEFAULT_DATA_PLANE_EVENTS_TRANSPORT]:'XhrQueue',beacon:'BeaconQueue'};const DEFAULT_DATA_SERVICE_ENDPOINT='rsaRequest';const METRICS_SERVICE_ENDPOINT='rsaMetrics';const CUSTOM_DEVICE_MODE_DESTINATION_DISPLAY_NAME='Custom Device Mode';
|
|
661
662
|
|
|
662
|
-
const defaultLoadOptions={configUrl:DEFAULT_CONFIG_BE_URL,loadIntegration:true,sessions:{autoTrack:true,timeout:DEFAULT_SESSION_TIMEOUT_MS,cutOff:{enabled:false}},sameSiteCookie:'Lax',polyfillIfRequired:true,integrations:DEFAULT_INTEGRATIONS_CONFIG,useBeacon:false,beaconQueueOptions:{},destinationsQueueOptions:{},queueOptions:{},lockIntegrationsVersion:
|
|
663
|
+
const defaultLoadOptions={configUrl:DEFAULT_CONFIG_BE_URL,loadIntegration:true,sessions:{autoTrack:true,timeout:DEFAULT_SESSION_TIMEOUT_MS,cutOff:{enabled:false}},sameSiteCookie:'Lax',polyfillIfRequired:true,integrations:DEFAULT_INTEGRATIONS_CONFIG,useBeacon:false,beaconQueueOptions:{},destinationsQueueOptions:{},queueOptions:{},lockIntegrationsVersion:true,lockPluginsVersion:true,uaChTrackLevel:'none',plugins:[],useGlobalIntegrationsConfigInEvents:false,bufferDataPlaneEventsUntilReady:false,dataPlaneEventsBufferTimeout:DEFAULT_DATA_PLANE_EVENTS_BUFFER_TIMEOUT_MS,storage:{encryption:{version:DEFAULT_STORAGE_ENCRYPTION_VERSION},migrate:true,cookie:{}},sendAdblockPage:false,sameDomainCookiesOnly:false,secureCookie:false,sendAdblockPageOptions:{},useServerSideCookies:false};const loadOptionsState=d$1(clone(defaultLoadOptions));
|
|
663
664
|
|
|
664
665
|
const DEFAULT_USER_SESSION_VALUES=deepFreeze({userId:'',userTraits:{},anonymousId:'',groupId:'',groupTraits:{},initialReferrer:'',initialReferringDomain:'',sessionInfo:{},authToken:null});const DEFAULT_RESET_OPTIONS=deepFreeze({entries:{userId:true,userTraits:true,groupId:true,groupTraits:true,sessionInfo:true,authToken:true,// These are not reset by default
|
|
665
666
|
anonymousId:false,initialReferrer:false,initialReferringDomain:false}});const SERVER_SIDE_COOKIES_DEBOUNCE_TIME=10;// milliseconds
|
|
@@ -796,8 +797,8 @@
|
|
|
796
797
|
const getErrInstance=(err,errorType)=>{switch(errorType){case ErrorType.UNHANDLEDEXCEPTION:{const{error}=err;return error||err;}case ErrorType.UNHANDLEDREJECTION:{return err.reason;}case ErrorType.HANDLEDEXCEPTION:default:return err;}};const createNewBreadcrumb=message=>({type:'manual',name:message,timestamp:new Date(),metaData:{}});/**
|
|
797
798
|
* A function to get the Bugsnag release stage for the current environment
|
|
798
799
|
* @param getHostName Optional function to get the hostname (primarily for testing)
|
|
799
|
-
* @returns 'development' if the host is empty (for file:// protocol etc.) or a dev host (localhost, 127.0.0.1, etc.), otherwise ''
|
|
800
|
-
*/const getReleaseStage=(getHostName=()=>window.location.hostname)=>{const host=getHostName();return !host||host&&DEV_HOSTS.includes(host)?'development':'
|
|
800
|
+
* @returns 'development' if the host is empty (for file:// protocol etc.) or a dev host (localhost, 127.0.0.1, etc.), otherwise ''production'' (it'll be replaced with the actual release stage during the build)
|
|
801
|
+
*/const getReleaseStage=(getHostName=()=>window.location.hostname)=>{const host=getHostName();return !host||host&&DEV_HOSTS.includes(host)?'development':'production';};const getAppStateForMetadata=state=>{const stateStr=stringifyWithoutCircular(state,false,APP_STATE_EXCLUDE_KEYS);return stateStr!==null?JSON.parse(stateStr):{};};const getURLWithoutQueryString=()=>{const url=globalThis.location.href.split('?');return url[0];};const getUserDetails=(source,session,lifecycle,autoTrack)=>({id:`${source.value?.id??lifecycle.writeKey.value}..${session.sessionInfo.value.id??'NA'}..${autoTrack.pageLifecycle.pageViewId.value??'NA'}`,name:source.value?.name??'NA'});const getDeviceDetails=(locale,userAgent)=>({locale:locale.value??'NA',userAgent:userAgent.value??'NA',time:new Date()});const getBugsnagErrorEvent=(exception,errorState,state,groupingHash)=>{const{context,lifecycle,session,source,reporting,autoTrack}=state;const{app,locale,userAgent,timezone,screen,library}=context;return {payloadVersion:'5',notifier:{name:NOTIFIER_NAME,version:app.value.version,url:SDK_GITHUB_URL},events:[{exceptions:[clone(exception)],severity:errorState.severity,unhandled:errorState.unhandled,severityReason:errorState.severityReason,app:{version:app.value.version,releaseStage:getReleaseStage(),type:app.value.installType},device:getDeviceDetails(locale,userAgent),request:{url:getURLWithoutQueryString(),clientIp:'[NOT COLLECTED]'},breadcrumbs:clone(reporting.breadcrumbs.value),context:exception.message,groupingHash,metaData:{app:{snippetVersion:library.value.snippetVersion},device:{...screen.value,timezone:timezone.value},// Add rest of the state groups as metadata
|
|
801
802
|
// so that they show up as separate tabs in the dashboard
|
|
802
803
|
...getAppStateForMetadata(state)},user:getUserDetails(source,session,lifecycle,autoTrack)}]};};/**
|
|
803
804
|
* A function to check if adblockers are active. The promise's resolve function
|
|
@@ -3296,10 +3297,8 @@
|
|
|
3296
3297
|
*/addEvent(event){this.userSessionManager.refreshSession();const rudderEvent=this.eventFactory.create(event);this.eventRepository.enqueue(rudderEvent,event.callback);}}
|
|
3297
3298
|
|
|
3298
3299
|
class UserSessionManager{/**
|
|
3299
|
-
* Tracks whether
|
|
3300
|
-
|
|
3301
|
-
* Tracks the number of queued cookie set requests
|
|
3302
|
-
*/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={};this.serverSideCookieSetRequests={};}/**
|
|
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={};}/**
|
|
3303
3302
|
* Initialize User session with values from storage
|
|
3304
3303
|
*/init(){this.syncStorageDataToState();// Register the effect to sync with storage
|
|
3305
3304
|
this.registerEffects();}syncStorageDataToState(){this.migrateStorageIfNeeded();this.migrateDataFromPreviousStorage();// get the values from storage and set it again
|
|
@@ -3329,32 +3328,28 @@
|
|
|
3329
3328
|
* @param callback
|
|
3330
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});}/**
|
|
3331
3330
|
* A function to make an external request to set the cookie from server side
|
|
3332
|
-
* @param key
|
|
3333
|
-
* @param
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
const
|
|
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
|
|
3337
3338
|
this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{// Mark the cookie req status as done
|
|
3338
|
-
clearInProgressFlags();if(details?.xhr?.status===200){
|
|
3339
|
-
|
|
3340
|
-
|
|
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();}}/**
|
|
3341
3346
|
* A function to sync values in storage
|
|
3342
3347
|
* @param sessionKey
|
|
3343
|
-
|
|
3344
|
-
*/syncValueToStorage(sessionKey,stateValue){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;// Determine the final user session entry value
|
|
3345
|
-
const value=stateValue??state.session[sessionKey].value;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
|
|
3346
3349
|
// set the cookie from server side
|
|
3347
3350
|
if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){// Mark the requests as in progress.
|
|
3348
|
-
this.serverSideCookiesRequestInProgress[sessionKey]=true;
|
|
3349
|
-
|
|
3350
|
-
// The first request is sent immediately to prevent events from missing session info.
|
|
3351
|
-
// Subsequent changes within the debounce window are consolidated into a single request
|
|
3352
|
-
// that sends the latest value after the debounce delay. Intermediate values are not persisted.
|
|
3353
|
-
if(!this.serverSideCookieDebounceFuncs[sessionKey]){this.serverSideCookieSetRequests[sessionKey]=0;// For the first time, make the cookie request anyway.
|
|
3354
|
-
setCookieFunc();this.serverSideCookieDebounceFuncs[sessionKey]=globalThis.setTimeout(()=>{delete this.serverSideCookieDebounceFuncs[sessionKey];// In the debounce function, make the cookie request only when cookie requests are waiting
|
|
3355
|
-
// in the queue. The first request would have been sent already.
|
|
3356
|
-
if(this.serverSideCookieSetRequests[sessionKey]>0){setCookieFunc();this.serverSideCookieSetRequests[sessionKey]=0;}},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {// Increment the queued cookie set actions
|
|
3357
|
-
this.serverSideCookieSetRequests[sessionKey]+=1;}}else {curStore?.set(key,value);}}else {curStore?.remove(key);}}}/**
|
|
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);}}}/**
|
|
3358
3353
|
* Function to update storage whenever state value changes
|
|
3359
3354
|
*/registerEffects(){// This will work as long as the user session entry key names are same as the state keys
|
|
3360
3355
|
USER_SESSION_KEYS.forEach(sessionKey=>{E(()=>{this.syncValueToStorage(sessionKey);});});}/**
|
|
@@ -3374,37 +3369,43 @@
|
|
|
3374
3369
|
// This is needed for entries that are fetched from the storage
|
|
3375
3370
|
// during the current session (for example, session info)
|
|
3376
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);}/**
|
|
3377
3379
|
* Fetches User Id
|
|
3378
3380
|
* @returns
|
|
3379
|
-
*/getUserId(){return this.
|
|
3381
|
+
*/getUserId(){return this.getUserSessionValue('userId');}/**
|
|
3380
3382
|
* Fetches User Traits
|
|
3381
3383
|
* @returns
|
|
3382
|
-
*/getUserTraits(){return this.
|
|
3384
|
+
*/getUserTraits(){return this.getUserSessionValue('userTraits');}/**
|
|
3383
3385
|
* Fetches Group Id
|
|
3384
3386
|
* @returns
|
|
3385
|
-
*/getGroupId(){return this.
|
|
3387
|
+
*/getGroupId(){return this.getUserSessionValue('groupId');}/**
|
|
3386
3388
|
* Fetches Group Traits
|
|
3387
3389
|
* @returns
|
|
3388
|
-
*/getGroupTraits(){return this.
|
|
3390
|
+
*/getGroupTraits(){return this.getUserSessionValue('groupTraits');}/**
|
|
3389
3391
|
* Fetches Initial Referrer
|
|
3390
3392
|
* @returns
|
|
3391
|
-
*/getInitialReferrer(){return this.
|
|
3393
|
+
*/getInitialReferrer(){return this.getUserSessionValue('initialReferrer');}/**
|
|
3392
3394
|
* Fetches Initial Referring domain
|
|
3393
3395
|
* @returns
|
|
3394
|
-
*/getInitialReferringDomain(){return this.
|
|
3396
|
+
*/getInitialReferringDomain(){return this.getUserSessionValue('initialReferringDomain');}/**
|
|
3395
3397
|
* Fetches session tracking information from storage
|
|
3396
3398
|
* @returns
|
|
3397
|
-
*/getSessionInfo(){return this.
|
|
3399
|
+
*/getSessionInfo(){return this.getUserSessionValue('sessionInfo');}/**
|
|
3398
3400
|
* Fetches auth token from storage
|
|
3399
3401
|
* @returns
|
|
3400
|
-
*/getAuthToken(){return this.
|
|
3402
|
+
*/getAuthToken(){return this.getUserSessionValue('authToken');}/**
|
|
3401
3403
|
* If session is active it returns the sessionId
|
|
3402
3404
|
* @returns
|
|
3403
3405
|
*/getSessionId(){const sessionInfo=this.getSessionInfo()??DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack&&!hasSessionExpired(sessionInfo)||sessionInfo.manualTrack){return sessionInfo.id??null;}return null;}/**
|
|
3404
3406
|
* A function to keep the session information up to date in the state
|
|
3405
3407
|
* before using it for building event payloads.
|
|
3406
|
-
*/refreshSession(){let
|
|
3407
|
-
if(initialSessionInfo===null&&this.serverSideCookiesRequestInProgress['sessionInfo']){initialSessionInfo=state.session.sessionInfo.value;}let sessionInfo=initialSessionInfo??DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack||sessionInfo.manualTrack){if(sessionInfo.autoTrack){this.startOrRenewAutoTracking(sessionInfo);sessionInfo=state.session.sessionInfo.value;}// Note that if sessionStart is false, then it's an active session.
|
|
3408
|
+
*/refreshSession(){let sessionInfo=this.getSessionInfo()??DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack||sessionInfo.manualTrack){if(sessionInfo.autoTrack){this.startOrRenewAutoTracking(sessionInfo);sessionInfo=state.session.sessionInfo.value;}// Note that if sessionStart is false, then it's an active session.
|
|
3408
3409
|
// So, we needn't update the session info.
|
|
3409
3410
|
//
|
|
3410
3411
|
// For other scenarios,
|
|
@@ -3414,7 +3415,7 @@
|
|
|
3414
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.
|
|
3415
3416
|
state.session.sessionInfo.value=sessionInfo;if(state.lifecycle.status.value!=='readyExecuted'){// Force update the storage as the 'effect' blocks are not getting triggered
|
|
3416
3417
|
// when processing preload buffered requests
|
|
3417
|
-
this.syncValueToStorage('sessionInfo'
|
|
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();}}/**
|
|
3418
3419
|
* Reset state values
|
|
3419
3420
|
* @param options options for reset
|
|
3420
3421
|
* @returns
|