GEO Optimizer

Audit your website's visibility to AI search engines

Analyzing...
    stars 📦 downloads/mo 🔍 audits run
    async function runAudit() { const url = document.getElementById('url-input').value; if (!url) return; const btn = document.getElementById('btn'); const spinner = document.getElementById('spinner'); const errorEl = document.getElementById('error'); const resultEl = document.getElementById('result'); btn.disabled = true; spinner.classList.add('active'); errorEl.style.display = 'none'; resultEl.style.display = 'none'; try { const res = await fetch('/api/audit?url=' + encodeURIComponent(url)); const data = await res.json(); if (!res.ok) { throw new Error(data.detail || 'Errore audit'); } const colors = {excellent:'#22c55e',good:'#06b6d4',foundation:'#eab308',critical:'#ef4444'}; const color = colors[data.band] || '#888'; // Usa textContent per prevenire XSS const scoreEl = document.getElementById('score'); scoreEl.textContent = data.score + '/100'; scoreEl.style.color = color; const bandEl = document.getElementById('band'); bandEl.textContent = data.band.toUpperCase(); bandEl.style.color = color; // Costruisci check rows con metodi DOM sicuri const checksEl = document.getElementById('checks'); checksEl.textContent = ''; const checkNames = {robots_txt:'Robots.txt',llms_txt:'llms.txt', schema_jsonld:'Schema JSON-LD',meta_tags:'Meta Tags',content:'Content Quality'}; const checks = data.checks; for (const [key, label] of Object.entries(checkNames)) { const c = checks[key]; const ok = key === 'robots_txt' ? c.citation_bots_ok : key === 'llms_txt' ? c.found : key === 'schema_jsonld' ? c.has_website : key === 'meta_tags' ? (c.has_title && c.has_description) : c.has_h1; const row = document.createElement('div'); row.className = 'check-row'; const nameSpan = document.createElement('span'); nameSpan.textContent = label; const statusSpan = document.createElement('span'); statusSpan.textContent = ok ? '\u2705' : '\u274c'; row.appendChild(nameSpan); row.appendChild(statusSpan); checksEl.appendChild(row); } // Raccomandazioni con metodi DOM sicuri const recsEl = document.getElementById('recs'); recsEl.textContent = ''; for (const rec of data.recommendations) { const li = document.createElement('li'); li.textContent = rec; recsEl.appendChild(li); } // Link report con metodi DOM sicuri const reportLinkEl = document.getElementById('report-link'); reportLinkEl.textContent = ''; if (data.report_url) { const a = document.createElement('a'); a.href = data.report_url; a.target = '_blank'; a.rel = 'noopener'; a.textContent = 'View full HTML report'; reportLinkEl.appendChild(a); } resultEl.style.display = 'block'; } catch (e) { errorEl.textContent = e.message; errorEl.style.display = 'block'; } finally { btn.disabled = false; spinner.classList.remove('active'); } } // Event listener per il bottone Audit (al posto di onclick inline, bloccato dalla CSP) document.getElementById('btn').addEventListener('click', runAudit); document.getElementById('url-input').addEventListener('keypress', function(e) { if (e.key === 'Enter') runAudit(); }); // Carica le statistiche all'avvio della pagina (async function loadStats() { try { const res = await fetch('/api/stats'); if (!res.ok) return; const data = await res.json(); const fmt = (n) => n >= 1000 ? (n/1000).toFixed(1) + 'k' : String(n); document.getElementById('stars-count').textContent = fmt(data.github_stars); document.getElementById('downloads-count').textContent = fmt(data.pypi_downloads_month); document.getElementById('audits-count').textContent = fmt(data.audits_run); } catch (e) { /* silenzioso se le stats non sono disponibili */ } })();