extern.conversion.consulting
Open in
urlscan Pro
2a01:4f8:1c1c:a1e8::a
Public Scan
URL:
http://extern.conversion.consulting/scripts/secure/load_all_functions.js
Submission: On October 30 via manual from DE — Scanned from DE
Submission: On October 30 via manual from DE — Scanned from DE
Form analysis
0 forms found in the DOMText Content
/* Following Vars are declared on a global scale inside GTM before calling this script: attribution_offset = {{-System Get ProfitFinder transaction_offset - Attribution Abweichung im Tracking}}; final_purchase_value = {{-Get final purchase value}};; allowed_hostnames = {{-System x_csggexeg}}; hostname_without_www = {{hostname without www}}; hostname_domain = {{hostname domain}}; */ /* this function now being made available directly inside GTM at INITIALZIATION stage function pullExtern(scriptSrc,deferState,scriptId){ //pullExtern("https...","defer"|"async" or false,extra_id_to_identify) var script = document.createElement('script'); script.setAttribute('id', "shoplytics_inject_"+scriptId); script.setAttribute('src', scriptSrc); if(deferState !== false){ script.setAttribute(deferState,deferState); } document.body.appendChild(script) // console.log(document.getElementById("shoplytics_inject_"+scriptId)) } */ //------------------------- //CHECK AND OBSERVE IF AN ELEMENT GETS LOADED ONTO THE PAGE //used in our Custom Conversion Functions in the external_service_machine.js //------------------------- /* function shoplytics_check_for_element_with_observer(className, callback) { console.log("------------------------") console.log("shoplytics_check_for_element_with_observer()") var sl_mutation_element_count = 0; console.log("------------------------") // Initial check const initialElement = document.querySelector(`.${className}`); if (initialElement) { console.log("INITIAL ELEMENT FOUND") callback(initialElement); return; } // MutationObserver setup const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.addedNodes.length) { console.log("MUTATION OBSERVER FOUND NEW NODeS") const element = document.querySelector(`.${className}`); if (element) { sl_mutation_element_count ++; console.log("element found: Count: "+sl_mutation_element_count) callback(element); observer.disconnect(); // Stop observing after the element is found } } }); }); observer.observe(document.body, { childList: true, subtree: true }); } */ /** * Observes a target element for mutations and runs a callback when an element matching a given selector becomes visible. * * @param {string} selector - The CSS selector for the element to find. * @param {string} targetSelector - The CSS selector for the target element within which to observe for mutations. * @param {Function} callback - The function to call when the element is found and visible. * @param {boolean} shouldReconnect - Whether the observer should reconnect after finding an element. */ function shoplytics_check_for_element_with_observer(selector, targetSelector, callback, shouldReconnect) { function isElementVisible(el) { let element = el; while (element) { const style = window.getComputedStyle(element); if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') { return false; } element = element.parentElement; } return true; } const target = document.querySelector(targetSelector); if (!target) { return; } const initialElement = target.querySelector(selector); if (initialElement && isElementVisible(initialElement)) { callback(initialElement); if (!shouldReconnect) { return; } } const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { if (mutation.addedNodes.length || mutation.type === 'attributes') { const element = target.querySelector(selector); if (element && isElementVisible(element)) { callback(element); if (!shouldReconnect) { observer.disconnect(); return; } } } } }); observer.observe(target, { attributes: true, childList: true, subtree: true }); } /** * Observes a target element for mutations and runs a callback when an element matching a given selector becomes visible. * * @param {string} selector - The CSS selector for the element to find. * @param {string} targetSelector - The CSS selector for the target element within which to observe for mutations. * @param {Function} callback - The function to call when the element is found and visible. * @param {boolean} shouldReconnect - Whether the observer should reconnect after finding an element. */ /* function shoplytics_check_for_element_with_observer(selector, targetSelector, callback, shouldReconnect) { // Type checking for arguments if (typeof selector !== 'string' || typeof targetSelector !== 'string' || typeof callback !== 'function') { console.error('Invalid arguments passed.'); return; } // Improved method to check if an element is visible in the viewport with debugging function isElementVisible(el) { const style = window.getComputedStyle(el); if ( style.display === 'none' || style.visibility === 'hidden' || parseFloat(style.opacity) <= 0 ) { console.debug('Element is hidden due to CSS styles.'); return false; } const rect = el.getBoundingClientRect(); if (rect.width === 0 && rect.height === 0) { return false; } const windowHeight = (window.innerHeight || document.documentElement.clientHeight); const windowWidth = (window.innerWidth || document.documentElement.clientWidth); // Check if any part of the element is within the viewport const vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0); const horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) >= 0); if (!vertInView || !horInView) { console.debug('Element is not in the viewport.', { rect, windowHeight, windowWidth }); } return (vertInView && horInView); } const target = document.querySelector(targetSelector); if (!target) { console.warn('Target element not found.'); return; } const initialElement = target.querySelector(selector); if (initialElement && isElementVisible(initialElement)) { callback(initialElement); if (!shouldReconnect) { return; } } const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { if (mutation.addedNodes.length || mutation.type === 'attributes') { const element = target.querySelector(selector); if (element && isElementVisible(element)) { console.debug('Element found.', element) callback(element); if (!shouldReconnect) { observer.disconnect(); return; } } } } }); observer.observe(target, { attributes: true, childList: true, subtree: true }); } */ function check_if_dom_ready(callback) { //console.log("------------") //console.log("check_if_dom_ready()") //console.log("------------") // If DOM is already loaded, execute the callback directly if (document.readyState === 'complete'|| document.readyState === 'interactive') { //console.log("dom is ready") callback(); } // Otherwise, wait for the DOM to be loaded else { //console.log("dom is NO READY, adding event listener") document.addEventListener('DOMContentLoaded', callback); } } /* Example usage check_if_dom_ready(() => { //code here }); */ //------------------------------ //-------------------------------- //FIRE GOOGLE ADS ATTRIBUTION TAGS MULTIPLE TIMES //-------------------------------- //-------------------------------- function fireGoogleAdsAttributionTagMultipleTimes(trackingOffset,google_ads_id,google_ads_label,final_purchase_value){//called by Tag: -- 0 - System Attribution 2 fire conversion repeatedly GAds shoplytics_fireGadsAttributionConversionAgain //trackingOffset = die Abweichung im Tracking zwischen Shop Backend und Trackingsystem var fireMax = 100/(100-trackingOffset); //example: trackingOffset = 30%, we track 70% of data (100-trackingOffset), but we want 100% (100/70) = fire this conversion 1,43 times //------------------------------------------------------------------------------------ //remember count of times this tag has fired an additional conversion //------------------------------------------------------------------------------------ if(localStorage.getItem("sl_multipleGadsConversionFireCount") == null){ localStorage.setItem("sl_multipleGadsConversionFireCount",0); var fireCountCurrent = 0; }else{ var fireCountCurrent = parseInt(localStorage.getItem("sl_multipleGadsConversionFireCount")) } //------------------------------------------------------------------------------------ //figure out how much more often to fire //------------------------------------------------------------------------------------ var howManyMore = fireMax - fireCountCurrent; //console.log("------GOOGLE ADS ----------") //console.log("howManyMore:"+howManyMore) //console.log("fireMax:"+fireMax) //console.log("fireCountCurrent:"+fireCountCurrent) //------------------------------------------------------------------------------------ //fire normal //------------------------------------------------------------------------------------ if(howManyMore > 1){ // dataLayer.push({"event":"shoplytics_fireGadsAttributionConversionAgain"}); //console.log("WHOLE NUMBER"); //fire GTAG directly instead of going round trip to GTM Tag (started 18.10.2023) var gtag_destination = 'AW-'+google_ads_id+"/"+google_ads_label gtag('event', 'conversion', { 'send_to': gtag_destination, 'value': final_purchase_value, 'currency': 'EUR', 'attribution_offset_count':fireCountCurrent, 'tracking_provider':'shoplytics.de' }); //console.log("attribution offset adjustment fired: "+fireCountCurrent) localStorage.setItem("sl_multipleGadsConversionFireCount",fireCountCurrent+1); //restart the Function setTimeout(function() {fireGoogleAdsAttributionTagMultipleTimes(trackingOffset,google_ads_id,google_ads_label,final_purchase_value);}, 50); //setTimeout(fireGoogleAdsAttributionTagMultipleTimes, 100); //------------------------------------------------------------------------------------ //fire fraction and stop //------------------------------------------------------------------------------------ }else if (howManyMore >0){//this is a fraction of a number, like 0,33 if fireMax was 3,33 -> so only fire in 1 out of (1/0,33)=3 times var randomChance = 1/howManyMore; // Generate a random number between 0 and 1 (inclusive of 0, but exclusive of 1) var randomNumber = Math.random(); // Scale the random number to the desired range (1 to randomChance (maximum number)) var theRandomFinal = Math.floor(randomNumber * randomChance) + 1; //console.log("------randomize fraction ----------") //console.log("randomChance:"+randomChance) //console.log("theRandomFinal:"+theRandomFinal) //fire the tag again in maximum 1 out of randomChance times if(theRandomFinal == 1){ //fire GTAG directly instead of going round trip to GTM Tag (started 18.10.2023) var gtag_destination = 'AW-'+google_ads_id+"/"+google_ads_label gtag('event', 'conversion', { 'send_to': gtag_destination, 'value': final_purchase_value, 'currency': 'EUR', 'attribution_offset_count':fireCountCurrent, 'tracking_provider':'shoplytics.de' }); //console.log("attribution offset adjustment fired: "+fireCountCurrent) } localStorage.removeItem("sl_multipleGadsConversionFireCount"); //------------------------------------------------------------------------------------ //No Firing, we reached the limit //------------------------------------------------------------------------------------ }else{ //we are done. dont fire it again and reset the count //console.log("NO FIRING, DONE"); localStorage.removeItem("sl_multipleGadsConversionFireCount"); } //console.log("----------------") } //<<------- END //FIRE GOOGLE ADS ATTRIBUTION TAGS MULTIPLE TIMES //------------------------------ //-------------------------------- //FIRE FACEBOOK ADS ATTRIBUTION TAGS MULTIPLE TIMES //-------------------------------- //-------------------------------- function fireFacebookAdsAttributionTagMultipleTimes(trackingOffset, final_purchase_value){ //trackingOffset = die Abweichung im Tracking zwischen Shop Backend und Trackingsystem var fireMax = 100/(100-trackingOffset); //example: trackingOffset = 30%, we track 70% of data (100-trackingOffset), but we want 100% (100/70) = fire this conversion 1,43 times //------------------------------------------------------------------------------------ //remember count of times this tag has fired an additional conversion //------------------------------------------------------------------------------------ if(localStorage.getItem("sl_multipleFBadsConversionFireCount") == null){ localStorage.setItem("sl_multipleFBadsConversionFireCount",0); var fireCountCurrent = 0; }else{ var fireCountCurrent = parseInt(localStorage.getItem("sl_multipleFBadsConversionFireCount")) } //------------------------------------------------------------------------------------ //figure out how much more often to fire //------------------------------------------------------------------------------------ var howManyMore = fireMax - fireCountCurrent; //console.log("-----FACEBOOK-----------") //console.log("howManyMore:"+howManyMore) //console.log("fireMax:"+fireMax) //console.log("fireCountCurrent:"+fireCountCurrent) //------------------------------------------------------------------------------------ //fire normal //------------------------------------------------------------------------------------ if(howManyMore > 1){ //dataLayer.push({"event":"shoplytics_fireFBadsAttributionConversionAgain"}); localStorage.setItem("sl_multipleFBadsConversionFireCount",fireCountCurrent+1); //SEND EVENT //------------ //send revenue fbq('trackCustom', "BETA_shoplytics_attribution_extrapolate_tracking_deviation",{ value: final_purchase_value }); //restart the Function //setTimeout(fireFacebookAdsAttributionTagMultipleTimes, 100); setTimeout(function() {fireFacebookAdsAttributionTagMultipleTimes(trackingOffset, final_purchase_value);}, 50); //------------------------------------------------------------------------------------ //fire fraction and stop //------------------------------------------------------------------------------------ }else if (howManyMore >0){//this is a fraction of a number, like 0,33 if fireMax was 3,33 -> so only fire in 1 out of (1/0,33)=3 times var randomChance = 1/howManyMore; // Generate a random number between 0 and 1 (inclusive of 0, but exclusive of 1) var randomNumber = Math.random(); // Scale the random number to the desired range (1 to randomChance (maximum number)) var theRandomFinal = Math.floor(randomNumber * randomChance) + 1; //fire the tag again in maximum 1 out of randomChance times if(theRandomFinal == 1){ //dataLayer.push({"event":"shoplytics_fireFBadsAttributionConversionAgain"}); //SEND EVENT //------------ //send revenue fbq('trackCustom', "BETA_shoplytics_attribution_extrapolate_tracking_deviation",{ value: final_purchase_value }); } localStorage.removeItem("sl_multipleFBadsConversionFireCount"); //------------------------------------------------------------------------------------ //No Firing, we reached the limit //------------------------------------------------------------------------------------ }else{ //we are done. dont fire it again and reset the count localStorage.removeItem("sl_multipleFBadsConversionFireCount"); } } //<<------- END //FIRE FACEBOOK ADS ATTRIBUTION TAGS MULTIPLE TIMES //----> deaktiviert 8.9.2021 - wird aktuell nicht genutzt, da nicht zwischen PF und TT unterschieden wird in der Funktion //push the Type of ProfitFinder purchased by the user into the DataLayer. //tp = turbo Pixel //pf = Profit Finder /* var dl=window.dataLayer; var dlen = dl.length; for(var i=0;i<dlen;i++){ if(typeof dl[i].profit_finder != "undefined"){ //window.dataLayer.profit_finder.push({"TrackingType":"Turbo Pixel"}); var s=document.getElementsByTagName("script") var slen = s.length; for(var ss=0;ss<slen;ss++){ if(typeof s[ss].getAttribute("src") != "undefined" && s[ss].getAttribute("src") != null){ if(s[ss].getAttribute("src").indexOf("profitfinder")>-1){ var theTT = s[ss].getAttribute("tt"); if(theTT == "tp"){ window.dataLayer[i].profit_finder.trackType= "Turbo Pixel" }else if(theTT == "pf"){ window.dataLayer[i].profit_finder.trackType= "Profit Finder" } } } } //push ProfitFinder Version into DataLayer window.dataLayer[i].profit_finder.version={--- 0-VERSIONS-INFOS-xxxxx}} ; } } */ //------------------- var originalPageTitle = document.title; //BEFORE-UNLOAD Function for all sorts of uses (i.e. tracking scroll depth the user actually exited on (instead of just clicking to a different page) window.addEventListener('beforeunload', function() { window.dataLayer.push({ event: 'shoplytics_exit-detection' }); console.log("shoplytics_exit-detection"); }); //DSGVO and Disable Function //gdhclkswwlidhkl = {-System x_xghewddgs}}; // == 1 if hostname ist predefined hostname inside profitFinder Vars //function xc2dg4zzxaxklkqisli(){if(gdhclkswwlidhkl == 1){return 1;}else{return 0;}} function domainExactMatch(){ var theSplit = allowed_hostnames.split(","); var theLen = theSplit.length; for(var s=0;s<theLen;s++){ if(document.location.host.match(theSplit[s]) != null){ return 1; } } return 0; } function subdomainWhiteList(){ //are we on a subdomain? var theHost = hostname_without_www; //i.e subdomain.top-level.de var domainSettingPF = allowed_hostnames;//"*.endlich-liebe.de"; var theMainDomain = hostname_domain; var domainSettingSplit = domainSettingPF.split(","); var theLen = domainSettingSplit.length; //console.log("theHost="+theHost); if(theHost.match(/.*[a-z0-9\-]+\.[a-z0-9\-]+\.[a-z]{2,10}$/) != null){ // we have a subdomain theWhiteListString = "*."+theMainDomain; for(var s=0;s<theLen;s++){ //check for every PF Domain in Settings ... if(domainSettingSplit[s] == theWhiteListString){ return 1; } } } return 0; } //8.9.2021 wir verzichten vorerst auf den HN check (always return 1) um Geschwindigkeit zu verbessern //aktuell keine Gefahr des Gebrauchst von PF auf unbefugten Domains function xc2dg4zzxaxklkqisli_x_checkHN(){ //console.log("inside the function ...="+{-System x_xghewddgs}}); //if( {-System x_xghewddgs}}==1){ // /* if({-System x_csggexeg}} == "*"){ //ein whitelist character ist mit angegeben return 1; } else if(subdomainWhiteList() == 1){ return 1; } else{//kein Whitelist Character Domain Liste in PF festgelegt if(domainExactMatch() == 1){ return 1; } } return 0; */ return 1; }; // Opt-out function /* function gaOptout() { document.cookie = disableStr + '=true; expires=Thu, 31 Dec 2199 23:59:59 UTC; path=/'; window[disableStr] = true; document.cookie="pf_nt=1; expires=Tue, 19 Jan 2038 03:14:07 UTC; path=/"; localStorage.setItem("pf_nt",1); notrack = 1; //alert("Ok. Wir haben die Optimierung dieser Seite für Ihre Besuche abgeschalten. Sie sehen ab sofort keine für Sie und Ihre Interessen optimierte Seite mehr. Nur noch die Webseite ohne erweiterten Funktionsumfang. Zudem erhalten Sie auch auf facebook und Google keine relevanten Informationen mehr von uns. Sie können diesen Service zur Personalisierung jederzeit wieder reaktivieren, wenn Sie den entsprechenden Link klicken."); location.reload(true); } */ /* function gaOptin() { document.cookie = disableStr + '=false; expires=Thu, 31 Dec 2199 23:59:59 UTC; path=/'; window[disableStr] = false; //alert("Ok. Wir haben den Service zur Personalisierung der Inhalte auf dieser Seite und unseren Informationen die Sie auf facebook und Google von unser zu sehen bekommen für Ihre Besuche wieder aktiviert."); document.cookie="pf_nt=0; expires=Tue, 19 Jan 2038 03:14:07 UTC; path=/"; localStorage.setItem("pf_nt",0); notrack = 0; location.reload(true); } */ /* function allOptout(){ gaOptout(); } */ /* function optIn(){ gaOptin(); } */ function readCookie(name,c,C,i){ //if(cookies){ return cookies[name]; } //for CookieConsent there is a "==" which breaks this script usually //thats why we have to take care of == sepeartely //it looks like this --> {stamp:'z+nykDhMobKRai/rIvEcimwutaBuGhDIQU8cjb1nqp+qFH6ZwZl/qw=='%2Cnecessary:true%2Cpreferences:true%2Cstatistics:true%2Cmarketing:true%2Cver:1} c = document.cookie.split('; '); //alert("c="+c); cookies = {}; for(i=c.length-1; i>=0; i--){ if(c[i].indexOf("==")>-1){ //we have a == in the cookie values C = c[i].split('=='); C1 = C[0].split("="); // cookies[C1[0]] = C[1]; }else{ //no double == in the cookie values C = c[i].split('='); cookies[C[0]] = C[1]; } } //alert("cookies:"+cookies[0]); return cookies[name]; } //-------------------------- //-------------------------- //EVERYTHING FOR SCROLL DEPTH TIMER //-------------------------- //-------------------------- /* --> Deaktiviert am 28.7.2022 wegen starken Abweichungen im Ecom Tracking wurde die sehr aufwändige scroll depth tracking sache verdächtigt. var theOldScroll = theOldScroll || 0; function checkIfThresholdCrossed(currentScroll){ if(currentScroll != theOldScroll){ theOldScroll = currentScroll; return true; } return false; } function roundDown (num, precision) { num = parseFloat(num); if (!precision) return num.toLocaleString(); return (Math.floor(num / precision) * precision).toLocaleString(); }; function getDocHeight() { var D = document; return Math.max( D.body.scrollHeight, D.documentElement.scrollHeight, D.body.offsetHeight, D.documentElement.offsetHeight, D.body.clientHeight, D.documentElement.clientHeight ) } var docheight = getDocHeight() function amountscrolled(){ var winheight= window.innerHeight || (document.documentElement || document.body).clientHeight var docheight = getDocHeight() var scrollTop = window.pageYOffset || (document.documentElement || document.body.parentNode || document.body).scrollTop var trackLength = docheight - winheight var pctScrolled = Math.floor(scrollTop/trackLength * 100) // gets percentage scrolled (ie: 80 or NaN if tracklength == 0) var toLower10 = roundDown(pctScrolled,10); var weCrossedThreshold = checkIfThresholdCrossed(toLower10); if(weCrossedThreshold){ dataLayer.push({ "event":"scrollTimer_calculate", "ScrollDepth":toLower10 }); // document.title = toLower10+"% "+originalPageTitle; if({-System GET URL Parameter showScroll}}==1){ document.getElementById("scrollDisplay").innerText = toLower10+" %"; //console.log("Scrolled to: "+toLower10+" %"); } } } // window.addEventListener("scroll", function(){ amountscrolled() }, false) /* //if scroll Display for testing purposes is turned on, then show if({-System GET URL Parameter showScroll}}==1){ scrollDisplay = document.createElement("div"); var newContent = document.createTextNode("0%"); scrollDisplay.appendChild(newContent); // füge den Textknoten zum neu erstellten div hinzu scrollDisplay.id="scrollDisplay" //document.body.appendChild(scrollDisplay); document.body.insertBefore(scrollDisplay, document.body.firstChild); scrollDisplay.style.position="fixed"; scrollDisplay.style.top="40px"; scrollDisplay.style.top= "50%"; scrollDisplay.style.left= "80%"; scrollDisplay.style.background= "#ababab"; scrollDisplay.style.fontSize= "48px"; scrollDisplay.style.height= "50px"; scrollDisplay.style.lineHeight= "48px"; } //-------------------------- //-------------------------- //END SCROLL DEPTH TIMER //-------------------------- //-------------------------- */ /* gdprCookieString = {-DSGVO -Setting dsgvo__CONTENT entscheidet__Cookie CONTENT falls AKZEPTIERT}}; //manipulate string before alerting the rest of the programm //add GAPtoutString to cookieString gdprCookieString += ";"+GAOptoutString+"=false"; */ dataLayer.push({'event':'shoplytics_allFunctionsLoaded_in_0_Load All Functions',"author":"shoplytics.de"});;