GEO Optimizer
v4.0.0
☰
Audit
Compare
Docs
More
Research
Roadmap
Manifesto
GitHub
Compare GEO Scores
Side-by-side — see who's more visible to AI
VS
Compare
Analyzing both sites... this may take up to 60 seconds.
fetch('/api/stats').then(function(r){return r.json()}).then(function(d){var ns=document.getElementById('nav-stars');if(ns&&d.github_stars)ns.textContent='★ '+d.github_stars}).catch(function(){}); const BANDS={excellent:'#22c55e',good:'#06b6d4',foundation:'#eab308',critical:'#ef4444'}; const CATS=[{k:'robots',l:'Robots',m:18},{k:'llms',l:'llms.txt',m:18},{k:'schema',l:'Schema',m:16},{k:'meta',l:'Meta',m:14},{k:'content',l:'Content',m:12},{k:'signals',l:'Signals',m:6},{k:'ai_discovery',l:'AI Disc.',m:6},{k:'brand_entity',l:'Brand',m:10}]; const $=id=>document.getElementById(id); $('btn').addEventListener('click',run); $('url2').addEventListener('keypress',e=>{if(e.key==='Enter')run()}); function isValidUrl(str){ if(/^https?:\/\/.+\..+/.test(str))return true; if(/^[^\s]+\.[a-z]{2,}(\/.*)?$/i.test(str))return true; return false; } async function run(){ let u1=$('url1').value.trim(),u2=$('url2').value.trim(); if(!u1||!u2)return; if(!isValidUrl(u1)){$('error').textContent='Site A: please enter a valid URL';$('error').style.display='block';return} if(!isValidUrl(u2)){$('error').textContent='Site B: please enter a valid URL';$('error').style.display='block';return} if(!/^https?:\/\//i.test(u1))u1='https://'+u1;$('url1').value=u1; if(!/^https?:\/\//i.test(u2))u2='https://'+u2;$('url2').value=u2; $('btn').disabled=true;$('spinner').classList.add('active');$('error').style.display='none';$('results').style.display='none'; try{ const [s1,s2]=await Promise.allSettled([fetch('/api/audit?url='+encodeURIComponent(u1)),fetch('/api/audit?url='+encodeURIComponent(u2))]); const errs=[]; let d1=null,d2=null; if(s1.status==='fulfilled'&&s1.value.ok){d1=await s1.value.json()}else{errs.push('Site A: '+(s1.reason?.message||'Error'))} if(s2.status==='fulfilled'&&s2.value.ok){d2=await s2.value.json()}else{errs.push('Site B: '+(s2.reason?.message||'Error'))} if(!d1&&!d2)throw new Error(errs.join('; ')); if(d1&&d2){render(d1,d2);$('results').style.display='block'} else{if(d1||d2){render(d1||{score:0,band:'critical',url:u1},d2||{score:0,band:'critical',url:u2});$('results').style.display='block'}if(errs.length){$('error').textContent=errs.join('; ');$('error').style.display='block'}} }catch(e){$('error').textContent=e.message;$('error').style.display='block'} finally{$('btn').disabled=false;$('spinner').classList.remove('active')} } function render(a,b){ const g=$('grid');g.textContent=''; [a,b].forEach((d,i)=>{ const win=(i===0?a.score>b.score:b.score>a.score); const c=document.createElement('div');c.className='card'+(win?' winner':''); const color=BANDS[d.band]||'#888'; const url=document.createElement('div');url.className='card-url';url.textContent=d.url||(i===0?$('url1').value:$('url2').value);c.appendChild(url); const sc=document.createElement('div');sc.className='card-score';sc.style.color=color;sc.textContent=d.score+'/100';c.appendChild(sc); const bd=document.createElement('div');bd.className='card-band';bd.style.color=color;bd.textContent=(d.band||'').toUpperCase();c.appendChild(bd); const bars=document.createElement('div');bars.className='bars'; const br=d.score_breakdown||{}; for(const cat of CATS){ const v=br[cat.k]||0;const pct=Math.min(v/cat.m*100,100); const row=document.createElement('div');row.className='bar-row'; const lbl=document.createElement('span');lbl.className='bar-lbl';lbl.textContent=cat.l; const track=document.createElement('div');track.className='bar-track'; const fill=document.createElement('div');fill.className='bar-fill';fill.style.width='0%';fill.style.background=color; track.appendChild(fill); const val=document.createElement('span');val.className='bar-val';val.textContent=v; row.appendChild(lbl);row.appendChild(track);row.appendChild(val);bars.appendChild(row); requestAnimationFrame(()=>{requestAnimationFrame(()=>{fill.style.width=pct+'%'})}); } c.appendChild(bars);g.appendChild(c); }); } document.getElementById('nav-ham').addEventListener('click',function(){ document.querySelector('.nav-links').classList.toggle('open'); this.textContent=this.textContent==='☰'?'✕':'☰'; }); document.querySelectorAll('.nav-dropdown-toggle').forEach(function(btn){ btn.addEventListener('click',function(e){ e.stopPropagation(); var dd=this.closest('.nav-dropdown'); dd.classList.toggle('open'); this.setAttribute('aria-expanded',dd.classList.contains('open')); }); }); document.addEventListener('click',function(){ document.querySelectorAll('.nav-dropdown.open').forEach(function(dd){ dd.classList.remove('open'); dd.querySelector('.nav-dropdown-toggle').setAttribute('aria-expanded','false'); }); });