Umami-Tracking: Loader + track()-Helper, Auto-Tracking ausgehender Affiliate/Partner-Links, data-umami-event auf CTAs, Events für Monitor/Finder/Rechner/Alarm/Pro
This commit is contained in:
@@ -18,8 +18,8 @@ const typeLabel = product.type === 'mobile_split' ? 'Mobile Split' : 'Monoblock'
|
|||||||
<div><span class="note">Score</span><br /><strong class="num">{product.score}/100</strong></div>
|
<div><span class="note">Score</span><br /><strong class="num">{product.score}/100</strong></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="pc-cta">
|
<div class="pc-cta">
|
||||||
<a class="btn sm" href={`/karte?modell=${product.slug}`}>Verfügbarkeit</a>
|
<a class="btn sm" href={`/karte?modell=${product.slug}`} data-umami-event="card_verfuegbarkeit" data-umami-event-modell={product.slug}>Verfügbarkeit</a>
|
||||||
<a class="btn sm" href={idealo(product.name)} rel={REL} target="_blank">Preis prüfen ↗</a>
|
<a class="btn sm" href={idealo(product.name)} rel={REL} target="_blank" data-umami-event="card_preis_pruefen" data-umami-event-modell={product.slug}>Preis prüfen ↗</a>
|
||||||
<a class="btn sm ghost" href={`/geraete/${product.slug}`}>Details</a>
|
<a class="btn sm ghost" href={`/geraete/${product.slug}`}>Details</a>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import '../styles/global.css';
|
|||||||
<meta property="og:description" content={desc} />
|
<meta property="og:description" content={desc} />
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
{jsonld && <script type="application/ld+json" set:html={JSON.stringify(jsonld)} />}
|
{jsonld && <script type="application/ld+json" set:html={JSON.stringify(jsonld)} />}
|
||||||
|
<!-- Umami Analytics (self-hosted). TODO: data-website-id setzen, Host prüfen. -->
|
||||||
|
<script defer is:inline src="https://umami.heidrich-digital.de/script.js" data-website-id="REPLACE_WITH_UMAMI_WEBSITE_ID" data-domains="kuehlfinder.de"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header class="site"><div class="wrap bar">
|
<header class="site"><div class="wrap bar">
|
||||||
@@ -24,9 +26,9 @@ import '../styles/global.css';
|
|||||||
<a href="/rechner">Rechner</a>
|
<a href="/rechner">Rechner</a>
|
||||||
<a href="/finder">Finder</a>
|
<a href="/finder">Finder</a>
|
||||||
<a href="/alarm">Alarm</a>
|
<a href="/alarm">Alarm</a>
|
||||||
<a href="/pro">Pro</a>
|
<a href="/pro" data-umami-event="nav_pro">Pro</a>
|
||||||
<a href="/login">Login</a>
|
<a href="/login">Login</a>
|
||||||
<a class="nav-cta" href="/karte">Live-Karte</a>
|
<a class="nav-cta" href="/karte" data-umami-event="nav_live_karte">Live-Karte</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div></header>
|
</div></header>
|
||||||
<main><slot /></main>
|
<main><slot /></main>
|
||||||
@@ -48,6 +50,9 @@ import '../styles/global.css';
|
|||||||
}
|
}
|
||||||
document.addEventListener('DOMContentLoaded',wire); wire();
|
document.addEventListener('DOMContentLoaded',wire); wire();
|
||||||
window.kfAnim=wire;
|
window.kfAnim=wire;
|
||||||
|
window.track=function(name,data){try{window.umami&&window.umami.track(name,data);}catch(e){}};
|
||||||
|
// Auto-Tracking ausgehender Affiliate-/Partner-Links
|
||||||
|
document.addEventListener('click',function(e){var a=e.target.closest&&e.target.closest('a[href^="http"]');if(!a)return;var rel=(a.getAttribute('rel')||'');var host=(a.hostname||'');if(rel.includes('sponsored')||/amazon|ebay|idealo|mediamarkt|saturn|obi|bauhaus|hornbach|toom|hagebau|globus|klempnerei-stoever|tgasolutions/i.test(host)){window.track&&window.track('outbound_click',{host:host,label:(a.textContent||'').trim().slice(0,40)});}},true);
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<footer class="site"><div class="wrap">
|
<footer class="site"><div class="wrap">
|
||||||
|
|||||||
@@ -49,5 +49,5 @@ import { allProducts } from '../lib/pricing';
|
|||||||
<script>
|
<script>
|
||||||
const f=document.getElementById('alarmform'), pw=document.getElementById('pricewrap');
|
const f=document.getElementById('alarmform'), pw=document.getElementById('pricewrap');
|
||||||
document.querySelectorAll('.segbtn').forEach(b=>b.addEventListener('click',()=>{document.querySelectorAll('.segbtn').forEach(x=>x.classList.remove('on'));b.classList.add('on');pw.hidden=b.dataset.mode!=='price';}));
|
document.querySelectorAll('.segbtn').forEach(b=>b.addEventListener('click',()=>{document.querySelectorAll('.segbtn').forEach(x=>x.classList.remove('on'));b.classList.add('on');pw.hidden=b.dataset.mode!=='price';}));
|
||||||
f.addEventListener('submit',e=>{e.preventDefault();const n=f.querySelectorAll('input[name=artikel]:checked').length;document.getElementById('alarmmsg').textContent=`Demo: ${n||'alle'} Wunschartikel vorgemerkt. Backend (Listmonk + Telegram) folgt – nichts gespeichert.`;});
|
f.addEventListener('submit',e=>{e.preventDefault();const n=f.querySelectorAll('input[name=artikel]:checked').length;window.track&&window.track('alarm_submit',{artikel:n});document.getElementById('alarmmsg').textContent=`Demo: ${n||'alle'} Wunschartikel vorgemerkt. Backend (Listmonk + Telegram) folgt – nichts gespeichert.`;});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ const products = allProducts.map(p=>({slug:p.slug,name:p.name,type:p.type,badge:
|
|||||||
return {primary:find(primary),alt:find(alt),budget:find(budget),warn};
|
return {primary:find(primary),alt:find(alt),budget:find(budget),warn};
|
||||||
}
|
}
|
||||||
function result(){
|
function result(){
|
||||||
const r=pick();
|
const r=pick(); window.track&&window.track("finder_ergebnis",{modell:r.primary&&r.primary.slug});
|
||||||
const card=p=>`<a class="rc" href="/geraete/${p.slug}"><strong>${p.name}</strong><span class="note">${p.badge}</span></a>`;
|
const card=p=>`<a class="rc" href="/geraete/${p.slug}"><strong>${p.name}</strong><span class="note">${p.badge}</span></a>`;
|
||||||
el.innerHTML=`<h2>Deine Empfehlung</h2>
|
el.innerHTML=`<h2>Deine Empfehlung</h2>
|
||||||
<div class="reco"><span class="badge">Beste Wahl</span>${card(r.primary)}</div>
|
<div class="reco"><span class="badge">Beste Wahl</span>${card(r.primary)}</div>
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ const Bell='<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="
|
|||||||
<p class="lead">Bei Hitze ist alles vergriffen. Kühlfinder ist dein Kontrollzentrum: <strong>live sehen, welcher Markt in der Nähe eins auf Lager hat</strong> – Baumärkte, Elektromärkte, Online & eBay – mit Prognose, Preis-Check gegen Wucher und Alarm. <em>Die nächste Hitzewelle kommt bestimmt.</em></p>
|
<p class="lead">Bei Hitze ist alles vergriffen. Kühlfinder ist dein Kontrollzentrum: <strong>live sehen, welcher Markt in der Nähe eins auf Lager hat</strong> – Baumärkte, Elektromärkte, Online & eBay – mit Prognose, Preis-Check gegen Wucher und Alarm. <em>Die nächste Hitzewelle kommt bestimmt.</em></p>
|
||||||
<form class="herobar" action="/karte" method="get">
|
<form class="herobar" action="/karte" method="get">
|
||||||
<input name="plz" inputmode="numeric" placeholder="PLZ oder Ort …" aria-label="PLZ oder Ort" />
|
<input name="plz" inputmode="numeric" placeholder="PLZ oder Ort …" aria-label="PLZ oder Ort" />
|
||||||
<button class="btn" type="submit">Verfügbarkeit zeigen</button>
|
<button class="btn" type="submit" data-umami-event="hero_plz_suche">Verfügbarkeit zeigen</button>
|
||||||
<a class="btn ghost" href="/karte" id="locbtn">In meiner Nähe</a>
|
<a class="btn ghost" href="/karte" id="locbtn" data-umami-event="hero_naehe">In meiner Nähe</a>
|
||||||
</form>
|
</form>
|
||||||
<div class="livewrap reveal">
|
<div class="livewrap reveal">
|
||||||
<div class="pills">
|
<div class="pills">
|
||||||
|
|||||||
@@ -224,17 +224,17 @@ const jsonld={'@context':'https://schema.org','@type':'WebApplication',name:'Kü
|
|||||||
if(DATA)render();
|
if(DATA)render();
|
||||||
});
|
});
|
||||||
$('#q').addEventListener('input',e=>{state.q=e.target.value.trim();shown=120;render();});
|
$('#q').addEventListener('input',e=>{state.q=e.target.value.trim();shown=120;render();});
|
||||||
$('#model').addEventListener('change',e=>{state.model=e.target.value;render();});
|
$('#model').addEventListener('change',e=>{state.model=e.target.value;window.track&&window.track('monitor_modell',{modell:state.model});render();});
|
||||||
$$('.chip[data-toggle]').forEach(b=>b.addEventListener('click',()=>{state[b.dataset.toggle]=!state[b.dataset.toggle];b.classList.toggle('on');render();}));
|
$$('.chip[data-toggle]').forEach(b=>b.addEventListener('click',()=>{state[b.dataset.toggle]=!state[b.dataset.toggle];b.classList.toggle('on');render();}));
|
||||||
$$('.chip[data-kind]').forEach(b=>b.addEventListener('click',()=>{state.kind=b.dataset.kind;$$('.chip[data-kind]').forEach(x=>x.classList.remove('on'));b.classList.add('on');render();}));
|
$$('.chip[data-kind]').forEach(b=>b.addEventListener('click',()=>{state.kind=b.dataset.kind;$$('.chip[data-kind]').forEach(x=>x.classList.remove('on'));b.classList.add('on');render();}));
|
||||||
$('#radius').addEventListener('input',e=>{state.radius=+e.target.value;$('#r-out').textContent=state.radius+' km';render();});
|
$('#radius').addEventListener('input',e=>{state.radius=+e.target.value;$('#r-out').textContent=state.radius+' km';render();});
|
||||||
$('#more').addEventListener('click',()=>{shown+=120;render();});
|
$('#more').addEventListener('click',()=>{shown+=120;render();});
|
||||||
$('#reset').addEventListener('click',()=>location.reload());
|
$('#reset').addEventListener('click',()=>location.reload());
|
||||||
$$('.mtab th[data-sort]').forEach(th=>th.addEventListener('click',()=>{state.chance=true;render();}));
|
$$('.mtab th[data-sort]').forEach(th=>th.addEventListener('click',()=>{state.chance=true;render();}));
|
||||||
$('#locate').addEventListener('click',()=>{if(!navigator.geolocation)return;navigator.geolocation.getCurrentPosition(p=>{center=[p.coords.longitude,p.coords.latitude];$('#radius').disabled=false;state.radius=100;$('#radius').value=100;$('#r-out').textContent='100 km';new maplibregl.Marker({color:'#185fa5'}).setLngLat(center).addTo(map);map.flyTo({center,zoom:8});render();});});
|
$('#locate').addEventListener('click',()=>{if(!navigator.geolocation)return;window.track&&window.track('monitor_standort');navigator.geolocation.getCurrentPosition(p=>{center=[p.coords.longitude,p.coords.latitude];$('#radius').disabled=false;state.radius=100;$('#radius').value=100;$('#r-out').textContent='100 km';new maplibregl.Marker({color:'#185fa5'}).setLngLat(center).addTo(map);map.flyTo({center,zoom:8});render();});});
|
||||||
$$('#scope .chip').forEach(b=>b.addEventListener('click',()=>{
|
$$('#scope .chip').forEach(b=>b.addEventListener('click',()=>{
|
||||||
$$('#scope .chip').forEach(x=>x.classList.remove('on'));b.classList.add('on');
|
$$('#scope .chip').forEach(x=>x.classList.remove('on'));b.classList.add('on');
|
||||||
if(b.dataset.scope==='de'){state.countries=new Set(['DE']);} else {state.countries=new Set();}
|
window.track&&window.track('monitor_scope',{scope:b.dataset.scope});if(b.dataset.scope==='de'){state.countries=new Set(['DE']);} else {state.countries=new Set();}
|
||||||
$$('#countrychips .chip').forEach(c=>c.classList.toggle('on', state.countries.has(c.dataset.cc)));
|
$$('#countrychips .chip').forEach(c=>c.classList.toggle('on', state.countries.has(c.dataset.cc)));
|
||||||
render();
|
render();
|
||||||
}));
|
}));
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ const jsonld={'@context':'https://schema.org','@type':'FAQPage',mainEntity:[
|
|||||||
<li>★ <strong>Preiswecker</strong>: Alarm, wenn Preis unter dein Limit fällt</li>
|
<li>★ <strong>Preiswecker</strong>: Alarm, wenn Preis unter dein Limit fällt</li>
|
||||||
<li>★ Beste-Chancen-Route in deinem Umkreis</li>
|
<li>★ Beste-Chancen-Route in deinem Umkreis</li>
|
||||||
</ul>
|
</ul>
|
||||||
<a class="btn" href="/alarm">Pro-Pass holen</a>
|
<a class="btn" href="/alarm" data-umami-event="pro_pass_cta">Pro-Pass holen</a>
|
||||||
<p class="note" style="margin:.5rem 0 0">Zahlung per Stripe (folgt). Keine automatische Verlängerung.</p>
|
<p class="note" style="margin:.5rem 0 0">Zahlung per Stripe (folgt). Keine automatische Verlängerung.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -107,6 +107,6 @@ const products = allProducts.map(p=>({slug:p.slug,name:p.name,type:p.type,btuh:p
|
|||||||
}
|
}
|
||||||
$('#m2').addEventListener('input',e=>{S.m2=+e.target.value;$('#m2-out').textContent=S.m2+' m²';calc();});
|
$('#m2').addEventListener('input',e=>{S.m2=+e.target.value;$('#m2-out').textContent=S.m2+' m²';calc();});
|
||||||
['room','sun','mode'].forEach(g=>$$('#'+g+' .segbtn').forEach(b=>b.addEventListener('click',()=>{
|
['room','sun','mode'].forEach(g=>$$('#'+g+' .segbtn').forEach(b=>b.addEventListener('click',()=>{
|
||||||
$$('#'+g+' .segbtn').forEach(x=>x.classList.remove('on'));b.classList.add('on');S[g]=b.dataset.v;calc();})));
|
$$('#'+g+' .segbtn').forEach(x=>x.classList.remove('on'));b.classList.add('on');S[g]=b.dataset.v;window.track&&window.track('rechner_input',{feld:g,wert:b.dataset.v});calc();})));
|
||||||
calc();
|
calc();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user