diff --git a/common/changes/@snowplow/browser-tracker-core/issue-bcpf-1813-stratchange-resume_2025-05-23-06-07.json b/common/changes/@snowplow/browser-tracker-core/issue-bcpf-1813-stratchange-resume_2025-05-23-06-07.json new file mode 100644 index 000000000..00643a1a4 --- /dev/null +++ b/common/changes/@snowplow/browser-tracker-core/issue-bcpf-1813-stratchange-resume_2025-05-23-06-07.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@snowplow/browser-tracker-core", + "comment": "Resume sessions when disabling anonymous tracking that was already tracking session state", + "type": "none" + } + ], + "packageName": "@snowplow/browser-tracker-core" +} \ No newline at end of file diff --git a/common/changes/@snowplow/javascript-tracker/issue-bcpf-1813-stratchange-resume_2025-05-23-08-06.json b/common/changes/@snowplow/javascript-tracker/issue-bcpf-1813-stratchange-resume_2025-05-23-08-06.json new file mode 100644 index 000000000..0a3904cb2 --- /dev/null +++ b/common/changes/@snowplow/javascript-tracker/issue-bcpf-1813-stratchange-resume_2025-05-23-08-06.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@snowplow/javascript-tracker", + "comment": "Resume sessions when disabling anonymous tracking that was already tracking session state", + "type": "none" + } + ], + "packageName": "@snowplow/javascript-tracker" +} \ No newline at end of file diff --git a/libraries/browser-tracker-core/src/tracker/index.ts b/libraries/browser-tracker-core/src/tracker/index.ts index 13934b401..4bd868d8d 100755 --- a/libraries/browser-tracker-core/src/tracker/index.ts +++ b/libraries/browser-tracker-core/src/tracker/index.ts @@ -1379,10 +1379,23 @@ export function Tracker( }, disableAnonymousTracking: function (configuration?: DisableAnonymousTrackingConfiguration) { + /* + Flag for if the state storage strategy has changed and we are currently storing session state (anonymously or not). + Because the strategy changes, the below call to initializeIdsAndCookies will fail to see that a session is currently in progress and start a new one. + Detect this state, and once we've updated settings, bump the session cookie with the new strategy to ensure it exists before loading the ID cookie, which will resume the session. + */ + const shouldResumeSession = + configuration?.stateStorageStrategy && // a new strategy was defined (otherwise will already resume) + configuration.stateStorageStrategy !== configStateStorageStrategy && // new strategy is different to old one (otherwise will already resume) + (!configAnonymousTracking || configAnonymousSessionTracking) && // we were previously tracking session IDs (otherwise nothing to resume) + getSnowplowCookieValue('ses'); // and we currently have a session in progress (otherwise we want a new session anyway) + trackerConfiguration.anonymousTracking = false; toggleAnonymousTracking(configuration); + if (shouldResumeSession) setSessionCookie(); // ensure session cookie exists with new strategy + initializeIdsAndCookies(); outQueue.executeQueue(); // There might be some events in the queue we've been unable to send in anonymous mode diff --git a/trackers/javascript-tracker/test/integration/sessionStorage.test.ts b/trackers/javascript-tracker/test/integration/sessionStorage.test.ts index 04d3046aa..db538de02 100644 --- a/trackers/javascript-tracker/test/integration/sessionStorage.test.ts +++ b/trackers/javascript-tracker/test/integration/sessionStorage.test.ts @@ -181,7 +181,20 @@ describe('Sessions', () => { log ) ) - ).toBe(3); + ).toBe(4); + expect( + F.size( + F.uniqBy( + F.get('event.domain_sessionid'), + F.filter( + (e) => + F.get('event.name_tracker', e) === 'anonymousSessionTracker' && + F.get('event.app_id', e) === 'session-integration-' + testIdentifier, + log + ) + ) + ) + ).toBe(2); }); it('should only increment domain_sessionidx outside of session timeout (cookie storage)', () => { diff --git a/trackers/javascript-tracker/test/pages/session-integration.html b/trackers/javascript-tracker/test/pages/session-integration.html index c63d738ea..f517ca369 100644 --- a/trackers/javascript-tracker/test/pages/session-integration.html +++ b/trackers/javascript-tracker/test/pages/session-integration.html @@ -52,7 +52,7 @@ window.snowplow('newTracker', 'anonymousSessionTracker', collector_endpoint, { appId: 'session-integration-' + testIdentifier, - cookieName: testIdentifier, + cookieName: testIdentifier + 'anon', sessionCookieTimeout: 1, stateStorageStrategy: 'localStorage', anonymousTracking: { withSessionTracking: true }, @@ -60,13 +60,17 @@ const currentUrl = window.location.href; const url = new URL(currentUrl); - if (url.searchParams.has("delayed")) { + if (url.searchParams.has('delayed')) { setTimeout(function () { window.snowplow('trackPageView:cookieSessionTracker'); window.snowplow('trackPageView:localStorageSessionTracker'); window.snowplow('trackPageView:anonymousSessionTracker'); + window.snowplow('disableAnonymousTracking:anonymousSessionTracker', { + stateStorageStrategy: 'cookieAndLocalStorage', + }); + window.snowplow('trackPageView:anonymousSessionTracker'); }, 0); } else { setTimeout(function () { @@ -81,7 +85,7 @@ }, 0); setTimeout(function () { - url.searchParams.set("delayed", "1"); + url.searchParams.set('delayed', '1'); window.location.href = url.toString(); }, 3000); }