Skip to content

fix(packages/sui-segment-wrapper): fix ga4 session id inconsistencies#1978

Merged
kikoruiz merged 2 commits intomasterfrom
fix-ga4-session-inconsistencies
Mar 30, 2026
Merged

fix(packages/sui-segment-wrapper): fix ga4 session id inconsistencies#1978
kikoruiz merged 2 commits intomasterfrom
fix-ga4-session-inconsistencies

Conversation

@kikoruiz
Copy link
Copy Markdown
Member

What

Fix GA4 session ID inconsistencies and remove Adobe Analytics integration while maintaining backwards compatibility.

Why

  • GA4 was showing 33% "Others" (unassigned sessions) due to session ID mismatches between client-side and server-side tracking
  • "sui" event was firing multiple times per session
  • Events were being sent to Segment without valid sessionIds
  • Adobe Analytics integration is no longer used

Changes

GA4 Session Management

  • Wait for GA4 cookie to be available before sending events to Segment
  • Block GA4 destination entirely when sessionId is not available (instead of sending null)
  • Only fire "sui" event on new sessions using localStorage detection
  • Ensure same sessionId is used for both "sui" event and Segment events

Adobe Analytics Removal

  • Removed Adobe Analytics implementation files
  • Removed Adobe-related tests and fixtures
  • Created stub functions for backwards compatibility (getAdobeVisitorData, getAdobeMCVisitorID)
  • Deprecated functions return empty promises to avoid breaking changes

Testing

  • ✅ All 111 tests passing
  • ✅ Linting passes
  • ✅ Backwards compatible - existing imports won't break

@tomasmax
Copy link
Copy Markdown
Contributor

Code review

Found 2 issues:

  1. Cookie regex /\.s(\d+)/ will always return null on real GA4 cookies — The regex expects a literal .s prefix before the session ID digits (e.g. GS1.1.s1234567890…), but the standard GA4 _ga_* cookie format from Google is GS1.1.<sessionId>.<timestamp>… with no s prefix. The test stubs in stubs.js artificially include the s prefix, masking this mismatch. The function's own JSDoc on line 9 also documents the format without the s prefix (GS1.1.<sessionId>.<timestamp>...), contradicting the regex. In production, against real browser-set GA4 cookies, getGA4SessionIdFromCookie will consistently return null, and GA4 will be disabled for every Segment event — making the fix ineffective.

/**
* Reads the GA4 session ID directly from the cookie.
* The cookie format is: _ga_<CONTAINER_ID>=GS1.1.<sessionId>.<timestamp>...
*
* @param {string} cookiePrefix - Cookie prefix configured in GA4 (e.g., 'segment')
* @returns {string|null} The session ID or null if not found
*/
export function getGA4SessionIdFromCookie(cookiePrefix = 'segment') {
const cookies = document.cookie.split(';')
const sessionRegex = /\.s(\d+)/
const searchStr = cookiePrefix ? `${cookiePrefix}_ga_` : '_ga_'

  1. console.log / console.warn in production hot path — Three console calls (all behind eslint-disable-next-line no-console suppressions) are left in getGoogleSessionId and triggerGoogleAnalyticsInitEvent. The project's ESLint config explicitly bans them (hence the suppressions), and prior commits removed similar logging from this file. These will appear in production browser consoles on every new session start and every time the GA4 cookie is absent.

// eslint-disable-next-line no-console
console.log(`Sending GA4 event "${eventName}" for the session "${sessionId}"`)

triggerGoogleAnalyticsInitEvent(cookieSessionId, true)
// eslint-disable-next-line no-console
console.log(`New GA4 session started: ${cookieSessionId} (Source: Cookie)`)
}
} else {
// Cookie still not available even after waiting
// eslint-disable-next-line no-console
console.warn('GA4 cookie not available after waiting. SessionId will not be sent to Segment.')
}

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@kikoruiz
Copy link
Copy Markdown
Member Author

Code review

Found 2 issues:

  1. Cookie regex /\.s(\d+)/ will always return null on real GA4 cookies — The regex expects a literal .s prefix before the session ID digits (e.g. GS1.1.s1234567890…), but the standard GA4 _ga_* cookie format from Google is GS1.1.<sessionId>.<timestamp>… with no s prefix. The test stubs in stubs.js artificially include the s prefix, masking this mismatch. The function's own JSDoc on line 9 also documents the format without the s prefix (GS1.1.<sessionId>.<timestamp>...), contradicting the regex. In production, against real browser-set GA4 cookies, getGA4SessionIdFromCookie will consistently return null, and GA4 will be disabled for every Segment event — making the fix ineffective.

/**
* Reads the GA4 session ID directly from the cookie.
* The cookie format is: _ga_<CONTAINER_ID>=GS1.1.<sessionId>.<timestamp>...
*
* @param {string} cookiePrefix - Cookie prefix configured in GA4 (e.g., 'segment')
* @returns {string|null} The session ID or null if not found
*/
export function getGA4SessionIdFromCookie(cookiePrefix = 'segment') {
const cookies = document.cookie.split(';')
const sessionRegex = /\.s(\d+)/
const searchStr = cookiePrefix ? `${cookiePrefix}_ga_` : '_ga_'

  1. console.log / console.warn in production hot path — Three console calls (all behind eslint-disable-next-line no-console suppressions) are left in getGoogleSessionId and triggerGoogleAnalyticsInitEvent. The project's ESLint config explicitly bans them (hence the suppressions), and prior commits removed similar logging from this file. These will appear in production browser consoles on every new session start and every time the GA4 cookie is absent.

// eslint-disable-next-line no-console
console.log(`Sending GA4 event "${eventName}" for the session "${sessionId}"`)

triggerGoogleAnalyticsInitEvent(cookieSessionId, true)
// eslint-disable-next-line no-console
console.log(`New GA4 session started: ${cookieSessionId} (Source: Cookie)`)
}
} else {
// Cookie still not available even after waiting
// eslint-disable-next-line no-console
console.warn('GA4 cookie not available after waiting. SessionId will not be sent to Segment.')
}

🤖 Generated with Claude Code

  • If this code review was useful, please react with 👍. Otherwise, react with 👎.

Console calls are OK for now since we need to debug the actual behavior in production, and the cookie regex has been extra documented and also more tested since it really works fine for the GA4 cookie format in production.

@kikoruiz kikoruiz merged commit 4e8e966 into master Mar 30, 2026
2 checks passed
@kikoruiz kikoruiz deleted the fix-ga4-session-inconsistencies branch March 30, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants