/**
* Aluvii Conversion Tracking Script
* Handles cross-domain tracking between landing pages and store domains
*/
(function() {
'use strict';
// Configuration
const CONFIG = {
tidParam: 'atc',
cookieName: 'aluvii_atc',
cookieExpireDays: 10,
targetDomain: '.aluvii.com'
};
console.log("Aluvii GMM v1.0.0", CONFIG);
/**
* Get URL parameter value by name
* @param {string} name - Parameter name
* @param {string} url - URL to search (defaults to current URL)
* @returns {string|null} Parameter value or null if not found
*/
function getUrlParameter(name, url = window.location.href) {
const urlObj = new URL(url);
return urlObj.searchParams.get(name);
}
/**
* Set cookie with specified name, value, and expiration
* @param {string} name - Cookie name
* @param {string} value - Cookie value
* @param {number} days - Days until expiration
*/
function setCookie(name, value, days) {
const expires = new Date();
expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000));
// Set cookie for current domain and .aluvii.com
const cookieString = `${name}=${value}; expires=${expires.toUTCString()}; path=/; SameSite=Lax`;
document.cookie = cookieString;
// Also try to set for .aluvii.com domain if we're on a subdomain
if (window.location.hostname.includes('aluvii.com')) {
document.cookie = `${cookieString}; domain=.aluvii.com`;
}
}
/**
* Get cookie value by name
* @param {string} name - Cookie name
* @returns {string|null} Cookie value or null if not found
*/
function getCookie(name) {
const nameEQ = name + "=";
const cookies = document.cookie.split(';');
for (let cookie of cookies) {
cookie = cookie.trim();
if (cookie.indexOf(nameEQ) === 0) {
return cookie.substring(nameEQ.length);
}
}
return null;
}
/**
* Check if URL points to current domain or .aluvii.com subdomain
* @param {string} url - URL to check
* @returns {boolean} True if URL should be tagged
*/
function shouldTagUrl(url) {
try {
const urlObj = new URL(url, window.location.origin);
const hostname = urlObj.hostname.toLowerCase();
const currentHostname = window.location.hostname.toLowerCase();
// Same domain
if (hostname === currentHostname) {
return true;
}
// .aluvii.com subdomain
if (hostname.endsWith(CONFIG.targetDomain)) {
return true;
}
return false;
} catch (e) {
// Invalid URL, skip
return false;
}
}
/**
* Add or update tracking ID parameter in URL
* @param {string} url - Original URL
* @param {string} trackingId - Tracking ID to append
* @returns {string} Modified URL with tracking ID
*/
function addTrackingIdToUrl(url, trackingId) {
try {
const urlObj = new URL(url, window.location.origin);
urlObj.searchParams.set(CONFIG.tidParam, trackingId);
return urlObj.toString();
} catch (e) {
// If URL parsing fails, return original URL
console.warn('Failed to parse URL for tracking:', url);
return url;
}
}
/**
* Tag all relevant links on the page with tracking ID
* @param {string} trackingId - Tracking ID to append
*/
function tagLinks(trackingId) {
if (!trackingId) return;
const links = document.querySelectorAll('a[href]');
links.forEach(link => {
const href = link.getAttribute('href');
// Skip if href is empty, javascript:, mailto:, tel:, etc.
if (!href ||
href.startsWith('javascript:') ||
href.startsWith('mailto:') ||
href.startsWith('tel:') ||
href.startsWith('#')) {
return;
}
if (shouldTagUrl(href)) {
const newHref = addTrackingIdToUrl(href, trackingId);
link.setAttribute('href', newHref);
}
});
}
/**
* Handle dynamically added links using MutationObserver
* @param {string} trackingId - Tracking ID to append
*/
function observeNewLinks(trackingId) {
if (!trackingId) return;
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
// Check if the added node is a link
if (node.tagName === 'A' && node.getAttribute('href')) {
const href = node.getAttribute('href');
if (shouldTagUrl(href)) {
const newHref = addTrackingIdToUrl(href, trackingId);
node.setAttribute('href', newHref);
}
}
// Check for links within the added node
const childLinks = node.querySelectorAll ? node.querySelectorAll('a[href]') : [];
childLinks.forEach(link => {
const href = link.getAttribute('href');
if (href && shouldTagUrl(href)) {
const newHref = addTrackingIdToUrl(href, trackingId);
link.setAttribute('href', newHref);
}
});
}
});
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
return observer;
}
/**
* Initialize tracking script
*/
function init() {
try {
// Check for tracking ID in URL parameter
const urlTrackingId = getUrlParameter(CONFIG.tidParam);
// Get existing tracking ID from cookie if cookie tracking is enabled
let currentTrackingId = !isCookieTrackingDisabled() ? getCookie(CONFIG.cookieName) : null;
// If we have a tracking ID from URL, store it and use it
if (urlTrackingId) {
if (!isCookieTrackingDisabled()) {
setCookie(CONFIG.cookieName, urlTrackingId, CONFIG.cookieExpireDays);
}
currentTrackingId = urlTrackingId;
}
// Tag existing links with current tracking ID
if (currentTrackingId) {
tagLinks(currentTrackingId);
// Set up observer for dynamically added links
observeNewLinks(currentTrackingId);
}
} catch (error) {
console.error('Aluvii Tracking: Initialization error:', error);
}
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
// Expose public API for manual triggering if needed
window.AluviiTracking = {
init: init,
getTrackingId: () => getCookie(CONFIG.cookieName),
setTrackingId: (id) => {
if (!isCookieTrackingDisabled()) {
setCookie(CONFIG.cookieName, id, CONFIG.cookieExpireDays);
}
tagLinks(id);
}
};
function isCookieTrackingDisabled() {
const script = document.currentScript || document.querySelector('script[src*="aluvii_tracking_script.js"]');
return script && script.getAttribute('data-disable-cookie-tracking') === 'true';
}
})();