📊 Analytics Dashboard

Visitors

0

Page Views

0

Anime Views

0

Episode Views

0

Downloads

0

Searches

0

🔥 Top Anime

    📺 Top Episodes

      🔍 Trending Searches

        🗂 Popular Categories

          🖼 Banner Performance

            🎞 Player Servers

              /* ============================================================ ANIMEHUNT CMS - COMPLETE ANALYTICS SYSTEM ============================================================ */ const API_BASE = "https://animehunt-backend.animehunt715.workers.dev/api" const ADMIN_ANALYTICS = API_BASE + "/admin/analytics" const TRACK_API = API_BASE + "/analytics/track" const TOKEN_KEY = "AUTH_TOKEN" const rangeSelect = document.getElementById("range") /* ============================================================ AUTH CHECK ============================================================ */ function getToken(){ return localStorage.getItem(TOKEN_KEY) } if(!getToken()){ location.href="login.html" } /* ============================================================ SAFE FETCH ============================================================ */ async function api(url,options={}){ try{ const res = await fetch(url,{ ...options, headers:{ "Content-Type":"application/json", "Authorization":"Bearer " + getToken(), ...(options.headers||{}) } }) if(res.status===401){ location.href="login.html" return } if(!res.ok){ throw new Error("API Error") } return await res.json() }catch(err){ console.error("API Error:",err) return null } } /* ============================================================ LIST RENDER ============================================================ */ function fillList(el,list,keyName,valName){ if(!el) return el.innerHTML="" if(!list || list.length===0){ el.innerHTML = `
            • No data available
            • `return } const maxVal = Math.max(...list.map(i=>i[valName]||0)) list.forEach(item=>{ const key = item[keyName] || "Unknown" const val = item[valName] || 0 const percent = maxVal>0 ? (val/maxVal)*100 : 0 const li = document.createElement("li") li.style.cssText="position:relative; padding:10px; margin-bottom:4px; border-bottom:1px solid #1a2035; display:flex; justify-content:space-between; overflow:hidden;" li.innerHTML=`
              ${key} ${val} ` el.appendChild(li) }) } /* ============================================================ LOAD ANALYTICS ============================================================ */ async function loadAnalytics(){ const range = rangeSelect?.value || "7" document.querySelectorAll(".stat-card p") .forEach(el=>el.style.opacity="0.4") const data = await api( "${ADMIN_ANALYTICS}?range=${range}" ) if(!data){ return } /* STATS */ setText("visitors",data.stats.visitors) setText("views",data.stats.pageViews) setText("animeViews",data.stats.animeViews) setText("episodeViews",data.stats.episodeViews) setText("downloads",data.stats.downloads) setText("searches",data.stats.searches) /* LISTS */ fillList( document.getElementById("topAnime"), data.topAnime, "slug", "v" ) fillList( document.getElementById("topEpisodes"), data.topEpisodes, "id", "v" ) fillList( document.getElementById("topSearches"), data.topSearches, "q", "c" ) fillList( document.getElementById("topCategories"), data.topCategories, "cat", "v" ) fillList( document.getElementById("topBanners"), data.topBanners, "ban", "c" ) fillList( document.getElementById("topServers"), data.topServers, "srv", "v" ) document.querySelectorAll(".stat-card p") .forEach(el=>el.style.opacity="1") } /* ============================================================ SET TEXT SAFE ============================================================ */ function setText(id,val){ const el = document.getElementById(id) if(!el) return el.textContent = Number(val||0).toLocaleString() } /* ============================================================ TRACKING FUNCTIONS ============================================================ */ function trackEvent(type,data={}){ fetch(TRACK_API,{ method:"POST", headers:{ "Content-Type":"application/json" }, body:JSON.stringify({ type, ...data }) }) } /* PAGE VIEW */ function trackPage(){ trackEvent("page",{ ref:location.pathname }) } /* ANIME VIEW */ function trackAnime(slug){ trackEvent("anime",{ ref:slug }) } /* EPISODE VIEW */ function trackEpisode(id){ trackEvent("episode",{ ref:id }) } /* DOWNLOAD */ function trackDownload(id){ trackEvent("download",{ ref:id }) } /* SEARCH */ function trackSearch(query){ trackEvent("search",{ value:query }) } /* BANNER */ function trackBanner(id){ trackEvent("banner",{ ref:id }) } /* SERVER */ function trackServer(server){ trackEvent("server",{ ref:server }) } /* CATEGORY */ function trackCategory(cat){ trackEvent("category",{ ref:cat }) } /* ============================================================ INIT ============================================================ */ document.addEventListener("DOMContentLoaded",()=>{ trackPage() loadAnalytics() }) if(rangeSelect){ rangeSelect.addEventListener( "change", loadAnalytics ) } /* AUTO REFRESH */ setInterval(loadAnalytics,120000)