The Laravel SEO Checklist: Routes, Metadata, Sitemaps and Schema

A practical SEO checklist for Laravel sites: URLs and redirects, titles and canonicals, JSON-LD, sitemaps with spatie/laravel-sitemap, rendering with Inertia, performance and proxies.

A Laravel site is ready for search and AI crawlers when every public page returns full HTML from the server with the right status code, one canonical URL, a unique title and description, structured data, and a place in an XML sitemap, and when old URLs redirect permanently to new ones. Laravel gives you the tools for all of this, but none of it is automatic. This checklist covers routing, metadata, sitemaps, redirects, rendering, performance and proxies, with the Laravel feature for each.

1. URLs and routing

  • Generate slugs with Str::slug and store them, so URLs do not change when titles are edited.
  • Choose one trailing-slash style and redirect the other version, usually in the web server or middleware.
  • Use route model binding by slug for public pages, and return 404 with abort(404) when a record is missing or unpublished, never a 200 page saying “not found”.
  • Keep query parameters for filters out of indexable URLs, or canonicalise them.

2. Redirects

// routes/web.php: simple permanent redirects
Route::permanentRedirect('/old-services', '/services');

// When a slug changes, store the old slug and redirect in the controller
public function show(string $slug)
{
    $post = Post::where('slug', $slug)->first();
    if (! $post) {
        $old = PostSlugHistory::where('slug', $slug)->first();
        abort_unless($old, 404);
        return redirect()->route('blog.show', $old->post->slug, 301);
    }
    return view('blog.show', compact('post'));
}

3. Titles, descriptions and canonicals

  • Pass title, description and canonical URL from each controller to the layout, or use a view composer or an SEO package such as artesaos/seotools.
  • Build canonicals from the route, not from the incoming request, so parameters and tracking codes never end up in them.
  • Add Open Graph tags for sharing on LinkedIn and messaging apps.
{{-- layouts/app.blade.php --}}
<title>{{ $seoTitle ?? config('app.name') }}</title>
<meta name="description" content="{{ $seoDescription ?? '' }}">
<link rel="canonical" href="{{ $canonical ?? url()->current() }}">

4. Structured data

Generate JSON-LD from your models and output it with @json in a layout stack. The full pattern is in adding JSON-LD schema in Laravel Blade templates.

5. XML sitemap and robots.txt

The spatie/laravel-sitemap package can crawl your site or build the sitemap from models. Building from models is faster and more accurate:

use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url;

$sitemap = Sitemap::create();
Post::published()->each(function (Post $post) use ($sitemap) {
    $sitemap->add(Url::create(route('blog.show', $post))
        ->setLastModificationDate($post->content_updated_at));
});
$sitemap->writeToFile(public_path('sitemap.xml'));

Run it from a scheduled command. Serve robots.txt from the public folder or a route, allow the crawlers you want, including AI search crawlers, and link the sitemap. Use a content-change date for lastmod, not updated_at if background jobs touch your records.

6. Rendering

  • Blade renders on the server, so crawlers receive full HTML by default.
  • If you use Inertia with Vue or React, enable Inertia’s server-side rendering for public pages; without it, crawlers that skip JavaScript receive an empty shell.
  • With a separate JavaScript front end, render public pages on the server there. See the Next.js checklist.

7. Performance

  • Cache config, routes and views in production (php artisan optimize).
  • Cache expensive queries and full responses for public pages where content allows.
  • Eager load relationships to avoid N+1 queries on listing pages.
  • Serve images in modern formats with width and height set, and lazy-load below the fold.
  • Consider Laravel Octane for high-traffic sites.

8. Behind Cloudflare or a load balancer

Configure trusted proxies so Laravel sees the correct scheme and client IP. Without it, generated URLs can use http instead of https, which breaks canonicals and sitemaps, and logs show the proxy’s IP instead of the crawler’s.

9. International sites

Add hreflang links for each language version, with a self-reference and matching return links on every version, and keep language in the URL path.

10. Test

  1. curl a few URLs and check status codes, titles, canonicals and JSON-LD in the raw HTML.
  2. Run our AI crawler access checker.
  3. Submit the sitemap in Search Console and Bing Webmaster Tools, and watch the Page indexing report.

Frequently asked questions

Do I need an SEO package?

No. Passing variables to a layout works well. Packages help on large sites with many content types.

Should Laravel pagination pages be indexed?

Let them be crawled and indexed with self-referencing canonicals, so items deeper in the list are found. Google no longer uses rel=”next” and rel=”prev” as signals.

Is Livewire crawlable?

Livewire renders the initial HTML on the server, so the first load is crawlable. Content loaded only after interaction is not.

Sources

  1. Laravel documentation: routing, redirects, Blade, caching, trusted proxies
  2. spatie/laravel-sitemap documentation
  3. Google Search Central: canonicalisation, redirects, sitemaps, localized versions