Audit
Compare
Roadmap
Research
Docs
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.
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:22},{k:'meta',l:'Meta',m:14},{k:'content',l:'Content',m:14},{k:'signals',l:'Signals',m:8},{k:'ai_discovery',l:'AI Disc.',m:6}]; const $=id=>document.getElementById(id); $('btn').addEventListener('click',run); $('url2').addEventListener('keypress',e=>{if(e.key==='Enter')run()}); async function run(){ const u1=$('url1').value,u2=$('url2').value; if(!u1||!u2)return; $('btn').disabled=true;$('spinner').classList.add('active');$('error').style.display='none';$('results').style.display='none'; try{ const [r1,r2]=await Promise.all([fetch('/api/audit?url='+encodeURIComponent(u1)),fetch('/api/audit?url='+encodeURIComponent(u2))]); const [d1,d2]=await Promise.all([r1.json(),r2.json()]); if(!r1.ok)throw new Error('Site A: '+(d1.detail||'Error')); if(!r2.ok)throw new Error('Site B: '+(d2.detail||'Error')); render(d1,d2);$('results').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); }); }