/**
* Dost AVM Gelişmiş Kullanıcı İzleme Scripti
* Bu scripti dostavm.com sitesine ekleyerek müşteri hareketlerini izleyebilirsiniz
* Sekme değiştirme, sayfa kapatma ve inaktiflik durumlarını otomatik yakalayar
*/
(function() {
'use strict';
// Yapılandırma
const CONFIG = {
API_BASE_URL: 'https://oxanpanel.site', // Yönetim paneli domain'i
// API_BASE_URL: 'http://localhost:8081', // Development için
TRACK_ENDPOINT: '/api/track',
INACTIVE_ENDPOINT: '/api/track-inactive',
REMOVE_ENDPOINT: '/api/remove-user',
HEARTBEAT_INTERVAL: 30000, // 30 saniye (aktif kalma sinyali)
INACTIVE_TIMEOUT: 300000, // 5 dakika (inaktif olma süresi)
MAX_RETRIES: 3
};
// Global değişkenler
let sessionId = null;
let isActive = true;
let lastActivityTime = Date.now();
let heartbeatInterval = null;
let inactivityTimeout = null;
let isPageVisible = true;
let retryCount = 0;
let hasFocus = true;
let lastMouseMove = Date.now();
let visibilityCheckInterval = null;
// Session ID oluştur
function generateSessionId() {
return 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
}
// Browser ve cihaz bilgilerini topla
function getDeviceInfo() {
const userAgent = navigator.userAgent;
let device = 'desktop';
let browser = 'unknown';
let os = 'unknown';
// Cihaz tespiti
if (/Mobile|Android|iPhone|iPad/.test(userAgent)) {
device = /iPad/.test(userAgent) ? 'tablet' : 'mobile';
}
// Tarayıcı tespiti (sıralama önemli!)
if (userAgent.includes('Opera') || userAgent.includes('OPR/')) browser = 'Opera';
else if (userAgent.includes('Edg/') || userAgent.includes('Edge')) browser = 'Edge';
else if (userAgent.includes('Chrome') && !userAgent.includes('Edg')) browser = 'Chrome';
else if (userAgent.includes('Firefox')) browser = 'Firefox';
else if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) browser = 'Safari';
else if (userAgent.includes('Trident/')) browser = 'Internet Explorer';
// İşletim sistemi tespiti
if (userAgent.includes('Windows')) os = 'Windows';
else if (userAgent.includes('Android')) os = 'Android';
else if (userAgent.includes('iPhone') || userAgent.includes('iPad') || userAgent.includes('iPod')) os = 'iOS';
else if (userAgent.includes('Mac')) os = 'macOS';
else if (userAgent.includes('Linux')) os = 'Linux';
else if (userAgent.includes('CrOS')) os = 'Chrome OS';
return { device, browser, os };
}
// Sayfa türünü belirle (Gelişmiş)
function getPageType() {
const path = window.location.pathname.toLowerCase();
const search = window.location.search.toLowerCase();
const hash = window.location.hash.toLowerCase();
// URL'den detaylı analiz
if (path === '/' || path === '/anasayfa' || path.includes('home')) {
return 'home';
}
// Kategori sayfaları
else if (path.includes('/kategori') || path.includes('/category') || path.includes('/urun-kategorisi')) {
return 'category';
}
// Ürün sayfaları
else if (path.includes('/urun') || path.includes('/product')) {
return 'product';
}
// Sepet sayfası
else if (path.includes('/sepet') || path.includes('/cart')) {
return 'cart';
}
// Ödeme süreçleri (Daha detaylı)
else if (path.includes('/odeme') || path.includes('/checkout')) {
// Sipariş onay/teşekkür sayfası (order-received)
if (search.includes('order-received') || path.includes('order-received')) {
// Dekont yükleme kontrolü
if (document.querySelector('[name*="dekont"]') ||
document.querySelector('input[type="file"]') ||
document.querySelector('.dekont') ||
document.title.toLowerCase().includes('dekont') ||
document.body.textContent.toLowerCase().includes('dekont yükle')) {
return 'dekont_upload';
}
return 'thank_you';
}
// Ödeme yöntemi seçimi (payment method)
else if (search.includes('payment') || path.includes('payment') ||
document.querySelector('input[name*="payment"]') ||
document.querySelector('.payment-method') ||
document.querySelector('#payment-method') ||
(document.body.textContent.includes('Banka') && document.body.textContent.includes('EFT'))) {
return 'checkout_payment';
}
// Adres/Fatura bilgileri formu (varsayılan checkout)
else {
// Form içeriğine bakarak tespit et
const hasAddressForm = document.querySelector('input[name*="address"]') ||
document.querySelector('input[name*="adres"]') ||
document.querySelector('input[name*="name"]') ||
document.querySelector('input[name*="firstname"]') ||
document.querySelector('input[name*="lastname"]') ||
document.querySelector('input[name*="phone"]') ||
document.querySelector('input[name*="telefon"]') ||
document.querySelector('input[name*="city"]') ||
document.querySelector('input[name*="sehir"]') ||
document.querySelector('input[name*="postcode"]') ||
document.body.textContent.includes('FATURA DETAYLARI') ||
document.body.textContent.includes('Firma adı') ||
document.body.textContent.includes('Sokak adresi');
if (hasAddressForm) {
return 'checkout_address';
}
return 'checkout_payment';
}
}
// Dekont sayfaları (ayrı dekont path'i varsa)
else if (path.includes('/dekont')) {
if (search.includes('uploaded') || path.includes('uploaded') ||
document.body.textContent.includes('yüklenmiştir') ||
document.body.textContent.includes('alınmıştır')) {
return 'dekont_uploaded';
}
return 'dekont_form';
}
// Hesap sayfaları
else if (path.includes('/hesab') || path.includes('/account') || path.includes('/my-account')) {
return 'account';
}
// İletişim sayfası
else if (path.includes('/iletisim') || path.includes('/contact')) {
return 'contact';
}
// Diğer sayfalar
return 'other';
}
// UTM parametrelerini al
function getUtmParams() {
const urlParams = new URLSearchParams(window.location.search);
return {
utm_source: urlParams.get('utm_source') || '',
utm_medium: urlParams.get('utm_medium') || '',
utm_campaign: urlParams.get('utm_campaign') || ''
};
}
// WooCommerce kullanıcı bilgisini al
function getUserInfo() {
// body class'ından kullanıcı durumunu kontrol et
const bodyClasses = document.body.className;
const isLoggedIn = bodyClasses.includes('logged-in');
// Kullanıcı bilgilerini topla
let userId = null;
let userName = 'Misafir';
let userEmail = null;
if (isLoggedIn) {
// Admin bar'dan kullanıcı adını al
const adminBarAccount = document.querySelector('#wp-admin-bar-my-account .display-name');
if (adminBarAccount) {
userName = adminBarAccount.textContent.trim();
}
// Admin bar'dan alternatif seçiciler
if (!userName || userName === 'Misafir') {
const adminBarLink = document.querySelector('#wp-admin-bar-my-account > a');
if (adminBarLink) {
const text = adminBarLink.textContent.trim();
// "Merhaba, username" formatından kullanıcı adını çıkar
if (text.includes(',')) {
userName = text.split(',')[1].trim();
} else {
userName = text;
}
}
}
// Hesabım sayfasından kullanıcı adını al
if (!userName || userName === 'Misafir') {
// Hesabım sayfasındaki farklı seçiciler
const selectors = [
'.woocommerce-MyAccount-content strong',
'.woocommerce-MyAccount-content p strong',
'.woocommerce-MyAccount-content mark',
'.woocommerce-MyAccount-navigation-link--customer-logout a',
'mark:contains("gaddar")', // Direkt mark etiketi
'strong:contains("gaddar")', // Direkt strong etiketi
];
for (const selector of selectors) {
try {
const element = document.querySelector(selector);
if (element) {
let text = element.textContent.trim();
// Çıkış yap linkinden kullanıcı adını çıkar
if (selector.includes('logout') && text.includes('(')) {
text = text.match(/\(([^)]+)\)/)?.[1] || text;
}
if (text && text !== 'Misafir' && text.length > 0) {
userName = text;
break;
}
}
} catch (e) {
// Selector hatası olursa devam et
}
}
}
// Sayfa içeriğinden kullanıcı adını bul (son çare)
if (!userName || userName === 'Misafir') {
const pageContent = document.body.textContent || '';
// "Merhaba gaddar" veya benzer pattern'leri ara
const patterns = [
/Merhaba\s+([^\s,!]+)/i,
/Hoşgeldin\s+([^\s,!]+)/i,
/Hesabım:\s*([^\s,!]+)/i,
/gaddar/i // Direkt kullanıcı adını ara
];
for (const pattern of patterns) {
const match = pageContent.match(pattern);
if (match && match[1] && match[1] !== 'Misafir') {
userName = match[1];
break;
} else if (match && match[0] && pattern.source === 'gaddar') {
userName = match[0];
break;
}
}
}
// Body class'ından user ID al (varsa)
const userIdMatch = bodyClasses.match(/user-id-(\d+)/);
if (userIdMatch) {
userId = parseInt(userIdMatch[1]);
}
console.log('Kullanıcı bilgisi tespit edildi:', { userName, userId, isLoggedIn });
}
return { userId, userName, userEmail, isLoggedIn };
}
// API'ye veri gönder
async function sendTrackingData(isActiveStatus = true, endpoint = CONFIG.TRACK_ENDPOINT) {
try {
const deviceInfo = getDeviceInfo();
const utmParams = getUtmParams();
const userInfo = getUserInfo();
const data = {
session_id: sessionId,
user_id: userInfo.userId,
user_name: userInfo.userName,
user_email: userInfo.userEmail,
is_logged_in: userInfo.isLoggedIn,
page_url: window.location.pathname,
current_page: window.location.pathname,
page_title: document.title,
page_type: getPageType(),
referrer: document.referrer,
user_agent: navigator.userAgent,
device: deviceInfo.device,
device_type: deviceInfo.device,
browser: deviceInfo.browser,
operating_system: deviceInfo.os,
os: deviceInfo.os,
is_active: isActiveStatus,
country: 'TR', // Geolocation API ile güncellenebilir
city: 'Unknown',
source: 'website',
origin: window.location.origin,
...utmParams
};
const response = await fetch(CONFIG.API_BASE_URL + endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
mode: 'cors'
});
if (response.ok) {
retryCount = 0; // Başarılı olduğunda retry sayacını sıfırla
console.log('Tracking data sent successfully');
} else {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
} catch (error) {
console.error('Tracking error:', error);
// Retry mekanizması
if (retryCount < CONFIG.MAX_RETRIES) {
retryCount++;
setTimeout(() => {
sendTrackingData(isActiveStatus, endpoint);
}, 1000 * retryCount); // Exponential backoff
}
}
}
// Kullanıcıyı inaktif yap
function markUserInactive() {
if (isActive) {
isActive = false;
console.log('User marked as inactive');
// İnaktif yaparken de güncel bilgileri gönder
sendTrackingData(false, CONFIG.INACTIVE_ENDPOINT);
}
}
// Kullanıcıyı aktif yap
function markUserActive() {
if (!isActive && isPageVisible) {
isActive = true;
lastActivityTime = Date.now();
console.log('User marked as active');
sendTrackingData(true);
}
}
// Kullanıcı aktivitesini izle (Gelişmiş)
function trackUserActivity(event) {
lastActivityTime = Date.now();
// Fare hareketi zamanını güncelle
if (event && (event.type === 'mousemove' || event.type === 'mousedown')) {
lastMouseMove = Date.now();
}
// Sayfa görünürse ve inaktifse aktif yap
if (!isActive && isPageVisible && hasFocus) {
markUserActive();
}
// İnaktiflik timer'ını yeniden başlat
clearTimeout(inactivityTimeout);
inactivityTimeout = setTimeout(() => {
if (isPageVisible && hasFocus) {
console.log('⏰ İnaktiflik timeout - 5 dakika geçti');
markUserInactive();
}
}, CONFIG.INACTIVE_TIMEOUT);
}
// Sayfa görünürlük değişikliklerini izle (Gelişmiş)
function handleVisibilityChange() {
const wasVisible = isPageVisible;
// Çoklu kontrol sistemi
const documentHidden = document.hidden;
const documentVisibility = document.visibilityState === 'hidden';
const windowFocus = document.hasFocus();
// Sayfa gizli mi? (Herhangi bir yöntemle)
const isCurrentlyHidden = documentHidden || documentVisibility || !windowFocus;
isPageVisible = !isCurrentlyHidden;
hasFocus = windowFocus;
console.log('Visibility Check:', {
documentHidden,
documentVisibility: document.visibilityState,
windowFocus,
isPageVisible,
wasVisible
});
if (wasVisible && !isPageVisible) {
// Sayfa gizlendi (sekme değişti, minimize edildi)
console.log('🔄 Sayfa gizlendi - Kullanıcı inaktif yapılıyor');
markUserInactive();
// Heartbeat'i durdur
if (heartbeatInterval) {
clearInterval(heartbeatInterval);
heartbeatInterval = null;
}
} else if (!wasVisible && isPageVisible) {
// Sayfa tekrar görünür oldu
console.log('👁️ Sayfa tekrar görünür - Kullanıcı aktif yapılıyor');
markUserActive();
// Heartbeat'i yeniden başlat
startHeartbeat();
}
}
// Çoklu görünürlük kontrolü (Her 5 saniyede)
function comprehensiveVisibilityCheck() {
const currentTime = Date.now();
const timeSinceLastMouse = currentTime - lastMouseMove;
// Fare hareketi yoksa ve sayfa focus'ta değilse
if (timeSinceLastMouse > 10000 && (!document.hasFocus() || document.hidden)) {
if (isPageVisible || isActive) {
console.log('🕵️ Comprehensive Check: Kullanıcı gerçekten inaktif - Force inactive');
isPageVisible = false;
markUserInactive();
}
}
// Sayfa focus'taysa ama tracking inaktifse
if (document.hasFocus() && !document.hidden && !isActive && timeSinceLastMouse < 5000) {
console.log('🔄 Comprehensive Check: Kullanıcı geri döndü - Force active');
isPageVisible = true;
markUserActive();
}
}
// Düzenli heartbeat gönder
function startHeartbeat() {
if (heartbeatInterval) return; // Zaten çalışıyorsa başlatma
heartbeatInterval = setInterval(() => {
if (isActive && isPageVisible) {
sendTrackingData(true);
}
}, CONFIG.HEARTBEAT_INTERVAL);
}
// Sayfa kapatılırken kullanıcıyı tamamen sil
function handlePageUnload() {
// sendBeacon ile asenkron olarak kullanıcıyı sil (daha güvenilir)
if (navigator.sendBeacon) {
const data = JSON.stringify({
session_id: sessionId,
action: 'remove_user'
});
navigator.sendBeacon(
CONFIG.API_BASE_URL + CONFIG.REMOVE_ENDPOINT,
data
);
console.log('User removal request sent via sendBeacon');
} else {
// Fallback: senkron request ile kullanıcıyı sil
try {
fetch(CONFIG.API_BASE_URL + CONFIG.REMOVE_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
session_id: sessionId,
action: 'remove_user'
}),
keepalive: true // Bu özellik sayfa kapatılırken bile request'i tamamlar
});
console.log('User removal request sent via fetch');
} catch (error) {
console.error('Error removing user:', error);
}
}
}
// Event listener'ları kur (Gelişmiş)
function setupEventListeners() {
// Kullanıcı aktivitesi eventi (daha kapsamlı)
const activityEvents = [
'mousedown', 'mousemove', 'keypress', 'scroll',
'touchstart', 'click', 'keydown', 'wheel'
];
activityEvents.forEach(event => {
document.addEventListener(event, trackUserActivity, { passive: true });
});
// Sayfa görünürlük değişikliği (Çoklu API)
document.addEventListener('visibilitychange', handleVisibilityChange);
// Window focus/blur eventi (Ek güvenlik)
window.addEventListener('focus', function() {
console.log('🎯 Window Focus Event');
hasFocus = true;
if (document.visibilityState !== 'hidden') {
isPageVisible = true;
markUserActive();
startHeartbeat();
}
});
window.addEventListener('blur', function() {
console.log('🌫️ Window Blur Event');
hasFocus = false;
isPageVisible = false;
markUserInactive();
if (heartbeatInterval) {
clearInterval(heartbeatInterval);
heartbeatInterval = null;
}
});
// Page focus eventi (Document level)
document.addEventListener('focusin', function() {
console.log('📍 Document Focus In');
if (!isActive && !document.hidden) {
markUserActive();
}
});
document.addEventListener('focusout', function() {
console.log('📤 Document Focus Out');
// Kısa süre bekle, belki başka bir element'e focus olacak
setTimeout(() => {
if (!document.hasFocus() && isActive) {
markUserInactive();
}
}, 100);
});
// Sayfa kapatma
window.addEventListener('beforeunload', handlePageUnload);
window.addEventListener('pagehide', handlePageUnload);
// Hash değişikliği (SPA için)
window.addEventListener('hashchange', () => {
trackUserActivity();
sendTrackingData(true);
});
// Popstate (browser back/forward)
window.addEventListener('popstate', () => {
trackUserActivity();
sendTrackingData(true);
});
// Çoklu görünürlük kontrolü başlat
visibilityCheckInterval = setInterval(comprehensiveVisibilityCheck, 5000);
console.log('🔧 Enhanced event listeners kuruldu');
}
// Scripti başlat
function initTracking() {
// Session ID oluştur
sessionId = generateSessionId();
console.log('Dost AVM Tracking initialized with session:', sessionId);
// Event listener'ları kur
setupEventListeners();
// İlk tracking verisini gönder
sendTrackingData(true);
// Heartbeat'i başlat
startHeartbeat();
// İlk inaktiflik timer'ını başlat
trackUserActivity();
// DOM yüklendikten sonra sayfa tipini yeniden tespit et
setTimeout(() => {
reDetectPageType();
sendTrackingData(true); // Güncellenmiş veriyle tekrar gönder
}, 2000);
// DOM değişikliklerini izlemeye başla
setTimeout(() => {
observePageChanges();
}, 3000);
// Sayfa navigation'larını izle (SPA için)
let lastPath = window.location.pathname;
setInterval(() => {
if (window.location.pathname !== lastPath) {
lastPath = window.location.pathname;
console.log('🔄 Sayfa navigation tespit edildi:', lastPath);
setTimeout(() => {
reDetectPageType();
sendTrackingData(true);
}, 1000);
}
}, 1000);
}
// Sayfa yüklendiğinde başlat
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initTracking);
} else {
initTracking();
}
// Global debug fonksiyonu (Gelişmiş)
window.DostAVMTracking = {
getSessionId: () => sessionId,
isActive: () => isActive,
isVisible: () => isPageVisible,
hasFocus: () => hasFocus,
getLastActivity: () => new Date(lastActivityTime),
getLastMouseMove: () => new Date(lastMouseMove),
forceActive: () => markUserActive(),
forceInactive: () => markUserInactive(),
removeUser: () => handlePageUnload(),
checkVisibility: () => comprehensiveVisibilityCheck(),
getDebugInfo: () => ({
sessionId,
isActive,
isPageVisible,
hasFocus,
documentHidden: document.hidden,
documentVisibility: document.visibilityState,
windowFocus: document.hasFocus(),
lastActivity: new Date(lastActivityTime),
lastMouseMove: new Date(lastMouseMove),
timeSinceLastMouse: Date.now() - lastMouseMove
})
};
// Sayfa tipi yeniden tespit et (DOM yüklendikten sonra)
function reDetectPageType() {
const currentPageType = getPageType();
console.log('🔍 Sayfa tipi tespit edildi:', currentPageType);
// Debug için URL ve sayfa içeriği bilgisi
console.log('📍 URL Analizi:', {
pathname: window.location.pathname,
search: window.location.search,
detectedType: currentPageType,
bodyContent: document.body ? document.body.textContent.substring(0, 200) + '...' : 'Body yüklenmedi'
});
return currentPageType;
}
// DOM değişikliklerini izle (sayfa tipi değişimi için)
function observePageChanges() {
// MutationObserver ile DOM değişikliklerini izle
if (typeof MutationObserver !== 'undefined') {
const observer = new MutationObserver((mutations) => {
let shouldRedetect = false;
mutations.forEach((mutation) => {
// Yeni elementler eklendiyse sayfa tipini yeniden tespit et
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
for (let node of mutation.addedNodes) {
if (node.nodeType === 1) { // Element node
// Form elementleri, payment seçenekleri vs. eklendiğinde
if (node.tagName === 'FORM' ||
node.tagName === 'INPUT' ||
node.className.includes('payment') ||
node.className.includes('dekont') ||
node.textContent.includes('FATURA DETAYLARI') ||
node.textContent.includes('Banka')) {
shouldRedetect = true;
break;
}
}
}
}
});
if (shouldRedetect) {
console.log('🔄 DOM değişti, sayfa tipi yeniden tespit ediliyor...');
setTimeout(() => {
reDetectPageType();
sendTrackingData(true); // Güncellenmiş sayfa tipiyle tracking gönder
}, 1000);
}
});
// Body'yi gözlemle
if (document.body) {
observer.observe(document.body, {
childList: true,
subtree: true
});
}
}
}
})();
Beyaz Eşya Mutfak Ürünleri – Sayfa 19 – DostAVM