Add simple traffic analytics with source attribution and conversion funnel

- track.js captures first-touch source per session (utm_source/src param
  or external referrer domain) and logs bridge/start page views.
- Join clicks now carry the source; all events aggregate per-source in
  data/analytics.json on the persistent volume.
- Admin: new Traffic & Conversions card with funnel totals (bridge ->
  start -> join click rates) and a per-source breakdown table.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-08-11 08:07:41 -05:00
parent ba14a1f1a9
commit 4115d3a920
8 changed files with 56 additions and 5 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ async function load(){
document.getElementById('copyButton').classList.add('hidden');
}
}
document.getElementById('joinButton').addEventListener('click',()=>{fetch('/api/public/join-click',{method:'POST'}).catch(()=>{})});
document.getElementById('joinButton').addEventListener('click',()=>{fetch('/api/public/join-click',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({source:window.ctbGetSource?window.ctbGetSource():'(direct)'})}).catch(()=>{})});
document.getElementById('copyButton').addEventListener('click',async()=>{
if(!currentSponsor)return; await navigator.clipboard.writeText(currentSponsor.id); const b=document.getElementById('copyButton'); const old=b.textContent;b.textContent='Copied ✓';setTimeout(()=>b.textContent=old,1400)
});