Cuando llegué por primera vez al mundo del "SEO en Laravel", pensé que la cosa iba más de contenido y menos de código. Error. El SEO técnico puede elevar o hundir un proyecto, especialmente cuando trabajas con frameworks como Laravel, donde el rendimiento, la estructura del HTML y la forma en que cargas los recursos pueden cambiar por completo tu posición en las SERPs. No exagero: pequeños detalles técnicos pueden darte un empujón brutal… o quitarte 40 puntos de PageSpeed de un día para otro.
En mi caso, arranqué con un puntaje de 37 en PageSpeed en algunas publicaciones del blog. Sí, 37. Casi me daba vergüenza. Y ojo: no era porque Laravel fuera lento. El problema era mío: scripts innecesarios, iframes asesinos, imágenes mal optimizadas y un JavaScript que parecía salido de una bodega olvidada.
A lo largo de este artículo te voy a contar todo lo que aprendí optimizando mi sitio, cómo llegué a 100 de rendimiento, qué cosas aún pueden mejorarse y cómo evitar que tu proyecto Laravel termine ahogado por YouTube, Facebook, GTM o cualquier otro script que decides agregar "por si acaso".
El SEO, siglas de Search Engine Optimization (optimización para motores de búsqueda), es el conjunto de técnicas que aplicamos en nuestras páginas web para ayudarlas a posicionarse de forma orgánica —sin pagar— en los primeros resultados de buscadores como Google o Bing. Aspectos como que el contenido incluya palabras clave relevantes, una jerarquía de encabezados correcta (h1, h2, h3…) y una buena organización del HTML son las bases del SEO. Y Laravel, al ser el framework PHP por excelencia, tiene mucho que decir en cómo aplicamos estas prácticas.
Si tienes un blog o una tienda en línea construida con Laravel, contar con las herramientas correctas para generar metadatos es fundamental para que Google y otros motores de búsqueda te indexen correctamente.
No te voy a dar teoría reciclada: aquí solo hay práctica, sudor, pruebas, errores y resultados reales.
Bases del SEO en Laravel: lo esencial que sí impacta
Antes de entrar en los hacks técnicos y trucos de rendimiento avanzados, el SEO en Laravel tiene tres pilares fundamentales que debes dominar: URLs limpias, metaetiquetas bien generadas y una estructura HTML coherente. Sin estos tres pilares sólidos, cualquier optimización adicional será construir sobre arena.
URLs limpias, enrutamiento y estructura semántica
Laravel nos da una base fantástica con su sistema de rutas. Crear URLs limpias, predecibles, cortas y con palabras clave es tan sencillo como:
Esto permite una estructura de URL clara y directa, esencial para la indexación. Pero la clave no es solo crear rutas SEO-friendly, sino mantener también una jerarquía de encabezados correcta en las vistas Blade.
Confieso que, durante un tiempo, tenía un h1, luego un h3… y de repente volvía a un h2. PageSpeed me lo marcaba como error de accesibilidad, y también afecta el SEO directamente. Desde que corregí la jerarquía de encabezados, la semántica de mis páginas mejoró considerablemente.
Metaetiquetas dinámicas con Blade y helpers SEO
Laravel y Blade facilitan algo que muchos CMS complican innecesariamente: las metaetiquetas dinámicas. Si tus títulos, descripciones y etiquetas OpenGraph se generan a partir del contenido real de cada página, Google te recompensa porque entiende mejor la intención detrás de cada URL.
Open Graph, Twitter Cards y canónicas sin romper tu arquitectura
La mayoría de competidores olvidan que los motores sociales también influyen en el SEO indirecto. Tener etiquetas og: bien configuradas aumenta el CTR desde redes sociales, y eso termina impulsando la autoridad de tu dominio. No es magia; es coherencia semántica y una buena práctica que cuesta muy poco implementar en Laravel.
Optimización extrema de rendimiento en Laravel (el verdadero factor SEO)
Aquí es donde Laravel brilla… o donde puedes tirarlo por un barranco si no cuidas lo que cargas. Google es claro: rendimiento = SEO. PageSpeed Insights evalúa JavaScript, CSS, imágenes, estabilidad visual (CLS), accesibilidad y eficiencia del HTML al milímetro.
Cómo analizar qué JavaScript bloquea tu página
Yo siempre empiezo abriendo DevTools → pestaña Network → filtro .js. Cuando hice esto con mi blog por primera vez, me encontré scripts que ni sabía que estaban cargando: GTM, Google Ads, Facebook Pixel… todos ejecutándose antes del contenido principal. Para una web donde estos scripts no son críticos en el primer renderizado, eso es literalmente un crimen contra el rendimiento.
Los retrasé todos usando el atributo defer o cargándolos bajo demanda. Solo ese cambio mejoró notablemente el tiempo de interacción (TTI).
Modularización del JavaScript: de un blog.js gigante a scripts ligeros
Tenía un blog.js enorme donde metí todo lo que necesitaba "en algún momento". Error de novato. Con el tiempo lo dividí en módulos, eliminé dependencias innecesarias y dejé solo las funciones realmente requeridas. Hoy pesa menos de 300 líneas y se ejecuta bajo demanda.
Por ejemplo, eliminé completamente axios; con el nativo fetch() resolví todas mis necesidades de peticiones HTTP. Esta decisión no solo ahorra peso en el bundle, sino que elimina dependencias externas que podrían quedar desactualizadas.
Eliminando lo que sobra: scripts del dashboard, plugins y recursos fantasma
Algo que me señalaba PageSpeed era que se estaban cargando scripts del panel de administración en el frontend público. No tiene sentido, pero pasa más de lo que crees, especialmente con paquetes o configuraciones mal heredadas de versiones anteriores del proyecto.
Los eliminé todos. Resultado: páginas más rápidas y un DOM más limpio para que Google lo procese sin fricción.
Carga diferida de JS y recursos críticos
Mi regla es simple y no tiene excepciones:
CSS crítico: carga inmediata.
JavaScript propio: bajo demanda o con defer.
Scripts de terceros (GTM, Pixel, Ads): lo más tarde posible.
Con eso solo ya ganas puntos importantes en PageSpeed.
El caso YouTube: cómo un solo iframe puede destruir tu SEO
Aquí viene el gran drama. El <iframe> nativo de YouTube es un veneno, así, sin rodeos. Si lo incrustas tal cual te lo da YouTube, añades más de 500 KB de JavaScript innecesario que se ejecuta antes de que el usuario siquiera haga clic en el vídeo.
Para analizarlo, abre las herramientas de desarrollador, ve a la pestaña Network y filtra por .js. Al recargar la página, verás claramente todos los scripts que se cargan. El de YouTube es una parte crítica del problema: trae demasiados recursos consigo, ralentizando la carga completa de la web incluso cuando el usuario nunca reproduce el vídeo.
Cómo pasé de 37 a 100 en PageSpeed: el problema del <iframe>
En este y en los próximos vídeos te voy a explicar cómo pasé de un rendimiento de 37 en mis publicaciones a alcanzar un 100. Lo cual, sinceramente, aún me sorprende, porque todavía tengo cosas que pulir. Aunque la métrica sea perfecta, el sitio no lo es del todo. Pero la mejora es real y replicable, y eso es lo que más importa.
En este primer vídeo me enfoco exclusivamente en el bendito <iframe> de YouTube, que fue el mayor responsable de aquella puntuación vergonzosa de 37.
El dilema del vídeo incrustado en el blog
Si tienes un blog, seguramente ya te habrán dicho que debes combinar contenido en texto y vídeo, especialmente si haces contenido mixto: creas un vídeo y luego escribes el artículo, o viceversa. Lo ideal es que ambos convivan en la misma publicación: el vídeo arriba y el artículo abajo. Así potencias tu contenido al ofrecer dos formatos distintos que se complementan.
Hasta ahí, todo bien. El problema llega cuando decides incrustar el vídeo directamente con el <iframe> estándar de YouTube, que es una verdadera pesadilla para el rendimiento.
Ese era el cáncer que tenía en mi blog, y por eso quiero explicarte exactamente qué pasaba y cómo lo resolví.
Por qué el iframe nativo de YouTube destroza PageSpeed
Cuando analicé mis publicaciones con DevTools, comprobé que el <iframe> cargaba una batería de scripts de YouTube —incluyendo sus APIs de seguimiento y reproducción— incluso si el usuario nunca llegaba a ver el vídeo. Eso mataba mi LCP (Largest Contentful Paint), la métrica que más peso tiene en el ranking de Google actualmente.
El <iframe> de YouTube fue el principal responsable de ese famoso "37" con el que empecé.
Solución: miniatura WebP + reproductor bajo demanda
Lo que hago ahora es súper sencillo y elegante:
Cargo una imagen .webp local y ligera como miniatura del vídeo.
Cuando el usuario hace clic en la miniatura, recién ahí cargo el <iframe> real de YouTube.
El vídeo aparece como si siempre hubiese estado ahí.
Resultado:
Carga ultrarrápida en el primer render.
Cero JavaScript de YouTube bloqueante.
Experiencia de usuario limpia y natural.
Lo más irónico es que YouTube te da por defecto una miniatura en .jpg… pero Google te penaliza si no usas .webp. Excelente coherencia de Google con Google.
Cómo recuperar los datos enriquecidos con JSON-LD (VideoObject) — Datos Estructurados
Si eliminas el <iframe> nativo, Google ya no detecta automáticamente tu vídeo incrustado. La solución: declararlo explícitamente con JSON-LD usando el esquema VideoObject.
Nombre del autor o canal (en mi caso, "Desarrollo Libre")
Logo del canal
URL del vídeo en YouTube
Desde que añadí este bloque de datos estructurados, Google volvió a entender y mostrar mis vídeos en los resultados enriquecidos sin penalizar el rendimiento de la página.
¿Y qué hay de plugins como lite-youtube-embed?
Existe el paquete lite-youtube-embed, que hace algo similar a mi solución pero mediante un web component. El problema es que te casas con su sintaxis específica:
Y eso es justo lo que yo no quería. Prefiero mantener el contenido usando el <iframe> estándar en la fuente de datos, para procesarlo internamente y transformarlo. Así el contenido queda agnóstico a cualquier librería. Pero si tú prefieres ir por la vía del plugin, también es una opción válida y rápida.
Identificación y auditoría de mis archivos JavaScript
En este punto, ya tenemos claro qué scripts no forman parte del núcleo de la web —como el Pixel de Facebook o Google Ads— y también conocemos recursos externos necesarios —como los de YouTube— que sí añaden valor al usuario aunque penalicen el rendimiento si no se gestionan bien.
El siguiente paso es auditar nuestros propios archivos .js. En mi caso, son principalmente dos:
highlight.js
blog.js
Optimización de imágenes, multimedia y DOM
Ambos archivos son de mi autoría y eso ya es una gran ventaja, porque antes tenía todo en un único archivo monolítico: el famoso blog.js. Incluía absolutamente de todo. Siguiendo recomendaciones de rendimiento, decidí dividirlo en módulos más pequeños y especializados.
También estoy eliminando dependencias que ya no necesito. Por ejemplo, he migrado todas las peticiones HTTP de axios a fetch() nativo. Puede que quede algún rastro por ahí, pero poco a poco estoy ordenando todo.
Reemplazo de Axios y otros scripts
Ya eliminé axios por completo del bundle del blog. También consideré quitar Alpine.js, pero pesa tan poco (~8KB minificado) que por ahora lo voy a mantener; la relación coste/beneficio no justifica eliminarlo.
Otro script que estoy evaluando es highlight.js. Este es fundamental para mí, ya que aplica el coloreado de sintaxis al código en los artículos. Básicamente detecta los bloques <pre> y <code>, los tokeniza y les aplica estilos visuales para que el código sea legible y atractivo.
Organización del código y carga condicional
Lo que estoy haciendo es organizar la carga de recursos de forma inteligente. Por ejemplo, con highlight.js he separado las responsabilidades: su CSS va en el layout principal para evitar flashes de contenido sin estilo, y el JS lo cargo solo cuando la página realmente lo necesita, bajo una condición específica. Esa lógica te la explicaré con detalle en un próximo vídeo.
El archivo blog.js ahora solo contiene las funciones mínimas: búsquedas y peticiones locales. Tiene menos de 300 líneas y planeo optimizarlo aún más. Solo conserva lo esencial.
Trucazo para el SEO en Laravel: carga diferida y pre-render del contenido
Te explicaba cómo pasé de un puntaje de 50 a 73 en PageSpeed simplemente cambiando el bendito <iframe> de YouTube por la miniatura WebP bajo demanda. Ese solo cambio ya fue un salto enorme. Ahora voy a continuar la explicación desde ese punto y mostrarte cómo llegué hasta los 100 con el resto de cambios que realicé.
Ejemplo real: el camino de 37 a 100 en PageSpeed
Aprovecho también para comentarte que este material formará parte de un curso que tengo planeado crear más adelante. Actualmente estoy trabajando en mi tienda en línea —a la fecha de grabación—, pero luego vendré con un curso completo sobre cómo crear un blog bien optimizado desde cero, explicando todos estos detalles y mucho más.
Este es el punto donde todo encaja. El camino fue más o menos así:
Eliminé axios
Dividí mi JS en módulos especializados
Eliminé los scripts del dashboard que se colaban en el frontend
Implementé miniaturas .webp para YouTube con carga bajo demanda
Añadí JSON-LD con el esquema VideoObject para recuperar el SEO perdido
Mejoré la accesibilidad (atributos alt, aria-label, etc.)
Reorganicé la jerarquía de encabezados (h1 → h2 → h3)
Integré carga diferida con defer para Alpine.js, highlight.js y otros scripts no críticos
SEO técnico en Laravel: tareas esenciales que Google sí evalúa
Mejorar la accesibilidad: atributos alt, aria-label y derivados
También hice ajustes en las imágenes, asegurándome de incluir el atributo alt con una descripción adecuada en cada una. Y algo muy importante: respetar la jerarquía de encabezados. Si colocas un h1, el siguiente debe ser un h2, luego h3, y así sucesivamente. Saltar de h1 directamente a h3 rompe la lógica semántica del contenido, y PageSpeed —y Google— te lo hacen saber.
Laravel facilita aplicar SEO técnico real si conoces dónde tocar. El framework no te limita; al contrario, te da el control total que necesitas.
Sitemap XML con Spatie
El paquete spatie/laravel-sitemap es práctico, simple y totalmente automático. Genera el sitemap.xml recorriendo tus rutas o modelos, y lo actualiza sin que tengas que intervenir. Imprescindible para proyectos serios.
robots.txt, canónicas e indexabilidad
Laravel no toca esto por defecto, pero crear un robots.txt dinámico es sencillo con una ruta simple. Las URLs canónicas deben generarse automáticamente según la ruta activa para evitar contenido duplicado que Google penalice.
Seguridad y HTTPS
HTTPS es obligatorio hoy en día; Google lo usa como señal de ranking. Laravel facilita todo el manejo de CSRF, headers seguros y buenas prácticas de seguridad de forma nativa.
Accesibilidad y semántica
A partir de aquí, el resto de los cambios se centraron en hacer la carga más eficiente y accesible. Por ejemplo, añadí atributos aria-label a los botones para indicar su función a los lectores de pantalla. Herramientas usadas por personas con discapacidad visual —y también evaluadas por Google— que necesitan saber qué hace cada elemento interactivo:
Los botones no tienen nombres accesibles. A continuación se indican consejos para mejorar la semántica de los controles de tu aplicación. Estos consejos pueden mejorar la experiencia de los usuarios de tecnologías de asistencia, como los lectores de pantalla.
<button aria-label="Cerrar ventana"> <svg><!-- ícono de cerrar --></svg> </button>
Los lectores de pantalla agradecen este tipo de atributos, y Google también los toma en cuenta en sus métricas de accesibilidad.
ralphjsmit/laravel-seo → alternativa moderna con soporte para Filament
Todos estos paquetes ayudan y ahorran tiempo, pero ninguno sustituye la tarea de optimizar tu JavaScript, imágenes y estructura HTML. Son herramientas, no soluciones mágicas.
Optimizar recursos bloqueantes
Además de lo anterior, optimicé la respuesta general del servidor. Aunque el cambio del <iframe> ayudó muchísimo, también empecé a remover todo el JavaScript innecesario. Había recursos cargándose desde el dashboard de administración en el frontend público, sin ningún sentido. Todo eso lo eliminé sin piedad.
Reducción de JavaScript y código más limpio
El JavaScript que se cargaba afectaba bastante el rendimiento. El <iframe> de YouTube por sí solo traía una barbaridad de recursos. Y todos estos pequeños cambios afectan directamente cómo el navegador renderiza la página y cómo Google la evalúa.
A medida que resuelves esos problemas, la carga mejora, el servidor responde más rápido y todo se procesa con más eficiencia. Por eso, con cambios estratégicos y bien priorizados, la web evolucionó muchísimo.
El problema del DOM excesivo
Uno de los aspectos que también me señalaba Google era el tamaño excesivo del DOM. Esto se debe a que en mi contenido tengo dos tipos principales: publicaciones con el vídeo de YouTube y su transcripción, y publicaciones que muestran cursos completos.
Cuando muestro un curso, el documento es largo porque contiene todas las secciones con sus descripciones. Coloco toda esa estructura dentro del HTML para que Google entienda qué hace cada parte. Por eso el DOM es tan extenso.
Esta estructura viene directamente de mi plataforma de cursos, donde cada sección tiene sus clases. Simplemente reutilicé esa estructura en las publicaciones del blog. Así que, aunque sea un DOM largo, el contenido es útil y semánticamente correcto.
Problemas de formato y accesibilidad visual
Hay algunos detalles visuales que también debo mejorar. Por ejemplo, algunos contrastes de color son demasiado fuertes. También tengo pendiente reorganizar el listado de posts para que los más recientes aparezcan primero.
Y algo que siempre me ha parecido curioso: cuando uso las miniaturas de YouTube, estas se sirven como .jpg, no como .webp, que es el formato que Google prefiere. Lo irónico es que si subes una imagen directamente a YouTube y haces clic derecho para descargarla, muchas veces sí obtienes un .webp. Parece que lo hacen a propósito para complicarnos la vida.
Reducción de JavaScript: más a fondo Volviendo a los aspectos clave: reducir JavaScript fue esencial. También cuidar los atributos descriptivos en el HTML. Por ejemplo, las imágenes deben tener su atributo alt, y los botones deben tener su aria-label para indicar qué acción realizan. Esto parece un detalle menor, pero Google lo penaliza directamente en la puntuación de accesibilidad.
Lo que más me importa es que todo el proceso quede lo más natural posible. Si una publicación tiene un vídeo de YouTube, en el CMS simplemente coloco el <iframe> estándar y mi código hace el resto del trabajo de optimización en el backend.
Código fuente y Highlight.js
Este blog está dirigido a programadores, así que obviamente hay bloques de código en muchos artículos. Uso highlight.js para aplicar el coloreado de sintaxis y mostrar el código de forma clara y atractiva.
El problema surge cuando tienes un libro técnico con 300 páginas llenas de código: highlight.js empieza a pesar y en algunos casos deja de funcionar correctamente o se ralentiza mucho, impactando la carga de la página.
Por eso tomé una decisión clave: procesar el coloreado de sintaxis una sola vez en el servidor y guardar el resultado en un campo llamado final_content. Eso significa que highlight.js se ejecuta solo una vez (al guardar el contenido), y el frontend simplemente sirve el HTML ya procesado. Así me ahorro toda la carga del plugin en cada visita.
Alpine.js y scripts mínimos
Otra parte que optimicé fue la estrategia de carga de scripts. Uso Alpine.js para el menú hamburguesa y los botones de compartir. Aunque pesa poco (~8KB minificado), decidí también retrasar su carga con defer para no bloquear el renderizado inicial.
La pregunta clave que me hago siempre es: ¿qué es lo mínimo que necesita cargar mi web para renderizar correctamente? El CSS, sin duda. También el CSS de highlight.js para el coloreado de código. Google penaliza los cambios bruscos de estilo (CLS), por eso ese CSS debe ir cargado desde el inicio, en el <head>, aunque el JS lo cargues después.
Errores comunes que arruinan el SEO en Laravel
Cargar GTM, Ads o Facebook Pixel demasiado temprano, bloqueando el renderizado.
Saltar de un h1 a un h3 sin pasar por el h2.
Incrustar vídeos de YouTube con el <iframe> nativo sin optimizar.
Dejar scripts repetidos o innecesarios que nunca se llegan a usar.
No controlar los atributos alt en imágenes ni aria-label en botones.
Servir imágenes pesadas o en formato .jpg/.png en lugar de .webp.
Laravel SEO: paquetes para generar metaetiquetas
Existen múltiples paquetes para generar etiquetas SEO en Laravel, lo cual es fantástico porque hay partes de la aplicación donde necesitamos inyectar metaetiquetas dinámicas sin preocuparnos de si la sintaxis es correcta: el paquete se encarga de eso por nosotros.
SEOTools
Los metatags son elementos primordiales para dar información a los motores de búsqueda, particularmente a los bots de indexación como Googlebot. Elementos como el <title> (que técnicamente no es un metatag pero funciona como tal), la meta description, la imagen OG, entre otros, son fundamentales para dar la primera impresión de tu sitio y que los motores sepan cómo presentarlo en los resultados.
Hay múltiples tipos de metadatos que podemos emplear. En la práctica son etiquetas HTML que sirven para dar un título, una descripción y una referencia a una imagen principal del post. También podemos personalizar etiquetas para redes sociales como Facebook o Twitter mediante los prefijos og: y twitter:. Las palabras clave (keywords) ya no tienen peso real en Google, pero los tres datos esenciales que sí importan son:
Título
Descripción
Imagen (OG Image)
artesaos/seotools es un paquete que permite generar todas estas etiquetas meta de forma sencilla mediante métodos encadenados. Repositorio oficial:
En Laravel 10 o inferior, abre el archivo config/app.php y agrega el provider. En Laravel 11+, el descubrimiento automático de paquetes suele encargarse de esto:
Esto creará el archivo config/seotools.php, donde puedes definir valores predeterminados para el título, descripción, Open Graph y Twitter Cards de todo el sitio. Desde tu controlador, podrías usarlo así:
SEOTools::setTitle("Latest posts");
SEOTools::opengraph()->addProperty('type', 'articles');
SEOTools::twitter()->setSite('@LibreDesarrollo');
SEOTools::jsonLd()->addImage(URL::to('/public/images/logo/logo.png'));
SEOTools::setDescription("Here you will find the latest posts that I have uploaded to my blog.");
Desde la vista Blade:
{!! SEO::generate() !!}
<!-- MINIFICADO -->{!! SEO::generate(true) !!}
Y el resultado en el HTML sería algo así:
<title>Latest posts</title><metaname="description"content="Here you will find the latest posts that I have uploaded to my blog."><metaproperty="og:title"content="Latest posts"><metaproperty="og:type"content="articles"><metaproperty="og:description"content="Here you will find the latest posts that I have uploaded to my blog."><metaname="twitter:title"content="Latest posts"><metaname="twitter:site"content="@LibreDesarrollo"><metaname="twitter:description"content="Here you will find the latest posts that I have uploaded to my blog."><scripttype="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Últimas publicaciones","description":"Here you will find the latest posts that I have uploaded to my blog."}</script>
Para personalizar el paquete con valores por defecto o un sufijo en el título, publica el archivo de configuración (si no lo hiciste antes):
Un ejemplo más completo con todas las facades disponibles:
SEOMeta::setTitle("Últimas publicaciones");
SEOMeta::setDescription("Aquí encontrarás las últimas publicaciones que he subido a mi blog.");
SEOTools::setDescription("Aquí encontrarás las últimas publicaciones que he subido a mi blog.");
OpenGraph::setDescription("Aquí encontrarás las últimas publicaciones que he subido a mi blog.");
OpenGraph::setTitle("Últimas publicaciones");
OpenGraph::addProperty('type', 'articles');
TwitterCard::setSite('@acy291190');
TwitterCard::setTitle("Últimas publicaciones");
Esas las empleo de forma fija para una sección en particular que muestra las últimas publicaciones. Pero para los posts individuales, los datos vienen del modelo:
Ralph J. Smith Laravel SEO (ralphjsmit/laravel-seo)
Laravel SEO Scanner
Luego, en los ejemplos prácticos, ejecutaremos el scanner en dos demos basadas en los dos primeros paquetes.
1. Artesaos SEO Tools
El primer paquete, artesaos/seotools, funciona así: tienes una página de demo, y si inspeccionas el código fuente de un post, verás etiquetas como meta description, meta twitter, <title>, entre otras, perfectamente generadas.
Para poblar estos datos desde la base de datos, creé un panel de administración con Filament dentro del mismo proyecto. Por ejemplo, puedo llenar title, description y author para un post, guardar los cambios, y en la base de datos se reflejan en la tabla que creé específicamente para SEO.
Al refrescar la página, verás los títulos y metas en el código fuente, incluyendo og:title y og:description. Además, se pueden configurar valores por defecto mediante el archivo de configuración.
Este paquete es antiguo (con commits de hace nueve años), pero todavía es compatible con Laravel 12. La última actualización del 14 de marzo adaptó el paquete para esta versión del framework.
2. Ralph J. Smith Laravel SEO
El segundo paquete es ralphjsmit/laravel-seo. Ralph es muy activo en la comunidad de Filament, y por eso parte de este paquete incluye integraciones nativas para ese panel.
En su documentación principal, indica que en el Blade solo necesitas llamar a seo()->for($post) para renderizar todos los metas. Para que el modelo tenga acceso a los datos SEO, basta con añadirle el trait HasSEO, que automáticamente crea la relación en la base de datos —a diferencia del primer paquete, donde la relación la gestionas tú manualmente.
Puedes cambiar title, description, etc., directamente desde el panel y los cambios se reflejan de inmediato en la página.
Ambos paquetes permiten trabajar con meta tags, títulos y etiquetas SEO en el HTML, que sigue siendo totalmente relevante para el posicionamiento en buscadores.
3. Laravel SEO Scanner
El tercer paquete es Laravel SEO Scanner, que permite escanear las páginas de tu sitio y revisar su configuración SEO según distintos criterios de forma automatizada.
Por ejemplo, tras instalarlo en el primer proyecto demo, puedes ejecutar:
php artisan seo:scan
Y obtienes un informe detallado: 19 checks exitosos y 6 fallidos, indicando exactamente qué elementos faltan, como la imagen de Open Graph, la meta description o las keywords.
Conclusión de los paquetes
De los tres paquetes mencionados, cada uno tiene su propósito específico:
artesaos/seotools y ralphjsmit/laravel-seo permiten configurar y gestionar los metadatos.
Laravel SEO Scanner sirve para auditar y detectar problemas en tus páginas.
La combinación ideal es usar uno de los dos primeros para generar los metas, y el scanner para validar que todo esté correctamente configurado.
Gestión de SEO en Laravel con SEO Suite
En el ecosistema de Laravel existen diversas herramientas dedicadas al SEO, facilitando tareas esenciales como la generación de metaetiquetas, sitemaps y datos estructurados.
Recientemente he evaluado un paquete denominado SEO Suite (nafakhari/seo-suite), el cual ofrece un enfoque integral para abordar estas necesidades en aplicaciones Laravel.
Características principales de SEO Suite
Aunque existen alternativas consolidadas en el ecosistema (como artesaos/seotools), este paquete reúne varias funcionalidades clave en una sola instalación:
Generación de Sitemaps: Construye dinámicamente el sitemap.xml con la estructura de URLs de la aplicación para facilitar la indexación:
Soporte para JSON-LD: Incorpora esquemas de datos estructurados en formato JSON-LD, proporcionando contexto detallado a los motores de búsqueda:
usewebspider\SeoSuite\Domain\Schema\SchemaComposer;
$composer = new SchemaComposer();
$composer->addSchema(['@type' => 'Organization', 'name' => config('app.name')]);
$composer->addSchema(['@type' => 'Article', 'headline' => $post->title]);
$jsonLd = $composer->generateJsonLd(); // safe to drop straight into a <script> tag
Gestión de Metaetiquetas: Configuración centralizada de títulos, descripciones y etiquetas Open Graph:
use webspider\SeoSuite\Core\Contracts\SeoRepositoryInterface;
app(SeoRepositoryInterface::class)->updateForModel($post, [
'meta_title' => 'How to tune Laravel queries',
'meta_description' => 'A practical guide to profiling and fixing slow Eloquent queries.',
'canonical_url' => 'https://example.com/blog/tune-laravel-queries',
]);
Auditoría y Scores de SEO: Herramientas internas de análisis para evaluar el cumplimiento de buenas prácticas directamente desde el código:
La incorporación del paquete al proyecto se realiza mediante Composer:
$ composer require nafakhari/seo-suite
A diferencia de otras librerías donde las etiquetas se gestionan de forma muy segmentada, SEO Suite centraliza gran parte de la configuración, destacando especialmente por su simplicidad en la generación de sitemaps y esquemas estructurados.
Evaluar este tipo de paquetes te permite seleccionar la herramienta que mejor se adapte a los requerimientos de arquitectura y mantenibilidad de cada proyecto en Laravel.
Conclusión: mantener un proyecto Laravel rápido, limpio y bien posicionado
El SEO en Laravel no es solo "agregar palabras clave". Es un proceso técnico continuo que requiere revisar tus scripts, imágenes, estructura HTML e integraciones de terceros de forma periódica. Los cambios pequeños suman, y a veces un solo <iframe> mal implementado puede tumbarlo todo.
La clave está en:
Simplificar el código y eliminar todo lo innecesario.
Cargar solo lo esencial en el primer render.
Ordenar tu HTML semánticamente.
Monitorizar constantemente con PageSpeed Insights y DevTools.
Si lo haces bien, puedes conseguir resultados como el salto que hice yo: de 37 a 100. Y lo más importante: mantener esa calidad a largo plazo.
Preguntas frecuentes sobre SEO en Laravel
¿Cómo mejorar el PageSpeed en Laravel?
En esta guía tienes los pasos detallados: elimina JavaScript bloqueante, reemplaza los <iframe> de YouTube por miniaturas .webp bajo demanda, y añade datos estructurados con JSON-LD.
¿Qué paquetes SEO puedo usar en Laravel?
Los más recomendados son artesaos/seotools, ralphjsmit/laravel-seo, spatie/laravel-sitemap y spatie/schema-org. Más arriba tienes una comparativa detallada de cada uno.
¿Cómo optimizar YouTube en Laravel sin perder SEO?
Sustituye el <iframe> nativo por una miniatura .webp que carga el reproductor al hacer clic, y declara el vídeo con un bloque JSON-LD usando el esquema VideoObject para que Google lo siga detectando.
¿Qué influye más en el SEO: el contenido o el rendimiento?
Ambos son importantes y se complementan. Sin contenido relevante no llegas a la intención de búsqueda; sin rendimiento, Google te penaliza en las métricas Core Web Vitals. La combinación de los dos es lo que lleva a un posicionamiento sólido.
¿Laravel es un buen framework para SEO?
Sí, y mucho. Laravel te da control total sobre la generación de HTML, rutas limpias, metadatos dinámicos y carga de recursos. La clave está en aplicar las optimizaciones técnicas descritas en esta guía.
Aprende a mejorar el rendimiento SEO en Laravel paso a paso: elimina JS bloqueante, reemplaza iframes de YouTube por WebP, genera JSON-LD y usa los mejores paquetes SEO como artesaos/seotools.
Únete a la comunidad de desarrolladores que han decidido dejar de picar código y empezar a construir productos reales. Recibe mis mejores trucos de arquitectura cada semana:
Acepto recibir anuncios de interes sobre este Blog.
Puedes copiar y pegar alguna de las siguientes opciones y compartir en tu red social favorita:
Opción 1
SEO en Laravel: cómo optimizar JavaScript, iframes de YouTube, paquetes y PageSpeed (de 37 a 100)
Aprende a mejorar el rendimiento SEO en Laravel paso a paso: elimina JS bloqueante, reemplaza iframes de YouTube por WebP, genera JSON-LD y usa los mejores paquetes SEO como artesaos/seotools.