1import{p as X,n as Y}from"./contentLanguages-AMyI2xtN.js";import{i as ee,n as te}from"./domains-ChqGQsKY.js";import{c as I,a as ie}from"./edgeProxy-Leo76bcu.js";import{g as oe}from"./standaloneContent-rFPRhids.js";import{s as S}from"./index-g1AjuXVI.js";import"./dataforseo-CS69Lx19.js";import"./seoMarkets-Bgv7DF-1.js";import"./imageService-B86XwPJA.js";import"./citationVerifier-CoAkvesY.js";import"./perplexity-BVOaEMFv.js";import"./moneyPages-DcnZ_Ff8.js";import"./geoCitationPack-CnjB46Ha.js";import"./searchIntent-DP837Ums.js";import"./keywords-oR1Ak5-5.js";import"./contentIntegrity-7lDEigJ1.js";function ne(i){return i.replace(/(<script[^>]*type=["']application\/ld\+json["'][^>]*>)([\s\S]*?)(<\/script>)/gi,(t,e,o,s)=>`${e}${o.replace(/<br\s*\/?>/gi,"").replace(/ /gi," ")}${s}`)}function ae(i){const t=ne(i),e=/<script[^>]*type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/gi,o=[];let s=0,l=0,a;for(;(a=e.exec(t))!==null;){s+=1;const r=a[1]?.trim()??"";if(!r){o.push("Empty JSON-LD block");continue}try{JSON.parse(r),l+=1}catch(c){o.push(c instanceof Error?c.message.slice(0,120):"Invalid JSON-LD")}}return{blockCount:s,validBlocks:l,invalidBlocks:s-l,errors:o}}function se(i){const t=[],e=/<h1\b[^>]*>([\s\S]*?)<\/h1>/gi;let o;for(;(o=e.exec(i))!==null;){const s=(o[1]??"").replace(/<[^>]+>/g,"").trim();s&&t.push(s)}return{count:t.length,texts:t}}const re=["amazon.","ebay.","wikipedia.","facebook.","instagram."];function le(i,t){const e=[],o=new Set,s=/<a\b[^>]*href=["']([^"']+)["'][^>]*>/gi;let l;for(;(l=s.exec(i))!==null;){const a=(l[1]??"").trim();if(!a||a==="#"){e.push({href:a||"(empty)",reason:"empty"});continue}if(a.startsWith("javascript:"))continue;let r=a;try{r=new URL(a,t).href}catch{continue}const c=r.toLowerCase();if(o.has(c)){e.push({href:r,reason:"duplicate"});continue}if(o.add(c),!ee(r,t)){const u=te(r);re.some(A=>u.includes(A))&&e.push({href:r,reason:"external_competitor"});continue}try{const u=new URL(r);(u.pathname==="/"||u.pathname==="")&&e.push({href:r,reason:"suspicious_home_redirect"})}catch{}}return e}function ce(i,t){return{jsonLd:ae(i),h1:se(i),internalLinkIssues:le(i,t)}}const M={is_broken:{code:"is_broken",severity:"critical",dimension:"seo",label:{it:"Pagine non raggiungibili (link rotti)",en:"Unreachable pages (broken links)"},why:{it:"Bloccano crawler e utenti; sprecano crawl budget e perdono autorità .",en:"They block crawlers and users; waste crawl budget and leak link authority."}},is_4xx_code:{code:"is_4xx_code",severity:"critical",dimension:"seo",label:{it:"Errori 4xx",en:"4xx errors"},why:{it:"Pagine mancanti: niente ranking né citazioni AI.",en:"Missing pages: no rankings and no AI citations."}},is_5xx_code:{code:"is_5xx_code",severity:"critical",dimension:"seo",label:{it:"Errori server 5xx",en:"5xx server errors"},why:{it:"Il sito non risponde: crawler e AI non possono leggere il contenuto.",en:"The site fails to respond: crawlers and AI cannot read the content."}},no_title:{code:"no_title",severity:"critical",dimension:"seo",label:{it:"Title mancante",en:"Missing title tag"},why:{it:"Il title è il segnale di rilevanza #1 per Google e per gli snippet AI.",en:"The title is the #1 relevance signal for Google and for AI snippets."}},no_description:{code:"no_description",severity:"warning",dimension:"seo",label:{it:"Meta description mancante",en:"Missing meta description"},why:{it:"Riduce CTR e priva lâAI di un riassunto pronto da citare.",en:"Lowers CTR and deprives AI of a ready-made summary to cite."}},no_h1_tag:{code:"no_h1_tag",severity:"warning",dimension:"seo",label:{it:"H1 mancante",en:"Missing H1"},why:{it:"LâH1 definisce il tema della pagina per motori e LLM.",en:"The H1 defines the page topic for search engines and LLMs."}},duplicate_title_tag:{code:"duplicate_title_tag",severity:"warning",dimension:"seo",label:{it:"Title duplicati",en:"Duplicate titles"},why:{it:"Cannibalizzazione: Google non sa quale pagina premiare.",en:"Cannibalization: Google canât tell which page to reward."}},duplicate_description:{code:"duplicate_description",severity:"warning",dimension:"seo",label:{it:"Description duplicate",en:"Duplicate descriptions"},why:{it:"Segnale di contenuto non differenziato.",en:"A signal of undifferentiated content."}},title_too_long:{code:"title_too_long",severity:"opportunity",dimension:"seo",label:{it:"Title troppo lunghi",en:"Titles too long"},why:{it:"Vengono troncati in SERP, perdendo keyword e CTR.",en:"They get truncated in the SERP, losing keywords and CTR."}},high_loading_time:{code:"high_loading_time",severity:"warning",dimension:"seo",label:{it:"Caricamento lento",en:"Slow loading"},why:{it:"Core Web Vitals scarsi penalizzano ranking ed esperienza.",en:"Poor Core Web Vitals hurt both rankings and user experience."}},no_image_alt:{code:"no_image_alt",severity:"opportunity",dimension:"seo",label:{it:"Immagini senza alt",en:"Images without alt text"}
1,why:{it:"Accessibilità e contesto immagine per ricerca/AI.",en:"Accessibility and image context for search and AI."}},low_content_rate:{code:"low_content_rate",severity:"warning",dimension:"geo",label:{it:"Poco testo rispetto al codice",en:"Low text-to-code ratio"},why:{it:"Contenuto sottile: poco materiale citabile dallâAI.",en:"Thin content: little material for AI to cite."}},small_page_size:{code:"small_page_size",severity:"opportunity",dimension:"geo",label:{it:"Pagine molto corte",en:"Very short pages"},why:{it:"Contenuto thin: difficile rankare o essere citati.",en:"Thin content: hard to rank or get cited."}},canonical:{code:"canonical",severity:"opportunity",dimension:"seo",label:{it:"Canonical assente su alcune pagine",en:"Canonical missing on some pages"},why:{it:"Aiuta a consolidare i segnali ed evitare duplicati.",en:"It helps consolidate signals and avoid duplicates."}},no_favicon:{code:"no_favicon",severity:"opportunity",dimension:"seo",label:{it:"Favicon mancante",en:"Missing favicon"},why:{it:"Segnale minore di cura/brand; appare negli snippet.",en:"A minor brand/care signal; it shows up in snippets."}}},q=5;function N(i){let t=2166136261;for(let e=0;e<i.length;e++)t^=i.charCodeAt(e),t=Math.imul(t,16777619);return t>>>0}function de(i,t){const e=i.replace(/\/$/,""),o=`${e}/`,l=[...new Set(t)].filter(a=>a!==o&&a!==e);return l.sort((a,r)=>{const c=N(`${i}|${a}`)-N(`${i}|${r}`);return c!==0?c:a.localeCompare(r)}),[o,...l]}async function ue(i,t){const e=new Set,o=i.replace(/\/$/,"");e.add(`${o}/`);let s;try{const l=await oe(i);l.length&&(s=new Set(l.map(a=>a.url)).size);for(const a of l)e.add(a.url)}catch{}return{pages:de(i,[...e]).slice(0,t),sitemapPageCount:s}}async function pe(i){try{const e=(await ie("/on_page/instant_pages",{url:i,enable_javascript:!1}))?.tasks?.[0]?.result?.[0]?.items?.[0];return e?{...e,url:i}:null}catch(t){return console.warn("[SiteAudit] instant_pages failed for",i,t),null}}function he(i){return/<table[\s>][\s\S]*?<t[dh][\s>]/i.test(i)?!0:/<(ul|ol)[\s>][\s\S]*?<li[\s>]/i.test(i)}function ge(i){const t=/^(come|cosa|quando|perche|quali|quale|chi|dove|quant[oiae]|how|what|why|when|which|who|where|can|should|is|are|do|does)\b/i;for(const e of i.matchAll(/<h[23][^>]*>([\s\S]*?)<\/h[23]>/gi)){const o=e[1].replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim();if(!o)continue;const s=o.normalize("NFD").replace(/[Ì-ͯ]/g,"");if(/\?\s*$/.test(o)||t.test(s))return!0}return!1}async function me(i,t){try{const e=await I(i),o=ce(e,t),s=o.jsonLd.blockCount>0&&o.jsonLd.validBlocks>0,l=/"@type"\s*:\s*"(FAQPage|Article|NewsArticle|BlogPosting|HowTo)"/i.test(e),a=/rel=["']author["']|"@type"\s*:\s*"Person"|class=["'][^"']*author/i.test(e),r=/"@type"\s*:\s*"(Organization|LocalBusiness|[A-Za-z]*Business|Corporation|OnlineStore|Store|NGO)"/i.test(e);return{url:i,schema:s,articleOrFaq:l,author:a,orgSchema:r,extractableStructure:he(e),questionHeading:ge(e),invalidJsonLd:o.jsonLd.invalidBlocks>0,multipleH1:o.h1.count>1,internalLinkIssueCount:o.internalLinkIssues.length,fetched:!0}}catch{return{url:i,schema:!1,articleOrFaq:!1,author:!1,orgSchema:!1,extractableStructure:!1,questionHeading:!1,invalidJsonLd:!1,multipleH1:!1,internalLinkIssueCount:0,fetched:!1}}}const fe=["OAI-SearchBot","Claude-SearchBot","PerplexityBot","Googlebot"],ye=["GPTBot","ClaudeBot","Google-Extended"];function be(i){const t=i.split(/\r?\n/).map(s=>s.replace(/#.*$/,"").trim()).filter(s=>s.length>0),e=[];let o=0;for(;o<t.length;){if(!/^user-agent:/i.test(t[o])){o++;continue}const s=[];for(;o<t.length&&/^user-agent:/i.test(t[o]);)s.push(t[o].slice(t[o].indexOf(":")+1).trim().toLowerCase()),o++;const l=[];for(;o<t.length&&!/^user-agent:/i.test(t[o]);){const a=t[o].match(/^disallow:\s*(.*)$/i),r=t[o].match(/^allow:\s*(.*)$/i);a&&a[1].trim()?l.push({type:"disallow",path:a[1].trim()}):r&&r[1].trim()&&l.push({type:"allow",path:r[1].trim()}),o++}e.push({agents:s,rules:l})}return e}function we(i,t){if(i==="/")return!0;const e=i.endsWith("/")?i.slice(0,-1):i;return e===""?!0:t===e||t.startsWith(e+"/")}function W(i,t){let e=null;for(const o of i)we(o.path,t)&&(!e||o.path.length>e.path.length||o.path.length===e.path.length&&o.type==="allow")&&(e=o);return e?e.type==="allow":!0}function _e(i){if(i.length===0)return{fullyBlocked:!1,partiallyRestricted:!1};const t=W(i,"/"),e=i.some(a=>a.type==="allow"),o=!t&&!e,s=i.some(a=>a.type==="disallow"&&!W(i,a.path));return{fullyBlocked:o,partiallyRestricted:!o&&s}}function F(i,t){const e=be(i),o=t.toLowerCase(),s=e.filter(a=>a.agents.includes(o)),l=s.length?s:e.filter(a=>a.agents.includes("*"));return _e(l.flatMap(a=>
1a.rules))}const Se={"OAI-SearchBot":{code:"geo_search_blocked_chatgpt",partialCode:"geo_search_partial_chatgpt",label:{en:"ChatGPT Search canât surface your site",it:"ChatGPT Search non può mostrare il tuo sito"},why:{en:"OAI-SearchBot is blocked, so your pages wonât be shown in ChatGPT search answers (they can still appear as navigational links). This affects only ChatGPT search and is independent of the GPTBot training opt-out.",it:"OAI-SearchBot è bloccato: le tue pagine non compariranno nelle risposte di ricerca di ChatGPT (possono comunque apparire come link di navigazione). Riguarda solo la ricerca di ChatGPT ed è indipendente dallâopt-out di addestramento GPTBot."},partialLabel:{en:"ChatGPT Search is partially blocked",it:"ChatGPT Search è parzialmente bloccato"},partialWhy:{en:"OAI-SearchBot is disallowed for some paths, so only part of the site can be shown in ChatGPT search answers.",it:"OAI-SearchBot è bloccato per alcuni percorsi: solo una parte del sito può comparire nelle risposte di ricerca di ChatGPT."}},"Claude-SearchBot":{code:"geo_search_blocked_claude",partialCode:"geo_search_partial_claude",label:{en:"Claude Search canât surface your site",it:"Claude Search non può mostrare il tuo sito"},why:{en:"Claude-SearchBot is blocked, so Claude may not index or surface your pages in its search results. This affects only Claudeâs search surface and is independent of the ClaudeBot training opt-out.",it:"Claude-SearchBot è bloccato: Claude potrebbe non indicizzare o mostrare le tue pagine nei suoi risultati di ricerca. Riguarda solo la ricerca di Claude ed è indipendente dallâopt-out di addestramento ClaudeBot."},partialLabel:{en:"Claude Search is partially blocked",it:"Claude Search è parzialmente bloccato"},partialWhy:{en:"Claude-SearchBot is disallowed for some paths, so only part of the site can be indexed for Claude search.",it:"Claude-SearchBot è bloccato per alcuni percorsi: solo una parte del sito può essere indicizzata per la ricerca di Claude."}},PerplexityBot:{code:"geo_search_blocked_perplexity",partialCode:"geo_search_partial_perplexity",label:{en:"Perplexity canât surface your site",it:"Perplexity non può mostrare il tuo sito"},why:{en:"PerplexityBot is blocked, so your pages may not be surfaced or linked in Perplexity search results. PerplexityBot is a search/surfacing crawler â it is not used to crawl content for AI foundation models.",it:"PerplexityBot è bloccato: le tue pagine potrebbero non essere mostrate o collegate nei risultati di ricerca di Perplexity. PerplexityBot è un crawler di ricerca/surfacing â non viene usato per acquisire contenuti per i foundation model."},partialLabel:{en:"Perplexity is partially blocked",it:"Perplexity è parzialmente bloccato"},partialWhy:{en:"PerplexityBot is disallowed for some paths, so only part of the site can be surfaced or linked in Perplexity search results.",it:"PerplexityBot è bloccato per alcuni percorsi: solo una parte del sito può essere mostrata o collegata nei risultati di ricerca di Perplexity."}},Googlebot:{code:"geo_search_blocked_google",partialCode:"geo_search_partial_google",label:{en:"Google Search canât index your site",it:"Google Search non può indicizzare il tuo sito"},why:{en:"Googlebot is blocked, so Google Search (including its AI features) cannot index the site. This is separate from Google-Extended, which only controls AI training/grounding â not Search eligibility.",it:"Googlebot è bloccato: Google Search (incluse le sue funzioni AI) non può indicizzare il sito. à separato da Google-Extended, che controlla solo addestramento/grounding AI â non lâeleggibilità per la Ricerca."},partialLabel:{en:"Google Search is partially blocked",it:"Google Search è parzialmente bloccato"},partialWhy:{en:"Googlebot is disallowed for some paths, so only part of the site can be indexed by Google Search.",it:"Googlebot è bloccato per alcuni percorsi: solo una parte del sito può essere indicizzata da Google Search."}}},D={GPTBot:{en:"GPTBot is disallowed, so your content wonât be used to train OpenAIâs foun
1dation models. This is a training opt-out, not a visibility defect â it is independent of ChatGPT search (controlled by OAI-SearchBot), so it does not by itself prevent the site being cited.",it:"GPTBot è bloccato: i tuoi contenuti non verranno usati per addestrare i foundation model di OpenAI. à un opt-out di addestramento, non un difetto di visibilità â è indipendente dalla ricerca di ChatGPT (controllata da OAI-SearchBot), quindi di per sé non impedisce di essere citati."},ClaudeBot:{en:"ClaudeBot is disallowed, so your content wonât be collected for Anthropic model training. This is a training opt-out, not a visibility defect â it is independent of Claude search (Claude-SearchBot), so it does not by itself prevent the site being cited.",it:"ClaudeBot è bloccato: i tuoi contenuti non verranno raccolti per lâaddestramento dei modelli Anthropic. à un opt-out di addestramento, non un difetto di visibilità â è indipendente dalla ricerca di Claude (Claude-SearchBot), quindi di per sé non impedisce di essere citati."},"Google-Extended":{en:"Google-Extended is disallowed, so your content wonât be used for training future Gemini models or for grounding in Gemini Apps / Vertex AI. This is a training/grounding opt-out, not the control for Google Search or AI Overviews eligibility â that is Googlebot, so this does not by itself prevent the site being indexed or cited.",it:"Google-Extended è bloccato: i tuoi contenuti non verranno usati per addestrare i futuri modelli Gemini né per il grounding in Gemini Apps / Vertex AI. à un opt-out di addestramento/grounding, non il controllo per Google Search o per AI Overviews â quello è Googlebot, quindi di per sé non impedisce di essere indicizzati o citati."}};function Ae(i,t){const e=[],o=[],s=[],l=[],a=[];for(const r of fe){const c=F(i,r),u=Se[r];c.fullyBlocked?(s.push(r),e.push({code:u.code,severity:"critical",count:1,dimension:"geo",label:t?u.label.en:u.label.it,why:t?u.why.en:u.why.it})):c.partiallyRestricted&&(l.push(r),e.push({code:u.partialCode,severity:"warning",count:1,dimension:"geo",label:t?u.partialLabel.en:u.partialLabel.it,why:t?u.partialWhy.en:u.partialWhy.it}))}for(const r of ye)F(i,r).fullyBlocked&&(a.push(r),o.push(t?D[r].en:D[r].it));return{issues:e,trainingOptOutNotes:o,blockedSearch:s,partiallyRestrictedSearch:l,trainingOptOuts:a}}async function ve(i,t){let e="";try{e=await I(`${i}/robots.txt`),(!e||/^\s*<(?:!doctype|html)/i.test(e.slice(0,200)))&&(e="")}catch{}let o=!1;try{const s=await I(`${i}/llms.txt`);o=/\S/.test(s)&&!/^\s*<(?:!doctype|html)/i.test(s.slice(0,200))}catch{}return{findings:Ae(e,t),hasLlmsTxt:o}}async function qe(i){const t=i.siteUrl.replace(/\/$/,""),e=X(Y(i.language)),o=Math.min(i.maxPages??q,q),s=Math.min(i.geoSampleSize??o,o),l=`astroseo:site-audit:${t}:${o}:${new Date().toISOString().slice(0,10)}`;if(typeof sessionStorage<"u")try{const n=sessionStorage.getItem(l);if(n)return JSON.parse(n)}catch{}const{pages:a,sitemapPageCount:r}=await ue(t,o);if(a.length===0)throw new Error("Nessuna pagina trovata (sitemap mancante o sito irraggiungibile).");const c=[];let u=0;const A=async()=>{for(;u<a.length;){const n=a[u++],d=await pe(n);d&&c.push(d)}};if(await Promise.all(Array.from({length:Math.min(5,a.length)},A)),c.length===0)throw new Error("Audit fallito: nessun dato OnPage ricevuto.");const P=c.map(n=>typeof n.onpage_score=="number"?n.onpage_score:0),O=Math.round(P.reduce((n,d)=>n+d,0)/P.length),v=new Map;for(const n of c){const d=n.checks??{},p=n.url;for(const k of Object.keys(M))if(d[k]===!0&&p){const R=v.get(k);R?R.push(p):v.set(k,[p])}}const g=[...v.entries()].map(([n,d])=>{const p=M[n];return{code:p.code,severity:p.severity,dimension:p.dimension,count:d.length,urls:[...d].sort(),label:e?p.label.en:p.label.it,why:e?p.why.en:p.why.it}}).sort((n,d)=>{const p={critical:0,warning:1,opportunity:2};return p[n.severity]-p[d.severity]||d.count-n.count}),L=a.slice(0,s),[m,f]=await Promise.all([Promise.all(L.map(n=>me(n,t))),ve(t,e)]),y=n=>m.filter(n).map(d=>d.url).sort(),b=m.filter(n=>n.schema).length,w=m.filter(n=>n.articleOrFaq).length,_=m.filter(n=>n.author).length,G=m.filter(n=>n.orgSchema).length,C=m.filter(n=>n.extractableStructure).length,x=m.filter(n=>n.questionHeading).length,J=y(n=>!n.schema),$=y(n=>!n.articleOrFaq),j=y(n=>!n.orgSchema),Q=y(n=>!n.author),U=y(n=>!n.extractableStructure&&!n.questionHeading),V=y(n=>n.invalidJsonLd),K=y(n=>n.multipleH1),h=L.length||1,T=Math.round(100*(.45*(b/h)+.3*(w/h)+.25*(_/h)));b/h<.5&&g.push({code:"geo_no_schema",severity:"warning",count:h-b,urls:J,dimension:"geo",label:e?"Structured data (schema) missing":"Dati strutturati (schema) assenti",why:e?"Without JSON-LD, AI struggles to understand and cite the content. Itâs the most underrated GEO signal.":"Senza JSON-LD le AI faticano a capire e citare il contenuto. à il segnale GEO più sottovalutato."}),w/h<.3&&g.push({code:"geo_no_article_faq",severity:"opportunity",count:h-w,urls:$,dimension:"geo",label:e?"Art
1icle/FAQ schema missing":"Schema Article/FAQ mancante",why:e?"Article/FAQPage JSON-LD boosts rich results and citability in AI answers.":"Article/FAQPage JSON-LD aumenta rich results e citabilità nelle risposte AI."}),_/h<.3&&g.push({code:"geo_no_author",severity:"opportunity",count:h-_,urls:Q,dimension:"geo",label:e?"Weak author / E-E-A-T signals":"Segnali di autore/E-E-A-T deboli",why:e?"Author and credentials raise the trust AI and Google assign to the content.":"Autore e credenziali aumentano la fiducia che AI e Google assegnano al contenuto."});const B=m.filter(n=>n.invalidJsonLd).length;B>0&&g.push({code:"invalid_jsonld",urls:V,severity:"warning",count:B,dimension:"geo",label:e?"Corrupt JSON-LD (parse failed)":"JSON-LD corrotto (parse fallito)",why:e?"WordPress wpautop often injects <br/> inside FAQ schema scripts â invisible in view-source but breaks structured data.":"wpautop di WordPress spesso inietta <br/> negli script FAQ â invisibile ma rompe i dati strutturati."});const z=m.filter(n=>n.multipleH1).length;z>0&&g.push({code:"multiple_h1",severity:"warning",count:z,urls:K,dimension:"seo",label:e?"Multiple H1 tags":"Più tag H1",why:e?"A single H1 clarifies page topic for Google and LLMs.":"Un solo H1 chiarisce il tema della pagina per Google e LLM."});const E=m.filter(n=>n.internalLinkIssueCount>0).length;E>0&&g.push({code:"internal_link_issues",severity:"opportunity",count:E,dimension:"seo",label:e?"Internal link issues (sample)":"Problemi link interni (campione)",why:e?"Empty, duplicate, or competitor links in content hurt crawl paths and user trust.":"Link vuoti, duplicati o verso competitor nel contenuto danneggiano crawl e fiducia."}),G===0&&g.push({code:"geo_no_org_schema",urls:j,severity:"opportunity",count:1,dimension:"geo",label:e?"Organization schema missing":"Schema Organization assente",why:e?"An Organization (or LocalBusiness) JSON-LD node with name, logo and sameAs is how AI engines resolve who your brand is and link it to its knowledge-graph entity â the backbone of AI brand recognition.":"Un nodo JSON-LD Organization (o LocalBusiness) con nome, logo e sameAs è ciò che permette alle AI di capire chi è il tuo brand e collegarlo alla sua entità nel knowledge graph â la base del riconoscimento del brand da parte dellâAI."}),C/h<.5&&x/h<.5&&g.push({code:"geo_low_answerability",urls:U,severity:"opportunity",count:h-Math.max(C,x),dimension:"geo",label:e?"Content not structured for AI extraction":"Contenuto poco estraibile dallâAI",why:e?"Answer engines lift lists, tables and question-style headings far more readily than walls of prose. Adding extractable structure (bullet lists, comparison tables, FAQ-style H2/H3) makes each page much easier to quote in an AI answer.":"I motori di risposta estraggono liste, tabelle e titoli in forma di domanda molto più facilmente del testo in blocco. Aggiungere struttura estraibile (elenchi puntati, tabelle di confronto, H2/H3 in stile FAQ) rende ogni pagina molto più citabile in una risposta AI."}),g.unshift(...f.findings.issues),f.hasLlmsTxt||g.push({code:"geo_no_llms_txt",severity:"opportunity",count:1,dimension:"geo",label:e?"llms.txt missing":"llms.txt assente",why:e?"An llms.txt gives AI assistants a curated map of your best content to read and cite â an emerging GEO standard. Rankdelta can generate one for you.":"Un file llms.txt offre agli assistenti AI una mappa curata dei tuoi contenuti migliori da leggere e citare â standard GEO emergente. Rankdelta può generarlo per te."});const Z=Math.round(.7*O+.3*T),H={siteUrl:t,pagesAudited:c.length,analyzedUrls:a.filter(n=>c.some(d=>d.url===n)||m.some(d=>d.url===n&&d.fetched)),...r!=null?{sitemapPageCount:r}:{},healthScore:Z,technicalScore:O,geoReadinessScore:T,issues:g,geoSignals:{pagesWithSchema:b,pagesWithArticleOrFaqSchema:w,pagesWithAuthorSignal:_,pagesWithOrgSchema:G,pagesWithExtractableStructure:C,pagesWithQuestionHeadings:x,sampledForGeo:h,aiCrawlerBlocked:f.findings.blockedSearch,aiSearchPartiallyRestricted:f.findings.partiallyRestrictedSearch,aiTrainingOptOuts:f.findings.trainingOptOuts,aiTrainingOptOutNotes:f.findings.trainingOptOutNotes,hasLlmsTxt:f.hasLlmsTxt},auditedAt:new Date().toISOString()};if(typeof sessionStorage<"u"&&c.length===a.length)try{sessionStorage.setItem(l,JSON.stringify(H))}catch{}return H}async function Ne(i,t){const{error:e}=await S.from("site_audits").upsert({project_id:i,result:t,audited_at:t.auditedAt},{onConflict:"project_id"});if(e)throw e;const o=t,{error:s}=await S.from("site_audit_history").insert({project_id:i,composite:o.compositeHealth??t.healthScore,technical:t.technicalScore,geo_structure:t.geoReadinessScore,geo_content:o.freshnessScore??null,weak_pages:o.weakPageCount??null,pages_audited:t.pagesAudited,audited_at:t.auditedAt});s&&console.warn("[SiteAudit] history snapshot write failed (non-fatal):",s.message)}async function We(i,t=20){const{data:e,error:o}=await S.from("site_audit_history").select("composite, technical, geo_structure, geo_content, audited_at").eq("project_id",i).order("audited_at",{ascending:!0}).limit(t);if(o)throw o;return e??[]}async function Fe(i){const{data:t}=await S.from("site_audits").select("result").eq("project_id",i).order("audited_at",{ascending:!1}).limit(1).maybeSingle();return t?.result??null}export{Ae as aiCrawlerFindings,Fe as getLatestSiteAudit,We as getSiteAuditHistory,he as htmlHasExtractableStructure,ge as htmlHasQuestionHeading,F as robotsAccessForBot,qe as runSiteAudit,Ne as saveSiteAudit};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.