Generate an XML Sitemap In Laravel
Generate an XML Sitemap In Laravel, if you want to build a sitemap, there are several packages built that can help you with smaller websites. One of them is the popular Spatie Sitemap package, which crawls your site when you ask it to and builds a sitemap for you based on the pages your frontend is linked to.
For smaller websites that only contain a few hundred pages, these packages will work great, and I recommend checking them out.
For a larger website with thousands of pages, you will not want to use them.
In my case, I was working on the Nursery People website a few months ago, and I wanted to build a sitemap for the site to help Google and other Search Engines see the pages on the site more easily. The Nursery People website has well over 30,000 pages, so I learned quickly that sitemap crawlers were not able to get the job done efficiently.
In this article, I’ll share how you can build a sitemap for a large website like I did for the Nursery People site.
Getting Started
First, you need to have a running Laravel application set up. For this tutorial, I created a new Laravel 8 application if you would like to follow along with the code, or you can just build this in your application.
For this example, I built a simple Model, Controller, and Migration for Posts. Of course, in your app, you will have more models, but for this example, I kept it simple.
Creating a Sitemap Controller
Once your application is built, you will want to build routing for your Sitemaps.
In our app, we will generate two controllers for the website but for your app, you may want to generate several controllers.
For example, you may want to create a PostSitemapController for your Post model, and a TagSitemapController for Tags.
Generate the SitemapController
In your terminal:
php artisan make:controller SitemapController
Add the Index Route
In routes/web.php add a route for the main entry point of your sitemap.
//Sitemap Routes
Route::get('/sitemap.xml', [SitemapController::class, 'index'])->name('sitemap.index');
This will be the main sitemap that will contain links to the other sitemaps on the site.
We are also giving our sitemap a name so that we can easily route to it in our blade file.
Write the index() method in the SitemapController
Next, you will want to create the index method that we just referenced in the web.php route file.
For my app, the controller looks like this:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class SitemapController extends Controller
{
public function index()
{
$post = Post::orderBy('updated_at', 'desc')->first();
return response()->view('sitemap.index', [
'post' => $post,
])->header('Content-Type', 'text/xml');
}
}
As you may notice, we are getting the latest post in this method. I will share why in a moment.
Also, we return a blade view with a header of “Content-Type”, “text/xml”. This is how we tell out app that we are returning an XML file, not an HTML page.
Build the XML Blade View
Create a sitemap folder in your /resources/views directory and create a file named index.blade.php.
Inside this file, add the following. You can also see how I am using the $post that I got inside our index method here to show the last time our sitemap was updated.
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
@if($post != null)
<sitemap>
<loc>{{ route('sitemap.posts.index') }}</loc>
<lastmod>{{ $post->updated_at->tz('UTC')->toAtomString() }}</lastmod>
</sitemap>
@endif
</sitemapindex>
Since this is the entry point to your other sitemaps, you can add as many links to other sitemaps as you would like. These will be generated in the next step.
In my simple example, I am only creating one sitemap index for my posts.
Now, my sitemap looks like this when visiting the /sitemap.xml link:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url>
<loc>{{change this with your url}}</loc>
<lastmod>2023-08-15T11:42:45+00:00</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
</urlset>