Si te preguntas si tus contenidos responden a la intención del usuario, aquí tienes una forma de saberlo usando IA.
La mayoría de auditoría SEO siguen centradas en señales técnicas: titles, H1, enlazado interno, indexación o densidad de palabras clave. Son métricas necesarias, pero dejan fuera una cuestión decisiva: si el contenido realmente responde a la pregunta que ha llevado al usuario hasta esa página.

 

Análisis de la intención de búsqueda en contenidos

 

Un artículo puede estar perfectamente optimizado para ser rastreado y, aun así, no resolver la intención informacional que motivó la búsqueda. El sistema que hemos desarrollado convierte Screaming Frog en un analizador editorial de contenido a escala. A partir del contenido principal de cada URL, identifica la pregunta que el artículo intenta responder, detecta si existe una respuesta directa, analiza la profundidad de esa respuesta y comprueba si el contenido cumple lo que promete el título o el H1. Además, el análisis introduce una segunda capa crítica: la verificación factual.

 

No solo evalúa si la página responde a la pregunta del usuario, sino también si la respuesta parece correcta según el conocimiento disponible. Esto permite detectar contenidos que aparentemente resuelven una consulta, pero lo hacen con información incompleta, incorrecta o potencialmente engañosa.

 

El resultado es una auditoría que deja de centrarse únicamente en la estructura técnica y pasa a evaluar el valor informativo real de cada URL. En un entorno donde los sistemas de búsqueda utilizan cada vez más modelos de lenguaje de IA para interpretar contenido, medir si una página responde correctamente a una pregunta deja de ser una revisión editorial y se convierte en un criterio operativo de posicionamiento.

{status=ok}

Esta variable indica que el proceso de análisis se ha ejecutado correctamente, sin errores técnicos en la extracción del contenido ni en la respuesta del modelo. No evalúa la calidad del artículo ni determina si la intención está resuelta. Solo confirma que el sistema ha podido generar el resultado.

Resultado status ok en Screaming Frog
Ejemplo de ejecución correcta del análisis en Screaming Frog.

 

Qué significa exactamente

  • El script se ejecutó correctamente.
  • El contenido principal pudo extraerse.
  • El modelo devolvió una respuesta válida.
  • Las variables del análisis se generaron sin errores.

 

Qué no significa

No indica que el contenido sea bueno, ni que la intención de búsqueda esté resuelta, ni que la información sea correcta. Un resultado como {status=ok, intent_ok=NO, final_ok=NO} significa que el sistema ha funcionado bien, pero que el contenido analizado presenta problemas editoriales o factuales.

 

Variables que analiza el sistema

Cada análisis genera un conjunto de variables estructuradas que se insertan en el HTML de la página. Después, Screaming Frog puede extraerlas con XPath y convertir cada URL en una fila evaluable dentro del rastreo. Esto permite analizar cientos o miles de páginas con una lógica editorial homogénea.

Extracción personalizada de variables en Screaming Frog
Configuración de extracción personalizada en Screaming Frog para recuperar las variables generadas por el análisis.

 

intent_question

Define la pregunta informacional principal que el modelo deduce que el artículo intenta responder.

¿Es obligatorio hacer un contrato de arras?

 

intent_answer

Indica si el artículo responde de forma directa a esa pregunta.

SI
NO

 

intent_depth

Mide el nivel de desarrollo de la respuesta dentro del contenido principal.

SUPERFICIAL
SUFICIENTE
PROFUNDO

 

intent_align

Evalúa si el contenido cumple realmente lo que promete el título o el H1.

Título: Cómo firmar un documento en el móvil
Contenido: habla de certificados digitales
Resultado: NO

 

intent_ok

Determina si la intención informacional del usuario queda resuelta con el contenido del artículo.

SI
NO

 

fact_status

Valora si la respuesta principal parece correcta según el conocimiento del modelo.

CORRECTO
INCORRECTO
DUDOSO
NO_VERIFICABLE

 

fact_reason

Explica por qué la información puede ser incorrecta, dudosa o no verificable.

El contrato de arras no es obligatorio en la compraventa según el artículo 1454 del Código Civil.

 

final_ok

Resume el veredicto final combinando resolución de intención y validación factual.

SI
NO

 

fail_reason

Describe el motivo principal del fallo cuando el contenido no cumple los criterios definidos.

La respuesta central del artículo es incorrecta según el marco legal.

Extracción de datos con XPath

Una vez insertadas las variables en el HTML, Screaming Frog puede recuperarlas mediante extracción personalizada. Así, cada URL rastreada incorpora una capa adicional de diagnóstico editorial y factual.

Ejemplo de expresiones XPath para extraer las variables del análisis.
intent_question
//*[@id='sf-intent-audit']/@data-user_question

intent_answer
//*[@id='sf-intent-audit']/@data-direct_answer_present

intent_depth
//*[@id='sf-intent-audit']/@data-answer_depth

intent_align
//*[@id='sf-intent-audit']/@data-title_content_alignment

intent_ok
//*[@id='sf-intent-audit']/@data-intent_resolved

fact_status
//*[@id='sf-intent-audit']/@data-fact_check_status

fact_reason
//*[@id='sf-intent-audit']/@data-fact_check_reason

final_ok
//*[@id='sf-intent-audit']/@data-final_assessment

fail_reason
//*[@id='sf-intent-audit']/@data-why_no

De este modo, la auditoría deja de apoyarse solo en señales HTML tradicionales y pasa a incorporar variables que permiten valorar si una URL aporta una respuesta útil, alineada y fiable.

 

Qué permite detectar este sistema

Este enfoque permite pasar de una auditoría basada en código y estructura a una auditoría basada en valor informativo. Con las variables extraídas puedes localizar con rapidez los principales tipos de fallo editorial.

 

URLs que no responden a la intención

intent_ok = NO

 

URLs que responden pero con poca profundidad

intent_depth = SUPERFICIAL

 

URLs con posibles errores de información

fact_status = INCORRECTO

 

Contenido que falla globalmente

final_ok = NO

Estas páginas pasan a ser prioridad editorial porque no solo presentan una debilidad de contenido, sino una brecha clara entre lo que la búsqueda exige y lo que la URL está entregando.

 

Cómo funciona el JavaScript dentro de Screaming Frog

Este script se ejecuta sobre cada URL rastreada y sigue una secuencia concreta: extrae los elementos principales de la página, construye una instrucción para el modelo, interpreta la respuesta y guarda el resultado dentro del HTML para poder recuperarlo después con XPath.

 

1. Configuración inicial

El script define dos constantes al inicio: la clave de la API y el modelo que se va a utilizar. Esta parte permite establecer la conexión con OpenAI y decidir qué modelo realizará el análisis de cada URL.

const OPENAI_API_KEY = "ESCRIBE TU API";
const MODEL = "gpt-5";

2. Limpieza del texto

La función clean() normaliza el texto antes de usarlo. Sustituye espacios especiales, elimina secuencias de espacios repetidos y devuelve una cadena más estable para enviar a la API.

function clean(text){
  if(!text) return "";
  return text.replace(/\u00A0/g," ").replace(/\s+/g," ").trim();
}

3. Extracción del title y del H1

Las funciones getTitle() y getH1() obtienen dos señales básicas de la página: el título del documento y el encabezado principal. Estas referencias ayudan al modelo a interpretar qué promete la URL antes de analizar el cuerpo del contenido.

function getTitle(){
  return clean(document.title || "");
}

function getH1(){
  const h1 = document.querySelector("h1");
  return h1 ? clean(h1.innerText || h1.textContent || "") : "";
}

4. Detección del contenido principal

La función getMainContent() intenta localizar el bloque principal del artículo. Para ello revisa varios selectores habituales en plantillas de blog, filtra los que existen y ordena los candidatos por longitud. Después toma el más extenso, que normalmente coincide con el contenido central de la URL.

function getMainContent(){

  const candidates = [
    document.querySelector("main article"),
    document.querySelector("article"),
    document.querySelector("main"),
    document.querySelector('[role="main"]'),
    document.querySelector(".post"),
    document.querySelector(".post-content"),
    document.querySelector(".entry-content"),
    document.querySelector(".article-content"),
    document.querySelector("#content"),
    document.querySelector(".content")
  ].filter(Boolean);

  if(!candidates.length) return "";

  candidates.sort(function(a,b){
    return (b.innerText || b.textContent || "").length -
           (a.innerText || a.textContent || "").length;
  });

  return clean(candidates[0].innerText || candidates[0].textContent || "");
}

5. Construcción del prompt

La función buildPrompt() monta la instrucción completa que recibirá el modelo. En ella se insertan el title, el H1 y el contenido principal, y se define con precisión qué tipo de salida debe devolver: un JSON con campos concretos y valores controlados.

function buildPrompt(title,h1,content){

return `
ROLE
You evaluate informational blog posts.

OBJECTIVE
Evaluate whether the article resolves the informational intent and whether the core answer appears factually correct.

INPUT
TITLE: ${title}
H1: ${h1}
MAIN_CONTENT: ${content}

TASK
1 Infer the main informational user question
2 Check if the article answers it
3 Check depth of explanation
4 Check alignment with TITLE and H1
5 Evaluate factual correctness using your knowledge

OUTPUT JSON ONLY

{
"user_question":"",
"direct_answer_present":"SI or NO",
"answer_depth":"SUFICIENTE or SUPERFICIAL",
"title_content_alignment":"SI or NO",
"intent_resolved":"SI or NO",
"fact_check_status":"CORRECTO or DUDOSO or INCORRECTO or NO_VERIFICABLE",
"fact_check_reason":"",
"final_assessment":"SI or NO",
"why_no":""
}
`;
}

6. Lectura segura de la respuesta

La función extractJSON() intenta convertir la salida del modelo en un objeto JSON. Primero prueba el parseo directo y, si falla, busca un bloque con forma de objeto dentro del texto para intentar recuperarlo igualmente.

function extractJSON(text){

  try{
    return JSON.parse(text);
  }catch(e){

    const match = text.match(/\{[\s\S]*\}/);

    if(match){
      return JSON.parse(match[0]);
    }

    return {};
  }
}

7. Petición a la API

La función callAI() envía el prompt al endpoint de OpenAI, espera la respuesta y devuelve el contenido generado por el modelo. Si la estructura recibida no es la esperada, lanza un error con el detalle exacto devuelto por la API.

async function callAI(prompt){

  const response = await fetch("https://api.openai.com/v1/chat/completions",{
    method:"POST",
    headers:{
      "Content-Type":"application/json",
      "Authorization":"Bearer "+OPENAI_API_KEY
    },
    body:JSON.stringify({
      model:MODEL,
      messages:[
        {role:"user",content:prompt}
      ]
    })
  });

  const data = await response.json();

  if(!data.choices || !data.choices[0] || !data.choices[0].message){
    throw new Error(JSON.stringify(data));
  }

  return data.choices[0].message.content;
}

8. Control de contenido insuficiente

Antes de enviar nada a la API, el script comprueba si la URL tiene contenido suficiente. Si no existe contenido o si el texto principal tiene menos de 300 caracteres, se genera igualmente el nodo final, pero se marca la URL como insuficiente para evitar un análisis sin base.

if(!content || content.length < 300){

  const node = document.createElement("div");
  node.id = "sf-intent-audit";

  node.setAttribute("data-user_question","");
  node.setAttribute("data-direct_answer_present","NO");
  node.setAttribute("data-answer_depth","SUPERFICIAL");
  node.setAttribute("data-title_content_alignment","NO");
  node.setAttribute("data-intent_resolved","NO");
  node.setAttribute("data-fact_check_status","NO_VERIFICABLE");
  node.setAttribute("data-fact_check_reason","");
  node.setAttribute("data-final_assessment","NO");
  node.setAttribute("data-why_no","Contenido insuficiente");

  document.body.appendChild(node);

  return seoSpider.data({status:"content_insufficient"});
}

9. Inserción de resultados en el DOM

Cuando el análisis termina correctamente, el script crea un nodo con id sf-intent-audit y añade todos los resultados como atributos data-*. Esta es la parte que hace posible la extracción posterior con XPath en Screaming Frog.

const node = document.createElement("div");
node.id = "sf-intent-audit";

node.setAttribute("data-user_question",parsed.user_question || "");
node.setAttribute("data-direct_answer_present",parsed.direct_answer_present || "");
node.setAttribute("data-answer_depth",parsed.answer_depth || "");
node.setAttribute("data-title_content_alignment",parsed.title_content_alignment || "");
node.setAttribute("data-intent_resolved",parsed.intent_resolved || "");
node.setAttribute("data-fact_check_status",parsed.fact_check_status || "");
node.setAttribute("data-fact_check_reason",parsed.fact_check_reason || "");
node.setAttribute("data-final_assessment",parsed.final_assessment || "");
node.setAttribute("data-why_no",parsed.why_no || "");

document.body.appendChild(node);

return seoSpider.data({status:"ok"});

10. Gestión de errores

Si algo falla durante el proceso, el script crea igualmente el nodo final, pero en este caso guarda el mensaje de error en un atributo específico. Así puedes detectar problemas técnicos sin perder trazabilidad dentro del rastreo.

}catch(e){

  const node = document.createElement("div");
  node.id = "sf-intent-audit";

  node.setAttribute("data-error",e.message || "unknown");

  document.body.appendChild(node);

  return seoSpider.data({error:true});

}

Qué resuelve este enfoque a nivel técnico

La utilidad principal de este script no está solo en llamar a un modelo, sino en dejar el resultado integrado en el HTML de cada página analizada. Eso permite separar claramente dos fases del proceso: primero generar el diagnóstico dentro del DOM y después extraerlo con XPath desde Screaming Frog como cualquier otro atributo estructurado.

 

JavaScript para copiar en Screaming Frog

return (async function () {

const OPENAI_API_KEY = "ESCRIBE TU API";
const MODEL = "gpt-5";

function clean(text){
  if(!text) return "";
  return text.replace(/\u00A0/g," ").replace(/\s+/g," ").trim();
}

function getTitle(){
  return clean(document.title || "");
}

function getH1(){
  const h1 = document.querySelector("h1");
  return h1 ? clean(h1.innerText || h1.textContent || "") : "";
}

function getMainContent(){

  const candidates = [
    document.querySelector("main article"),
    document.querySelector("article"),
    document.querySelector("main"),
    document.querySelector('[role="main"]'),
    document.querySelector(".post"),
    document.querySelector(".post-content"),
    document.querySelector(".entry-content"),
    document.querySelector(".article-content"),
    document.querySelector("#content"),
    document.querySelector(".content")
  ].filter(Boolean);

  if(!candidates.length) return "";

  candidates.sort(function(a,b){
    return (b.innerText || b.textContent || "").length -
           (a.innerText || a.textContent || "").length;
  });

  return clean(candidates[0].innerText || candidates[0].textContent || "");
}

function buildPrompt(title,h1,content){

return `
ROLE
You evaluate informational blog posts.

OBJECTIVE
Evaluate whether the article resolves the informational intent and whether the core answer appears factually correct.

INPUT
TITLE: ${title}
H1: ${h1}
MAIN_CONTENT: ${content}

TASK
1 Infer the main informational user question
2 Check if the article answers it
3 Check depth of explanation
4 Check alignment with TITLE and H1
5 Evaluate factual correctness using your knowledge

OUTPUT JSON ONLY

{
"user_question":"",
"direct_answer_present":"SI or NO",
"answer_depth":"SUFICIENTE or SUPERFICIAL",
"title_content_alignment":"SI or NO",
"intent_resolved":"SI or NO",
"fact_check_status":"CORRECTO or DUDOSO or INCORRECTO or NO_VERIFICABLE",
"fact_check_reason":"",
"final_assessment":"SI or NO",
"why_no":""
}
`;
}

function extractJSON(text){

  try{
    return JSON.parse(text);
  }catch(e){

    const match = text.match(/\{[\s\S]*\}/);

    if(match){
      return JSON.parse(match[0]);
    }

    return {};
  }
}

async function callAI(prompt){

  const response = await fetch("https://api.openai.com/v1/chat/completions",{
    method:"POST",
    headers:{
      "Content-Type":"application/json",
      "Authorization":"Bearer "+OPENAI_API_KEY
    },
    body:JSON.stringify({
      model:MODEL,
      messages:[
        {role:"user",content:prompt}
      ]
    })
  });

  const data = await response.json();

  if(!data.choices || !data.choices[0] || !data.choices[0].message){
    throw new Error(JSON.stringify(data));
  }

  return data.choices[0].message.content;
}

try{

  const title = getTitle();
  const h1 = getH1();
  const content = getMainContent();

  if(!content || content.length < 300){

    const node = document.createElement("div");
    node.id = "sf-intent-audit";

    node.setAttribute("data-user_question","");
    node.setAttribute("data-direct_answer_present","NO");
    node.setAttribute("data-answer_depth","SUPERFICIAL");
    node.setAttribute("data-title_content_alignment","NO");
    node.setAttribute("data-intent_resolved","NO");
    node.setAttribute("data-fact_check_status","NO_VERIFICABLE");
    node.setAttribute("data-fact_check_reason","");
    node.setAttribute("data-final_assessment","NO");
    node.setAttribute("data-why_no","Contenido insuficiente");

    document.body.appendChild(node);

    return seoSpider.data({status:"content_insufficient"});
  }

  const prompt = buildPrompt(title,h1,content);

  const raw = await callAI(prompt);
  const parsed = extractJSON(raw);

  const node = document.createElement("div");
  node.id = "sf-intent-audit";

  node.setAttribute("data-user_question",parsed.user_question || "");
  node.setAttribute("data-direct_answer_present",parsed.direct_answer_present || "");
  node.setAttribute("data-answer_depth",parsed.answer_depth || "");
  node.setAttribute("data-title_content_alignment",parsed.title_content_alignment || "");
  node.setAttribute("data-intent_resolved",parsed.intent_resolved || "");
  node.setAttribute("data-fact_check_status",parsed.fact_check_status || "");
  node.setAttribute("data-fact_check_reason",parsed.fact_check_reason || "");
  node.setAttribute("data-final_assessment",parsed.final_assessment || "");
  node.setAttribute("data-why_no",parsed.why_no || "");

  document.body.appendChild(node);

  return seoSpider.data({status:"ok"});

}catch(e){

  const node = document.createElement("div");
  node.id = "sf-intent-audit";

  node.setAttribute("data-error",e.message || "unknown");

  document.body.appendChild(node);

  return seoSpider.data({error:true});

}

})();

Ejemplo real de análisis sobre los contenidos de esta web

Para comprobar el funcionamiento del sistema se ejecutó el script sobre varias URLs del blog de Agencia de SEO. Cada página fue analizada automáticamente para identificar la pregunta que intenta responder, evaluar si el contenido resuelve esa intención y comprobar si la información parece factualmente correcta.

El resultado es un diagnóstico estructurado por URL que permite detectar rápidamente problemas editoriales o conceptuales dentro del contenido.

Resultado resumido del análisis automático de varias URLs
URLIntent OKFact StatusFinal OKDiagnóstico
/la-publicidad-desleal-y-sus-ejemplos/NODUDOSONODefinición correcta pero ejemplos confusos y referencias legales incompletas.
/como-usar-nano-banana/NODUDOSONOLa herramienta descrita no coincide con productos reales de Google.
/clics-posicion-media-impresiones-ctr/NOINCORRECTONOErrores conceptuales sobre posición media y relaciones matemáticas entre métricas.
/content-age/SIDUDOSOSIExplicación coherente aunque algunas cifras no tienen fuente verificable.
/lsi/SICORRECTOSIExplicación consistente con la evolución conocida de los sistemas de búsqueda.

Ejemplo real de análisis sobre los contenidos de esta web

Ejemplo de diagnóstico generado por el sistema

El siguiente resultado corresponde al análisis automático de una URL. El sistema identifica la pregunta que el contenido intenta responder, evalúa si existe una respuesta directa y revisa la consistencia factual de la explicación.

Resultado JSON generado por el análisis
{
"user_question": "¿Qué son los dominios .onion y cómo acceder a ellos?",
"direct_answer_present": "SI",
"answer_depth": "SUPERFICIAL",
"title_content_alignment": "SI",
"intent_resolved": "NO",
"fact_check_status": "INCORRECTO",
"fact_check_reason": "Describe .onion como subdominio y no como TLD especial de Tor.",
"final_assessment": "NO",
"why_no": "Errores conceptuales sobre dominios .onion y funcionamiento de Tor."
}

Este tipo de diagnóstico permite detectar rápidamente páginas que necesitan revisión editorial. En este caso el contenido intenta responder la pregunta, pero contiene errores conceptuales que afectan a la fiabilidad de la información.

 

De la auditoría técnica a la auditoría del conocimiento

Durante años el SEO ha analizado páginas desde una perspectiva principalmente técnica: etiquetas, estructura, enlazado o indexación. Sin embargo, los sistemas de búsqueda actuales con inteligencia artificial evalúan algo mucho más complejo: si el contenido realmente responde a las preguntas de los usuarios.

El sistema descrito en este artículo permite auditar precisamente ese punto. Al integrar análisis de intención, profundidad de respuesta y verificación factual dentro del propio rastreo de Screaming Frog, es posible evaluar cientos o miles de URLs desde una perspectiva editorial que hasta ahora solo era viable de forma manual.

Esto permite detectar con rapidez contenidos superficiales, artículos que no responden a la intención informacional o páginas que contienen errores conceptuales que afectan a la fiabilidad del contenido. En lugar de revisar páginas una a una, el análisis identifica automáticamente dónde están los problemas y qué URLs deben priorizarse en una optimización editorial.

Si quieres aplicar este tipo de análisis sobre tu propio sitio y detectar qué contenidos realmente necesitan una mejora estratégica, puedes contactar con nuestro equipo de agencia GEO. Analizamos tu web, identificamos los puntos críticos y definimos un plan de optimización orientado a mejorar la calidad real del contenido y su capacidad para responder a las búsquedas de tus usuarios.