class InteractionTracker { constructor() { this.le = null; this.events = []; this.clientId = this.generateClientId(); this.startTime = Date.now(); this.isTabActive = this.getCurrentUnixTime(); this.aliveIntervall = null; this.scrolled = null; this.bottomReached = false; } generateClientId() { const unixTimeStamp = this.getCurrentUnixTime(); const randomNumbers = this.generateRandomNumbers(10); const clientId = `${randomNumbers}.${unixTimeStamp}`; return clientId; } generateRandomNumbers(length) { let result = ''; for (let i = 0; i < length; i++) { result += Math.floor(Math.random() * 10); } return result; } getCurrentUnixTime() { return Math.floor(Date.now() / 1000); } onDocumentReady(){ this.setupListeners(); this.checkMousePointer(); } setupListeners() { // Base Interactions (once) ['click', 'drag', 'scroll', "visibilitychange"].forEach(event => { document.addEventListener(event, (e) => this.eventHandler(e, event)); }); document.body.onmousemove = (e) => { this.mouseMoveHandler(e); }; document.body.ontouchstart = () => { this.isTabActive = this.getCurrentUnixTime(); document.body.classList.remove("mouse"); document.cookie = "pointer=touch"; }; } eventHandler(e, event) { switch (event) { case 'click': if (e.target.tagName === 'A') { this.addEvent('click', { link_classes: e.target.className, link_domain: e.target.hostname, link_id: e.target.id, link_url: e.target.href, outbound: e.target.hostname !== window.location.hostname }); break; } this.addEvent('click'); break; case 'drag': this.addEvent('drag'); break; case 'scroll': this.scrollHandler(e); break; case 'visibilitychange': this.visibilityChangeHandler(); break; } } visibilityChangeHandler() { let event = 'OpenedTab'; if (document.visibilityState === 'hidden') { event = 'LeftTab'; this.isTabActive = 0; } else { this.startTime = Date.now(); this.isTabActive = this.getCurrentUnixTime(); } this.addEvent(event); } scrollHandler(e) { this.isTabActive = this.getCurrentUnixTime(); clearTimeout(this.scrolled); this.scrolled = setTimeout(() => { const scrollPosition = window.scrollY; const totalHeight = document.documentElement.scrollHeight; const windowHeight = window.innerHeight; const distanceToBottom = totalHeight - (scrollPosition + windowHeight); // Check if the user has scrolled to 90% if (distanceToBottom <= (0.1 * totalHeight)) { if (!this.bottomReached) { this.bottomReached = true; this.addEvent("scroll"); } } }, 500) } mouseMoveHandler(e) { this.isTabActive = this.getCurrentUnixTime(); if ("movementX" in e && e.movementX != 0){ document.body.classList.add("mouse"); document.cookie = "pointer=mouse"; } } checkMousePointer() { if (new RegExp(/pointer=mouse/g).test(document.cookie)) { document.body.classList.add("mouse"); } } addEvent(event, props = null){ let ce = this.baseEvent(); let e = ce; if (this.le){ ce = this.getChangedEvent(e); } this.le = e; ce["client_id"] = this.clientId; ce["type"] = event; if(props) ce["props"] = props; this.events.push(ce); this.alive(); } baseEvent() { let [url, params] = window.location.href.split("?"); return { timestamp: new Date().toISOString(), event_id: Math.random().toString(36).substr(2, 9), lang: navigator.language || 'en-us', res: `${window.screen.width}x${window.screen.height}`, vp: `${window.innerWidth}x${window.innerHeight}`, user_agent: navigator.userAgent, build: navigator.buildID || '', os: navigator.platform, cpu: navigator.oscpu || '', title: document.title, speed: window.performance.getEntriesByType("navigation")[0]["domContentLoadedEventEnd"] || 0, href: url, params: params || '', touch: document.cookie.includes("pointer=")&&document.cookie.includes("pointer=touch"), eduration: Date.now()-this.startTime, scrolldepth: this.getScrollDepth(), ref: window.frames.top.document.referrer, }; } getChangedEvent(e) { return Object.fromEntries(Object.entries(e).filter(([key, value]) => { return !Object.entries(this.le).some(([ok, ov]) => { return ok === key && ov === value; }); })); } getScrollDepth(){ return document.body?Math.round( window.scrollY/( Math.max( document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight )-window.innerHeight )*100 ):0; } alive(){ let userActive = this.isTabActive > Math.floor(Date.now() / 1000)-60; let es = this.events; this.events = []; // Replace $.post with fetch fetch('/async/alive', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ active: userActive, e: es }) }) .then(response => response.text()) .then(data => { var page = window.location.href.replace(/^.*\/\/[^\/]+/, ''); var isLanguagePage = /^\/(de|en|it)/.test(page); if (isLanguagePage) { page = page.slice(3); } var conditions = [ "/?", "/auth", "/check_browser", "/demo", "/articles", "/vendita-pietre", "/join", "/login", "/slabs/", "/block/", "/recover", "/shop", "/item", "/cart", "/register", "/offer_join", "/selection", "/downloads", "/landing", "/footer/imprint", "/footer/privacy", "/footer/tos", "/offer", "/overlay", "/architects", "/contact", "/messe", "/navigator/edit", "/o/", "/shedule", "/planen", "/marketing_blender", "/layout" ]; if (page !== "/" && !isLanguagePage && !conditions.some(function(el) { return page.indexOf(el) === 0 })) { if (data.indexOf("jq401Unauthorized") !== -1) { window.location.reload(); } } }) .catch(error => console.error('Error:', error)); clearInterval(this.aliveIntervall); this.aliveIntervall = setInterval(this.alive, 1000 * 60); }; start() { this.addEvent('pageview'); } } let interactionTracker = new InteractionTracker(); interactionTracker.start(); function gtag(scope, event_type, props){ if(scope == "event"){ interactionTracker.addEvent(event_type, props); } } if( document.readyState !== 'loading' ) { init_core(); } else { document.addEventListener('DOMContentLoaded', function () { init_core(); }); } function appendScript(url) { var newScript = document.createElement("script"); newScript.setAttribute('src', url); newScript.setAttribute('type', 'text/javascript'); document.head.appendChild(newScript); }; function appendStyle(url) { var newStyle = document.createElement("link"); newStyle.setAttribute('href', url); newStyle.setAttribute('type', 'text/css'); newStyle.setAttribute('rel', 'stylesheet'); document.head.appendChild(newStyle); }; function init_core() { console.log("init_core"); interactionTracker.onDocumentReady(); // Replace $('head').append with document.head.insertAdjacentHTML appendScript('//cdn.drylayout.com/assets/js/cookieconsent.js'); appendStyle('//cdn.drylayout.com/assets/css/cookieconsent.css'); //$('head').append(" "); var ccInterval = setInterval(check_cookie_settings, 50); function check_cookie_settings() { console.log("check_cookie_settings", typeof initCookieConsent ); if(typeof initCookieConsent == 'function'){ clearInterval(ccInterval); window.cc = initCookieConsent(); window.cc.run({ current_lang: 'en', autoclear_cookies: true, // default: false cookie_name: 'cc_cookie', // default: 'cc_cookie' cookie_expiration: 365, // default: 182 page_scripts: true, // default: false force_consent: true, // default: false auto_language: 'browser', // default: null; could also be 'browser' or 'document' // autorun: true, // default: true // delay: 0, // default: 0 // hide_from_bots: false, // default: false // remove_cookie_tables: false // default: false // cookie_domain: location.hostname, // default: current domain // cookie_path: '/', // default: root // cookie_same_site: 'Lax', // use_rfc_cookie: false, // default: false // revision: 0, // default: 0 gui_options: { consent_modal: { layout: 'cloud', // box,cloud,bar position: 'bottom center', // bottom,middle,top + left,right,center transition: 'slide' // zoom,slide }, settings_modal: { layout: 'box', // box,bar position: 'left', // right,left (available only if bar layout selected) transition: 'slide' // zoom,slide } }, onFirstAction: function(){ console.log('onFirstAction'); }, onAccept: function (cookie) { typeof gtag === 'function' && gtag('consent', 'update', { 'analytics_storage': window.cc.allowedCategory("analytics")?'granted':'denied' }); if (window.cc.allowedCategory("analytics")) { const lazyBlocked = document.querySelectorAll(".lazy.blocked"); lazyBlocked.forEach(function(element) { const clickEvent = new Event("click"); element.dispatchEvent(clickEvent); }); } }, onChange: function (cookie, changed_preferences) { console.log('onChange'); // If analytics category is disabled => disable google analytics typeof gtag === 'function' && gtag('consent', 'update', { 'analytics_storage': window.cc.allowedCategory("analytics")?'granted':'denied' }); }, languages: { 'en': { consent_modal: { title: 'We value your privacy', description: 'We use cookies to enhance your browsing experience, serve personalized content, and analyze our traffic. By clicking "Accept All", you consent to our use of cookies. Privacy policy', primary_btn: { text: 'Accept all', role: 'accept_all' //'accept_selected' or 'accept_all' }, secondary_btn: { text: 'Preferences', role: 'settings' //'settings' or 'accept_necessary' }, revision_message: '

Dear user, terms and conditions have changed since the last time you visisted!' }, settings_modal: { title: 'Cookie settings', save_settings_btn: 'Save current selection', accept_all_btn: 'Accept all', reject_all_btn: 'Reject all', close_btn_label: 'Close', cookie_table_headers: [ {col1: 'Name'}, {col2: 'Duration'}, {col3: 'Expiration'} ], blocks: [ { title: 'Cookie usage', description: 'We use cookies to help you navigate efficiently and perform certain functions. You will find detailed information about all cookies under each consent category below.

The cookies that are categorized as "Necessary" are stored on your browser as they are essential for enabling the basic functionalities of the site.

Privacy Policy' }, { title: 'Strictly necessary cookies', description: "Necessary cookies are required to enable the basic features of this site, such as providing secure log-in or adjusting your consent preferences. These cookies do not store any personally identifiable data.", toggle: { value: 'necessary', enabled: true, readonly: true //cookie categories with readonly=true are all treated as "necessary cookies" }, cookie_table: [ { col1: 'cc_cookie', col2: "1 year", col3: 'This cookie is used to remember users consent preferences so that their preferences are respected on their subsequent visits to this site.', is_regex: true }, { col1: 'PHPSESSID', col2: "7 days", col3: 'The cookie is used to store and identify a users\' unique session ID for the purpose of managing user session on the website.', }, { col1: 'cookietest', col2: "1 Minute", col3: 'Is used to check if cookies are enabled.', }, { col1: 'pointer', col2: "session", col3: 'The cookie is stores the type of input device that is used.', }, { col1: 'device', col2: "session", col3: 'The cookie is used to store and identify each unique device for security reasons.', } ] }, { title: 'Analytics & Performance cookies', description: "Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics such as the number of visitors, bounce rate, traffic source, etc.", toggle: { value: 'analytics', enabled: false, readonly: false }, cookie_table: [ { col1: '_ga', col2: '1 years', col3: 'The _ga cookie, installed by Google Analytics, calculates visitor, session and campaign data and also keeps track of site usage for the site\'s analytics report. The cookie stores information anonymously and assigns a randomly generated number to recognize unique visitors.', is_regex: true }, { col1: '_gid', col2: '1 day', col3: 'Installed by Google Analytics, _gid cookie stores information on how visitors use a website, while also creating an analytics report of the website\'s performance. Some of the data that are collected include the number of visitors, their source, and the pages they visit anonymously.', }, { col1: '_lr_*', col2: '1 day', col3: 'Installed for some sessions of registered users by LogRocket, _lr_* cookie stores information on how visitors use a website, while also creating an session report of the website\'s users to improve application performance.', }, { col1: '_gat_gtag_*', col2: '1 minute', col3: 'Set by Google to distinguish users.', } ] } ] } }, 'de': { consent_modal: { title: 'Wir schätzen Ihre Privatsphäre', description: 'Wir verwenden Cookies, um Ihr Surferlebnis zu verbessern, personalisierte Inhalte anzubieten und unseren Datenverkehr zu analysieren. Indem Sie auf "Alle akzeptieren" klicken, stimmen Sie unserer Verwendung von Cookies zu. Datenschutz', primary_btn: { text: 'Alle akzeptieren', role: 'accept_all' //'accept_selected' or 'accept_all' }, secondary_btn: { text: 'Präferenzen', role: 'settings' //'settings' or 'accept_necessary' }, revision_message: '

Sehr geehrter Nutzer, die Bedingungen haben sich seit Ihrem letzten Besuch geändert!' }, settings_modal: { title: 'Cookie-Einstellungen', save_settings_btn: 'Aktuelle Auswahl speichern', accept_all_btn: 'Alle akzeptieren', reject_all_btn: 'Alle ablehnen', close_btn_label: 'Schließen', cookie_table_headers: [ {col1: 'Name'}, {col2: 'Dauer'}, {col3: 'Verfallsdatum'} ], blocks: [ { title: 'Verwendung von Cookies', description: 'Wir verwenden Cookies, damit Sie effizient navigieren und bestimmte Funktionen ausführen können. Detaillierte Informationen über alle Cookies finden Sie unter jeder Einwilligungskategorie unten.

Die Cookies, die als "notwendig" eingestuft werden, werden in Ihrem Browser gespeichert, da sie für die grundlegenden Funktionen der Website unerlässlich sind.

Datenschutz' }, { title: 'Notwendige Cookies', description: "Notwendige Cookies sind erforderlich, um die grundlegenden Funktionen dieser Website zu ermöglichen, wie z. B. die sichere Anmeldung oder die Anpassung Ihrer Einwilligungspräferenzen. Diese Cookies speichern keine persönlich identifizierbaren Daten.", toggle: { value: 'necessary', enabled: true, readonly: true //cookie categories with readonly=true are all treated as "necessary cookies" }, cookie_table: [ { col1: 'cc_cookie', col2: "1 year", col3: 'Dieses Cookie wird verwendet, um sich die Präferenzen der Benutzer zu merken, so dass ihre Präferenzen bei späteren Besuchen auf dieser Website berücksichtigt werden.', is_regex: true }, { col1: 'PHPSESSID', col2: "7 days", col3: 'Das Cookie wird verwendet, um die eindeutige Sitzungs-ID eines Benutzers zu speichern und zu identifizieren, um die Benutzersitzung auf der Website zu verwalten.', }, { col1: 'cookietest', col2: "1 Minute", col3: 'Wird verwendet, um zu prüfen, ob Cookies aktiviert sind.', }, { col1: 'pointer', col2: "session", col3: 'Der Cookie speichert den Typ des verwendeten Eingabegeräts.', }, { col1: 'device', col2: "session", col3: 'Das Cookie wird verwendet, um aus Sicherheitsgründen jedes einzelne Gerät zu speichern und zu identifizieren.', } ] }, { title: 'Analyse- und Leistungs-Cookies', description: "Analytische Cookies werden verwendet, um zu verstehen, wie Besucher mit der Website interagieren. Diese Cookies helfen dabei, Informationen über Metriken wie die Anzahl der Besucher, Absprungrate, Verkehrsquelle usw. zu liefern.", toggle: { value: 'analytics', enabled: false, readonly: false }, cookie_table: [ { col1: '_ga', col2: '1 years', col3: 'Das _ga-Cookie, das von Google Analytics installiert wird, berechnet Besucher-, Sitzungs- und Kampagnendaten und verfolgt auch die Nutzung der Website für den Analysebericht der Website. Das Cookie speichert Informationen anonym und weist eine zufällig generierte Nummer zu, um eindeutige Besucher zu erkennen.', is_regex: true }, { col1: '_gid', col2: '1 day', col3: 'Das von Google Analytics installierte _gid-Cookie speichert Informationen darüber, wie Besucher eine Website nutzen, und erstellt gleichzeitig einen Analysebericht über die Leistung der Website. Zu den gesammelten Daten gehören die Anzahl der Besucher, ihre Quelle und die Seiten, die sie anonym besuchen.', }, { col1: '_lr_*', col2: '1 day', col3: 'Das von LogRocket für einige Sitzungen registrierter Benutzer installierte _lr_*-Cookie speichert Informationen darüber, wie Besucher eine Website nutzen, und erstellt gleichzeitig einen Sitzungsbericht über die Benutzer der Website, um die Anwendungsleistung zu verbessern.', }, { col1: '_gat_gtag_*', col2: '1 minute', col3: 'Von Google festgelegt, um Nutzer zu unterscheiden.', } ] } ] } } } }); }else{ window.cc = false; } } }