Conceptos básicos de SEO en JavaScript

JavaScript es una parte importante de la plataforma web porque aporta muchas funciones que convierten a la Web en una potente plataforma de aplicaciones. Si permites que la Búsqueda de Google pueda descubrir las aplicaciones web que hayas creado con JavaScript, te resultará más fácil llegar a nuevos usuarios y volver a captar el interés de los usuarios que ya tengas mientras buscan el contenido que proporciona tu aplicación web. Aunque la Búsqueda de Google ejecuta JavaScript siempre con la versión más reciente de Chromium, hay algunos aspectos que puedes optimizar.

En esta guía, se explica cómo procesa la Búsqueda de Google el código JavaScript y se proporcionan prácticas recomendadas sobre cómo optimizar aplicaciones web JavaScript para la Búsqueda de Google.

Cómo procesa el robot de Google el código JavaScript

El robot de Google procesa las aplicaciones web JavaScript en tres fases principales:

  1. Rastreo
  2. Renderizado
  3. Indexación

El robot de Google rastrea, renderiza e indexa las páginas.

El robot de Google coge una URL de la cola de rastreo, la rastrea y luego la envía a la fase de procesamiento. En la fase de procesamiento se extraen enlaces que se envían a la cola de rastreo y se pone la página en la cola para renderizarla. La página va de la cola de renderizado al renderizador, que devuelve el HTML renderizado a la fase de procesamiento. Durante esta fase, la página se indexa y se extraen enlaces para colocarlos en la cola de rastreo.

Cuando el robot de Google obtiene una URL de la cola de rastreo mediante una solicitud HTTP, primero verifica si permites que se rastree. Para ello, lee el archivo robots.txt. Si no lo permites, el robot de Google no envía ninguna solicitud HTTP a la URL y se la salta.

A continuación, el robot de Google analiza la respuesta que recibe y busca otras URL en el atributo href de los enlaces HTML; si hay alguna, la añade a la cola de rastreo. Para que no se busquen enlaces, utiliza el mecanismo nofollow.

El sistema de rastrear URLs y analizar las respuestas HTML es útil para procesar sitios web clásicos o páginas que se renderizan en el servidor, ya que en ambos casos en el HTML de la respuesta HTTP se incluye todo el contenido. No obstante, es posible que en algunos sitios web con JavaScript se use el modelo de esqueleto de aplicación, en el que el HTML que se devuelve en primera instancia no incluye el contenido real, sino que el robot de Google tiene que ejecutar JavaScript para ver el contenido real de la página que el código JavaScript genera.

El robot de Google pone todas las páginas en la cola de renderizado, a menos que en el encabezado o la metaetiqueta robots de una página se indique que no debe indexarse. Las páginas suelen permanecer en esta cola durante unos segundos, aunque a veces podrían estar algo más de tiempo. Una vez que los recursos del robot de Google lo permiten, un Chromium sin interfaz gráfica renderiza la página y ejecuta el JavaScript. Después, el robot de Google vuelve a analizar el HTML renderizado en busca de enlaces y, si hay alguno, lo pone en la cola de rastreo. También indexa la página con el documento HTML renderizado.

Ten en cuenta que sigue siendo una buena opción renderizar el contenido previamente o en el servidor, ya que así tu sitio web funcionará más rápido para los usuarios y los rastreadores; además, no todos los robots pueden ejecutar JavaScript.

Describir las páginas con títulos y fragmentos únicos

Los títulos únicos y descriptivos, así como las metadescripciones útiles, ayudan a los usuarios a identificar rápidamente cuál es el mejor resultado para cumplir su objetivo. Consulta las directrices sobre cómo crear títulos y descripciones interesantes.

Puedes crear y cambiar metadescripciones y títulos con JavaScript.

Escribir código compatible

Como los navegadores ofrecen muchas API y JavaScript es un lenguaje que evoluciona rápidamente, el robot de Google tiene ciertas limitaciones en cuanto a las API y las funciones de JavaScript que admite. Para asegurarte de que tu código sea compatible con el robot de Google, sigue las directrices de solución de problemas de JavaScript.

Usar códigos de estado HTTP con significado

El robot de Google detecta si se ha producido algún error al rastrear una página mediante los códigos de estado HTTP.

Por tanto, te recomendamos que indiques al robot de Google si debe rastrear o indexar una página mediante códigos de estado que tengan un significado, como el código 404 si una página no puede encontrarse o el código 401 si hay que iniciar sesión para acceder a la página. Con los códigos de estado HTTP, también puedes avisar al robot de Google de que una página se ha trasladado a otra URL para que el índice pueda actualizarse correctamente.

A continuación, se muestra una lista de códigos de estado HTTP y se indica cuándo deben usarse:

Estado HTTP Cuándo debe utilizarse
301/302 Se ha trasladado la página a otra URL.
401/403 La página no está disponible debido a problemas con permisos.
404/410 La página ya no está disponible.
5xx Se ha producido un error en el servidor.

Evitar errores soft 404 en aplicaciones de página única

Por lo general, en las aplicaciones de página única que deben renderizar los clientes, el enrutamiento se implementa de modo que también lo realicen los clientes. En estos casos, es poco práctico (y a veces imposible) devolver códigos de estado HTTP con significado. Para que no se devuelvan errores soft 404 al utilizar el renderizado y el enrutamiento de cliente, sigue una de estas estrategias:

  • Usa redirecciones JavaScript que lleven a una URL en la que el servidor pueda devolver un código de estado HTTP 404 (por ejemplo, /not-found).
  • Añade la etiqueta <meta name="robots" content="noindex"> a las páginas de error mediante JavaScript.

A continuación puedes ver un fragmento de código que muestra cómo se implementaría una redirección:

fetch(`/api/products/${productId}`)
.then(response => response.json())
.then(product => {
  if(product.exists) {
    showProductDetails(product); // shows the product information on the page
  } else {
    // this product does not exist, so this is an error page.
    window.location.href = '/not-found'; // redirect to 404 page on the server.
  }
})

A continuación puedes ver un fragmento de código que muestra cómo se implementaría la etiqueta noindex:

fetch(`/api/products/${productId}`)
.then(response => response.json())
.then(product => {
  if(product.exists) {
    showProductDetails(product); // shows the product information on the page
  } else {
    // this product does not exist, so this is an error page.
    // Note: This example assumes there is no other meta robots tag present in the HTML.
    const metaRobots = document.createElement('meta');
    metaRobots.name = 'robots';
    metaRobots.content = 'noindex';
    document.head.appendChild(metaRobots);
  }
})

Utilizar la API History en vez de fragmentos

Cuando el robot de Google busca enlaces en tus páginas, solo tiene en cuenta las URL incluidas en el atributo href de los enlaces HTML.

En las aplicaciones de página única en las que se utiliza enrutamiento de cliente, implementa el enrutamiento entre las diferentes vistas de tu aplicación web mediante la API History. Para asegurarte de que el robot de Google pueda encontrar enlaces, no cargues distintas partes del contenido de la página mediante fragmentos. A continuación se muestra un ejemplo de lo que no debería hacerse, ya que, en esta implementación, el robot de Google no podrá rastrear los enlaces:

<nav>
  <ul>
    <li><a href="#/products">Our products</a></li>
    <li><a href="#/services">Our services</a></li>
  </ul>
</nav>

<h1>Welcome to example.com!</h1>
<div id="placeholder">
  <p>Learn more about <a href="#/products">our products</a> and <a href="#/services">our services</p>
</div>
<script>
window.addEventListener('hashchange', function goToPage() {
  // this function loads different content based on the current URL fragment
  const pageToLoad = window.location.hash.slice(1); // URL fragment
  document.getElementById('placeholder').innerHTML = load(pageToLoad);
});
</script>

En lugar de utilizar el código de arriba, implementa la API History para asegurarte de que el robot de Google pueda acceder a las URL de los enlaces:

<nav>
  <ul>
    <li><a href="/products">Our products</a></li>
    <li><a href="/services">Our services</a></li>
  </ul>
</nav>

<h1>Welcome to example.com!</h1>
<div id="placeholder">
  <p>Learn more about <a href="/products">our products</a> and <a href="/services">our services</p>
</div>
<script>
function goToPage(event) {
  event.preventDefault(); // stop the browser from navigating to the destination URL.
  const hrefUrl = event.target.getAttribute('href');
  const pageToLoad = hrefUrl.slice(1); // remove the leading slash
  document.getElementById('placeholder').innerHTML = load(pageToLoad);
  window.history.pushState({}, window.title, hrefUrl) // Update URL as well as browser history.
}

// Enable client-side routing for all links on the page
document.querySelectorAll('a').forEach(link => link.addEventListener('click', goToPage));

</script>

Usar metaetiquetas robots cuidadosamente

Puedes impedir que el robot de Google indexe una página o siga enlaces mediante la metaetiqueta robots. Por ejemplo, si añades la metaetiqueta que se indica a continuación en la parte superior de tu página, el robot de Google no podrá indexarla:

<!-- Googlebot won't index this page or follow links on this page -->
<meta name="robots" content="noindex, nofollow">

Con JavaScript, puedes añadir metaetiquetas robots a páginas, así como cambiar su contenido. En el fragmento de código de ejemplo que aparece a continuación, se muestra cómo cambiar la metaetiqueta robots con JavaScript para impedir que la página se indexe si no se devuelve contenido en una llamada a la API.

fetch('/api/products/' + productId)
  .then(function (response) { return response.json(); })
  .then(function (apiResponse) {
    if (apiResponse.isError) {
      // get the robots meta tag
      var metaRobots = document.querySelector('meta[name="robots"]');
      // if there was no robots meta tag, add one
      if (!metaRobots) {
        metaRobots = document.createElement('meta');
        metaRobots.setAttribute('name', 'robots');
        document.head.appendChild(metaRobots);
      }
      // tell Googlebot to exclude this page from the index
      metaRobots.setAttribute('content', 'noindex');
      // display an error message to the user
      errorMsg.textContent = 'This product is no longer available';
      return;
    }
    // display product information
    // ...
  });
    

Si el robot de Google detecta noindex en la metaetiqueta robots de una página antes de ejecutar el código JavaScript, no la renderizará ni la indexará.

Utilizar almacenamiento en caché de larga duración

Para reducir las solicitudes de red que se hacen y disminuir el uso de recursos, el robot de Google almacena mucho contenido en caché. A veces, el servicio de renderizado web (WRS) ignora los encabezados de almacenamiento en caché, por lo que quizá acabe usando recursos CSS o JavaScript obsoletos. Para resolver este problema, crea una huella digital del contenido e inclúyela en el nombre del archivo (por ejemplo, main.2bb85551.js). Como las huellas digitales dependen del contenido, cada vez que modifiques un archivo, su nombre cambiará. Puedes consultar más información al respecto en la guía de web.dev sobre estrategias de almacenamiento en caché de larga duración.

Utilizar datos estructurados

Si utilizas datos estructurados en tus páginas, puedes usar JavaScript para generar el archivo JSON-LD necesario e insertarlo en la página. Prueba tu implementación para evitar problemas.

Seguir las prácticas recomendadas sobre componentes web

El robot de Google admite componentes web. Cuando renderiza una página, unifica el contenido de shadow DOM y de light DOM, por lo que solo puede ver el contenido que es visible en el HTML renderizado. Para asegurarte de que el robot de Google siga viendo tu contenido después de renderizarlo, utiliza la prueba de optimización para móviles o la herramienta de inspección de URLs y comprueba el HTML renderizado.

Si el contenido no es visible en el HTML renderizado, el robot de Google no podrá indexarlo.

A continuación se muestra un ejemplo en el que se crea un componente web que muestra su contenido light DOM dentro del shadow DOM correspondiente. Una forma de asegurarse de que tanto el light DOM como el shadow DOM se muestren en el HTML renderizado es utilizar un elemento Slot.

<script>
  class MyComponent extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({ mode: 'open' });
    }

    connectedCallback() {
      let p = document.createElement('p');
      p.innerHTML = 'Hello World, this is shadow DOM content. Here comes the light DOM: <slot></slot>';
      this.shadowRoot.appendChild(p);
    }
  }

  window.customElements.define('my-component', MyComponent);
</script>

<my-component>
  <p>This is light DOM content. It's projected into the shadow DOM.</p>
  <p>WRS renders this content as well as the shadow DOM content.</p>
</my-component>
            

Después de renderizarlo, el robot de Google indexará este contenido:

<my-component>
  Hello World, this is shadow DOM content. Here comes the light DOM:
  <p>This is light DOM content. It's projected into the shadow DOM<p>
  <p>WRS renders this content as well as the shadow DOM content.</p>
</my-component>
    

Solucionar problemas con imágenes y contenido de carga en diferido

Las imágenes pueden consumir mucho ancho de banda y afectar al rendimiento, por lo que es una buena estrategia cargarlas solo cuando los usuarios estén a punto de verlas, un método que se denomina "carga en diferido". Sigue nuestras directrices de carga en diferido para asegurarte de que implementas este método correctamente.