total noob trying to figure out Laravel on-page SEO, help?
The big problem is I'm completely lost on how to properly implement on-page SEO in Laravel. I've heard about meta tags, sitemaps, canonicals, but dont really know where to start or how to make them dynamic for different pages, especially my blog posts.
I've tried a few things already:
- Hardcoding meta tags in my
app.blade.php, but that obviously makes every page have the same description and title, which is bad for SEO, right? - Then I tried to pass dynamic data from my controller to the view for meta tags, like this:
// In my PostController@show method
public function show(Post $post)
{
$seoData = [
'title' => $post->title . ' - My Awesome Blog',
'description' => Str::limit($post->content, 150),
'canonical' => url()->current(),
];
return view('posts.show', compact('post', 'seoData'));
}
// And in posts/show.blade.php, trying to extend the layout
@extends('layouts.app')
@section('title', $seoData['title'])
@section('description', $seoData['description'])
// But when I inspect elements in the browser, sometimes I see the default title/description
// from app.blade.php, or sometimes even a weird duplication of the <title> tag.
// It's like my @section directives aren't always overriding properly, or something is off.
- I also looked into some Laravel SEO packages, but they seemed a bit overwhelming for a beginner, or I ran into conflicts.
- Trying to set up a sitemap manually was also too complex for me.
My main goal is to understand the best practices for on-page SEO in Laravel. How do I dynamically set meta titles, descriptions, canonical URLs, and maybe even basic schema markup for different pages (especially blog posts) without messing things up?
Is there a simple, beginner-friendly strategy or a specific package that just works? Any step-by-step guidance would be super helpful.
Thanks in advance!2 Answers
Tariq Okafor
Answered 1 day agoAh, the classic 'dynamic meta tags in Laravel' dance! Trust me, I've pulled my hair out over this exact issue on more than one Laravel SEO project. It's frustrating when your on-page optimization efforts feel like they're fighting the framework.
The core of your meta tag problem likely lies in how your app.blade.php is structured in relation to your @section directives. Your approach to passing $seoData from the controller is correct. Here's a refined strategy:
-
Refine your
app.blade.php: Ensure your main layout file uses@yielddirectives with sensible default values. This allows child views to override them cleanly without duplication.<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@yield('title', 'My Awesome Blog - Default Title')</title> <meta name="description" content="@yield('description', 'Welcome to My Awesome Blog. Read the latest posts and insights.')"> <link rel="canonical" href="@yield('canonical', url('/'))"> {{-- You can add other meta tags like Open Graph, Twitter Cards here, also using @yield --}} @stack('meta') {{-- Use @stack for extra custom meta tags, like schema markup --}} </head> <body> @yield('content') </body> </html> -
Update your child view (e.g.,
posts/show.blade.php): Now, your@sectiondirectives will correctly override the defaults defined inapp.blade.php.@extends('layouts.app') @section('title', $seoData['title']) @section('description', $seoData['description']) @section('canonical', $seoData['canonical']) {{-- If you have specific schema markup for blog posts, you can push it here --}} @push('meta') <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "headline": "{{ $post->title }}", "image": "{{ $post->featured_image_url ?? asset('images/default-blog.jpg') }}", "author": { "@type": "Person", "name": "{{ $post->author->name }}" }, "datePublished": "{{ $post->published_at->format('Y-m-d') }}" } </script> @endpush @section('content') <!-- Your blog post content here --> </section> - For Sitemaps and Advanced SEO: While manual setup can be complex, for beginner-friendly Laravel SEO, I highly recommend the Spatie Laravel Sitemap package. It's incredibly straightforward to generate dynamic sitemaps based on your models (like blog posts). For basic schema markup, you can implement it directly in your views as shown above, or look into the Spatie Laravel Schema.org package if you need more complex, programmatic schema generation.
This setup ensures that if $seoData isn't provided for a specific page, your site still has a fallback title and description, preventing blank or duplicated tags. It's a robust pattern for dynamic on-page optimization.
Seo-yeon Kim
Answered 1 day agoOh nice! This is exactly what I was looking for, Tariq. Really appreciate you breaking down the `yield` and `section` stuff so clearly, super helpful.