Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Semantic SEO Intent Analyzer</title> | |
| <style> | |
| *{box-sizing:border-box;margin:0;padding:0} | |
| body{font-family:"Segoe UI",system-ui,sans-serif;background:#0f1117;color:#e2e8f0;min-height:100vh;padding:20px} | |
| h1{text-align:center;font-size:1.6rem;font-weight:700;color:#a78bfa;margin-bottom:4px} | |
| .subtitle{text-align:center;color:#94a3b8;font-size:.85rem;margin-bottom:24px} | |
| .grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;max-width:1200px;margin:0 auto} | |
| @media(max-width:768px){.grid{grid-template-columns:1fr}} | |
| .panel{background:#1e2130;border:1px solid #2d3148;border-radius:12px;padding:16px} | |
| .panel h2{font-size:.95rem;font-weight:600;color:#c4b5fd;margin-bottom:10px} | |
| textarea{width:100%;background:#0f1117;border:1px solid #2d3148;border-radius:8px;color:#e2e8f0;font-size:.85rem;padding:10px;resize:vertical;font-family:inherit;line-height:1.5} | |
| textarea:focus{outline:none;border-color:#7c3aed} | |
| .entity-row{display:flex;gap:6px;margin-bottom:6px;flex-wrap:wrap} | |
| .entity-tag{background:#312e81;color:#c4b5fd;border:1px solid #4c1d95;border-radius:20px;padding:3px 10px;font-size:.78rem;display:flex;align-items:center;gap:4px} | |
| .entity-tag .rm{color:#f87171;font-weight:700;cursor:pointer} | |
| .input-row{display:flex;gap:6px;margin-bottom:10px} | |
| .input-row input{flex:1;background:#0f1117;border:1px solid #2d3148;border-radius:8px;color:#e2e8f0;font-size:.85rem;padding:7px 10px} | |
| .input-row input:focus{outline:none;border-color:#7c3aed} | |
| .btn{background:#7c3aed;color:#fff;border:none;border-radius:8px;padding:8px 16px;font-size:.85rem;cursor:pointer;font-weight:600} | |
| .btn-analyze{width:100%;padding:12px;font-size:1rem;margin-top:10px;border-radius:10px;background:linear-gradient(135deg,#7c3aed,#4f46e5)} | |
| .results{max-width:1200px;margin:20px auto 0} | |
| .score-header{background:#1e2130;border:1px solid #2d3148;border-radius:12px;padding:20px;text-align:center;margin-bottom:16px} | |
| .total-score{font-size:3.5rem;font-weight:800;line-height:1} | |
| .score-label{color:#94a3b8;font-size:.9rem;margin-top:4px} | |
| .score-bar-wrap{background:#0f1117;border-radius:10px;height:12px;margin:12px auto;max-width:400px;overflow:hidden} | |
| .score-bar{height:100%;border-radius:10px;transition:width .8s ease} | |
| .metrics-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px;margin-bottom:16px} | |
| .metric-card{background:#1e2130;border:1px solid #2d3148;border-radius:10px;padding:14px} | |
| .metric-name{font-size:.78rem;color:#94a3b8;margin-bottom:6px;font-weight:600;text-transform:uppercase;letter-spacing:.04em} | |
| .metric-val{font-size:1.6rem;font-weight:700;margin-bottom:4px} | |
| .metric-bar-wrap{background:#0f1117;border-radius:6px;height:6px;overflow:hidden} | |
| .metric-bar{height:100%;border-radius:6px;transition:width .8s ease} | |
| .entity-results{background:#1e2130;border:1px solid #2d3148;border-radius:12px;padding:16px;margin-bottom:16px} | |
| .entity-results h3{font-size:.95rem;color:#c4b5fd;margin-bottom:12px} | |
| .ent-item{display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid #2d3148;flex-wrap:wrap} | |
| .ent-item:last-child{border-bottom:none} | |
| .ent-name{min-width:130px;font-size:.85rem;font-weight:600} | |
| .ent-bar-wrap{flex:1;min-width:80px;background:#0f1117;border-radius:6px;height:8px;overflow:hidden} | |
| .ent-bar{height:100%;border-radius:6px;transition:width .8s ease} | |
| .ent-score{min-width:40px;text-align:right;font-size:.85rem;font-weight:700} | |
| .ent-badges{display:flex;gap:4px;flex-wrap:wrap;min-width:160px} | |
| .badge{font-size:.7rem;padding:2px 7px;border-radius:10px;font-weight:600} | |
| .badge-found{background:#14532d;color:#86efac}.badge-action{background:#1e3a5f;color:#93c5fd}.badge-result{background:#422006;color:#fbbf24}.badge-causal{background:#3b1f52;color:#d8b4fe}.badge-missing{background:#3f0a0a;color:#fca5a5} | |
| .warnings{background:#1e2130;border:1px solid #2d3148;border-radius:12px;padding:16px;margin-bottom:16px} | |
| .warnings h3{font-size:.95rem;color:#f87171;margin-bottom:10px} | |
| .warn-item{font-size:.82rem;color:#fca5a5;padding:3px 0} | |
| .tips{background:#1e2130;border:1px solid #2d3148;border-radius:12px;padding:16px} | |
| .tips h3{font-size:.95rem;color:#34d399;margin-bottom:10px} | |
| .tip-item{font-size:.82rem;color:#6ee7b7;padding:3px 0} | |
| .hidden{display:none} | |
| .preset-btn{background:#1e2130;color:#a78bfa;border:1px solid #4c1d95;border-radius:16px;padding:4px 10px;font-size:.75rem;cursor:pointer} | |
| .presets{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px} | |
| </style> | |
| </head> | |
| <body> | |
| <h1>🔍 Semantic SEO Intent Analyzer</h1> | |
| <p class="subtitle">Entity → Action → Result triplet coverage scorer (0.01–1.00)</p> | |
| <div class="grid"> | |
| <div class="panel"><h2>Article Text</h2> | |
| <textarea id="articleText" rows="14" placeholder="Paste your article text here..."></textarea> | |
| </div> | |
| <div class="panel"><h2>Entities to Analyze</h2> | |
| <p style="font-size:.78rem;color:#94a3b8;margin-bottom:8px">Add entities that must be explained with Action and Result</p> | |
| <div class="presets"> | |
| <button class="preset-btn" onclick="loadPreset('rainbet')">RainBet/India</button> | |
| <button class="preset-btn" onclick="loadPreset('crypto')">Crypto/Blockchain</button> | |
| <button class="preset-btn" onclick="loadPreset('seo')">SEO/Content</button> | |
| </div> | |
| <div class="input-row"> | |
| <input id="entityInput" type="text" placeholder="Add entity (Enter or +)" onkeydown="if(event.key==='Enter')addEntity()"> | |
| <button class="btn" onclick="addEntity()">+</button> | |
| </div> | |
| <div id="entityTags" class="entity-row"></div> | |
| <h2 style="margin-top:14px">Settings</h2> | |
| <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:6px"> | |
| <label style="display:flex;flex-direction:column;gap:4px;font-size:.8rem;color:#94a3b8"><span>Min words/sentence</span><input id="minWords" type="number" value="5" min="1" max="30" style="background:#0f1117;border:1px solid #2d3148;border-radius:6px;color:#e2e8f0;padding:5px 8px;font-size:.82rem"></label> | |
| <label style="display:flex;flex-direction:column;gap:4px;font-size:.8rem;color:#94a3b8"><span>Cliche penalty (0-1)</span><input id="clishePenalty" type="number" value="0.15" min="0" max="1" step="0.05" style="background:#0f1117;border:1px solid #2d3148;border-radius:6px;color:#e2e8f0;padding:5px 8px;font-size:.82rem"></label> | |
| </div> | |
| <button class="btn btn-analyze" onclick="analyze()">▶ Analyze Text</button> | |
| </div></div> | |
| <div id="results" class="results hidden"></div> | |
| <script> | |
| var entities=[]; | |
| var PRESETS={ | |
| rainbet:["RainBet","India","INR","cryptocurrency","Bitcoin","Ethereum","blockchain","crypto wallet","KYC verification","provably fair","live casino","sports betting","IPL","SSL encryption","VIP program","withdrawal limits","betting odds","crash games"], | |
| crypto:["Bitcoin","Ethereum","blockchain","smart contract","DeFi","wallet","gas fees","staking","NFT","consensus mechanism"], | |
| seo:["keyword","backlink","meta description","canonical URL","structured data","page speed","crawl budget","E-E-A-T","search intent","SERP"] | |
| }; | |
| var AV=["supports","enables","allows","processes","uses","provides","requires","determines","affects","increases","reduces","improves","protects","encrypts","verifies","confirms","converts","generates","calculates","validates","triggers","causes","leads","results","ensures","prevents","manages","controls","limits","connects","depends","based","powered","built","operates","functions","delivers","handles","stores","creates","applies","serves","runs","works","performs","executes","accepts","sends","receives","returns","displays","shows","tracks","implements","defines","specifies","operates","integrates"]; | |
| var RM=["therefore","thus","hence","as a result","which means","allowing","enabling","making","ensuring","preventing","resulting","leading","causing","because","since","due to","thanks to","in order to","this means","this allows","this ensures","this prevents","consequently","so that","meaning","giving","granting"]; | |
| var CP=["because","since","due to","as a result","therefore","thus","which means","this means","enabling","allowing","causing","resulting in","leads to","depends on","based on","in order to","so that"]; | |
| var CL=["best platform","amazing experience","great service","top-notch","world-class","state-of-the-art","cutting-edge","revolutionary","game-changing","unparalleled","second to none","industry-leading","fast withdrawals","secure betting","trusted platform","reliable service","easy to use","user-friendly","seamless experience","wide selection","huge variety"]; | |
| function loadPreset(k){entities=PRESETS[k].slice();renderTags();} | |
| function addEntity(){var inp=document.getElementById("entityInput");var val=inp.value.trim();if(val&&entities.indexOf(val)===-1){entities.push(val);renderTags();}inp.value="";inp.focus();} | |
| function removeEntity(i){entities.splice(i,1);renderTags();} | |
| function renderTags(){document.getElementById("entityTags").innerHTML=entities.map(function(e,i){return'<span class="entity-tag">'+e+'<span class="rm" onclick="removeEntity('+i+')"> x</span></span>';}).join("");} | |
| function sc(s){if(s>=0.75)return"#34d399";if(s>=0.5)return"#fbbf24";if(s>=0.25)return"#f97316";return"#f87171";} | |
| function eh(t){return(""+t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");} | |
| function analyze(){ | |
| var text=document.getElementById("articleText").value.trim(); | |
| if(!text){alert("Please enter article text");return;} | |
| if(entities.length===0){alert("Please add at least one entity");return;} | |
| var minW=parseInt(document.getElementById("minWords").value)||5; | |
| var clP=parseFloat(document.getElementById("clishePenalty").value)||0.15; | |
| var tL=text.toLowerCase(); | |
| var sents=text.split(/[.!?]+/).map(function(s){return s.trim();}).filter(function(s){return s.split(/\s+/).length>=minW;}); | |
| var words=text.split(/\s+/).length; | |
| var eData=entities.map(function(entity){ | |
| var eL=entity.toLowerCase(); | |
| var re=new RegExp(eL.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"gi"); | |
| var mentions=(text.match(re)||[]).length; | |
| var found=mentions>0; | |
| var eS=sents.filter(function(s){return s.toLowerCase().indexOf(eL)!==-1;}); | |
| var aF=false,rF=false,cF=false; | |
| eS.forEach(function(s){ | |
| var sl=s.toLowerCase(); | |
| if(AV.some(function(v){return sl.indexOf(v)!==-1;}))aF=true; | |
| if(RM.some(function(m){return sl.indexOf(m)!==-1;}))rF=true; | |
| if(CP.some(function(p){return sl.indexOf(p)!==-1;}))cF=true; | |
| }); | |
| var score=0;if(found)score+=0.25;if(aF)score+=0.30;if(rF)score+=0.25;if(cF)score+=0.20;if(mentions>1)score=Math.min(score+0.05,1); | |
| return{entity:entity,found:found,aF:aF,rF:rF,cF:cF,mentions:mentions,score:Math.max(0.01,score)}; | |
| }); | |
| var avgE=eData.reduce(function(a,b){return a+b.score;},0)/eData.length; | |
| var tc=0;sents.forEach(function(s){var sl=s.toLowerCase();var hE=entities.some(function(e){return sl.indexOf(e.toLowerCase())!==-1;});var hA=AV.some(function(v){return sl.indexOf(v)!==-1;});var hR=RM.some(function(m){return sl.indexOf(m)!==-1;});if(hE&&hA&&hR)tc++;}); | |
| var tripS=Math.min(tc/Math.max(entities.length*0.6,1),1); | |
| var cc=0;sents.forEach(function(s){if(CP.some(function(p){return s.toLowerCase().indexOf(p)!==-1;}))cc++;}); | |
| var causS=Math.min(cc/Math.max(sents.length*0.3,1),1); | |
| var clF=[];CL.forEach(function(ph){if(tL.indexOf(ph)!==-1)clF.push(ph);}); | |
| var clT=Math.min(clF.length*clP,0.5); | |
| var totalM=eData.reduce(function(a,b){return a+b.mentions;},0); | |
| var densS=totalM>0?Math.min(totalM/(words/80),1):0.01; | |
| var cov=eData.filter(function(e){return e.found;}).length;var covS=cov/entities.length; | |
| var raw=(avgE*0.35+tripS*0.25+causS*0.20+densS*0.10+covS*0.10)-clT; | |
| var final=Math.max(0.01,Math.min(1,raw));var col=sc(final);var pct=Math.round(final*100); | |
| var mD=[{name:"Entity Coverage",val:covS,label:Math.round(covS*100)+"%"},{name:"Triplet Quality",val:tripS,label:tripS.toFixed(2)},{name:"Causal Density",val:causS,label:causS.toFixed(2)},{name:"Semantic Density",val:densS,label:densS.toFixed(2)},{name:"Avg Entity Score",val:avgE,label:avgE.toFixed(2)},{name:"Cliche Penalty",val:clT,label:"-"+clT.toFixed(2),inv:true}]; | |
| var mH=mD.map(function(m){var c=m.inv?"#f87171":sc(m.val);return'<div class="metric-card"><div class="metric-name">'+m.name+'</div><div class="metric-val" style="color:'+c+'">'+m.label+'</div><div class="metric-bar-wrap"><div class="metric-bar" style="width:'+Math.round(m.val*100)+'%;background:'+c+'"></div></div></div>';}).join(""); | |
| var miss=eData.filter(function(e){return!e.found;}).map(function(e){return e.entity;}); | |
| var noA=eData.filter(function(e){return e.found&&!e.aF;}).map(function(e){return e.entity;}); | |
| var noR=eData.filter(function(e){return e.found&&!e.rF;}).map(function(e){return e.entity;}); | |
| var eH=eData.map(function(e){var c=sc(e.score); | |
| var b=(e.found?'<span class="badge badge-found">Found</span>':'<span class="badge badge-missing">Missing</span>')+(e.aF?'<span class="badge badge-action">Action</span>':"" )+(e.rF?'<span class="badge badge-result">Result</span>':"")+(e.cF?'<span class="badge badge-causal">Causal</span>':""); | |
| return'<div class="ent-item"><div class="ent-name" style="color:'+c+'">'+eh(e.entity)+'</div><div class="ent-bar-wrap"><div class="ent-bar" style="width:'+Math.round(e.score*100)+'%;background:'+c+'"></div></div><div class="ent-score" style="color:'+c+'">'+e.score.toFixed(2)+'</div><div class="ent-badges">'+b+'</div></div>'; | |
| }).join(""); | |
| var warns=[]; | |
| if(miss.length>0)warns.push("Entities not found: "+eh(miss.join(", "))); | |
| if(noA.length>0)warns.push("No Action verb near: "+eh(noA.join(", "))); | |
| if(noR.length>0)warns.push("No Result/Effect near: "+eh(noR.join(", "))); | |
| if(clF.length>0)warns.push("Cliches found: "+eh(clF.join(", "))); | |
| if(sents.length<5)warns.push("Text too short for deep analysis"); | |
| var tips=[]; | |
| if(tripS<0.5)tips.push("Add sentences: [Entity] + [action verb] + [result clause]"); | |
| if(causS<0.4)tips.push("Use causal connectors: because, which means, as a result, enabling, due to"); | |
| if(cov<entities.length)tips.push("Cover missing entities: "+eh(miss.slice(0,5).join(", "))); | |
| if(clF.length>0)tips.push("Replace cliches with factual technical explanations"); | |
| if(final>=0.8)tips.push("Excellent! Text follows Entity -> Action -> Result structure well"); | |
| var wH=warns.length>0?'<div class="warnings"><h3>Issues ('+warns.length+')</h3>'+warns.map(function(w){return'<div class="warn-item">* '+w+'</div>';}).join("")+'</div>':""; | |
| var tH=tips.length>0?'<div class="tips"><h3>Recommendations</h3>'+tips.map(function(t){return'<div class="tip-item">-> '+t+'</div>';}).join("")+'</div>':""; | |
| var scoreRow=words+" words, "+sents.length+" sentences, "+cov+"/"+entities.length+" entities, "+tc+" full triplets"; | |
| document.getElementById("results").innerHTML= | |
| '<div class="score-header"><div class="total-score" style="color:'+col+'">'+final.toFixed(2)+'</div>' | |
| +'<div class="score-label">Semantic Intent Score (0.01 to 1.00)</div>' | |
| +'<div class="score-bar-wrap"><div class="score-bar" style="width:'+pct+'%;background:'+col+'"></div></div>' | |
| +'<div style="color:#94a3b8;font-size:.8rem;margin-top:6px">'+scoreRow+'</div></div>' | |
| +'<div class="metrics-grid">'+mH+'</div>' | |
| +'<div class="entity-results"><h3>Entity Breakdown</h3>'+eH+'</div>' | |
| +wH+tH; | |
| document.getElementById("results").classList.remove("hidden"); | |
| document.getElementById("results").scrollIntoView({behavior:"smooth"}); | |
| } | |
| </script> | |
| </body> | |
| </html> |