|
/** |
|
* Parses GA4 cookies using a measurement ID without polluting the global namespace |
|
* @param {string} measurementId - GA4 measurement ID (e.g., 'G-XXXXXXXX') |
|
* @returns {Object|null} Parsed GA4 cookie data or null if cookies not found |
|
*/ |
|
function parseGA4Cookies(measurementId) { |
|
function getCookieValue(name) { |
|
const match = document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)'); |
|
return match ? match.pop() : null; |
|
} |
|
|
|
// Validate measurement ID |
|
if (!measurementId || typeof measurementId !== 'string') { |
|
console.error('Invalid measurement ID'); |
|
return null; |
|
} |
|
|
|
// Extract ID suffix |
|
const parts = measurementId.split('-'); |
|
if (parts.length !== 2 || !parts[1]) { |
|
console.error('Invalid measurement ID format. Expected: G-XXXXXXXX'); |
|
return null; |
|
} |
|
const idSuffix = parts[1]; |
|
|
|
// Get the cookies |
|
const gaCookie = getCookieValue('_ga'); |
|
const ga4Cookie = getCookieValue(`_ga_${idSuffix}`); |
|
|
|
if (!ga4Cookie) { |
|
return null; |
|
} |
|
|
|
// Parse GA4 cookie |
|
const cookieParts = ga4Cookie.split('.'); |
|
if (cookieParts.length < 6) { |
|
return null; |
|
} |
|
|
|
// Build result object |
|
const result = { |
|
measurementId: measurementId, |
|
streamType: cookieParts[0], |
|
hostnameSegments: parseInt(cookieParts[1], 10) || 0, |
|
sessionStartTimestamp: new Date(parseInt(cookieParts[2], 10) * 1000 || 0).toISOString(), |
|
sessionsCount: parseInt(cookieParts[3], 10) || 0, |
|
sessionEngaged: cookieParts[4] === '1', |
|
latestHitTimestamp: new Date(parseInt(cookieParts[5], 10) * 1000 || 0).toISOString() |
|
}; |
|
|
|
// Add enhanced user ID if available |
|
if (cookieParts.length > 8 && cookieParts[8]) { |
|
result.enhancedUserId = isNaN(cookieParts[8]) ? cookieParts[8] : parseInt(cookieParts[8], 10); |
|
} |
|
|
|
// Extract client ID from _ga cookie if available |
|
if (gaCookie) { |
|
const match = gaCookie.match(/^[^.]*\.[^.]*\.(.*)$/); |
|
if (match && match[1]) { |
|
const clientId = match[1]; |
|
result.clientId = clientId; |
|
|
|
const timestampPart = clientId.split('.')[1]; |
|
if (timestampPart && !isNaN(timestampPart)) { |
|
result.firstVisitTimestamp = new Date(parseInt(timestampPart, 10) * 1000).toISOString(); |
|
} |
|
} |
|
} |
|
|
|
return result; |
|
} |