Automate sitemap generation in Laravel using Spatie Sitemap

By Priyash Patil | Updated: May 14, 2023 6PM IST

Table of contents

  1. Install Spatie Sitemap
  2. Create custom Laravel command
    1. Verify the generated sitemap
  3. Automate sitemap generation
    1. Defining Schedules
    2. Running The Scheduler
  4. Conclusion

Install Spatie Sitemap

Spatie Sitemap is a Laravel package that makes it easy to generate sitemaps for your website. It provides a simple API for adding URLs to the sitemap and generates the sitemap file in XML format. The package also supports various options for customizing the sitemap generation process, such as including images, setting the priority and frequency of URLs, and more.

Run the following command in your terminal:

composer require spatie/laravel-sitemap

Create custom Laravel command

php artisan make:command GenerateSitemap

This will generate new console command at app/Console/Commands/GenerateSitemap.php. Open and modify the file as below:

<?php

namespace App\Console\Commands;

use App\Models\Post;
use Illuminate\Console\Command;
use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url;

class GenerateSitemap extends Command
{
    /**
     * The console command name.
     *
     * @var string
     */
    protected $signature = 'sitemap:generate';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Generate the sitemap.';

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $posts = Post::where('published', true)->get();
        $sitemap = Sitemap::create()->add('/');

        foreach ($posts as $post) {
            $sitemap->add(Url::create('/posts/' . $post->slug)
                ->setLastModificationDate($post->updated_at));
        }

        $sitemap->writeToFile(public_path('sitemap.xml'));
    }
}

In my case, I have a Post model of which I want to control the lastmod property for better ranking purposes. However, you can use the following code to automatically crawl the site, but remember this won’t give you full control of dates and all.

SitemapGenerator::create('https://example.com')->writeToFile($path);

Verify the generated sitemap

Run our custom command:

php artisan sitemap:generate

This will generate a sitemap.xml in the public directory. You can visit the url http://localhost:8000/sitemap.xml to confirm.

Automate sitemap generation

Laravel offers a command scheduler to manage scheduled tasks on your server. The scheduler allows you to fluently and expressively define your command schedule within your Laravel application itself. When using the scheduler, only a single cron entry is needed on your server. Your task schedule is defined in the app/Console/Kernel.php file’s schedule method.

Defining Schedules

You may define all of your scheduled tasks in the schedule method of your application’s App\Console\Kernel class. To get started, let’s take a look at an example. In this example, we will schedule our command sitemap:generate to be called every day at midnight :

<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * Define the application's command schedule.
     */
    protected function schedule(Schedule $schedule): void
    {
        $schedule->command('sitemap:generate')->daily();
    }

    /**
     * Register the commands for the application.
     */
    protected function commands(): void
    {        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}

You can customise the schedule duration as per your need. For example, you can use the following table for reference:

Method Description
->cron('* * * * *'); Run the task on a custom cron schedule
->everyMinute(); Run the task every minute
->everyTwoMinutes(); Run the task every two minutes
->everyThreeMinutes(); Run the task every three minutes
->everyFourMinutes(); Run the task every four minutes
->everyFiveMinutes(); Run the task every five minutes
->everyTenMinutes(); Run the task every ten minutes
->everyFifteenMinutes(); Run the task every fifteen minutes
->everyThirtyMinutes(); Run the task every thirty minutes
->hourly(); Run the task every hour
->hourlyAt(17); Run the task every hour at 17 minutes past the hour
->everyOddHour(); Run the task every odd hour
->everyTwoHours(); Run the task every two hours
->everyThreeHours(); Run the task every three hours
->everyFourHours(); Run the task every four hours
->everySixHours(); Run the task every six hours
->daily(); Run the task every day at midnight
->dailyAt('13:00'); Run the task every day at 13:00
->twiceDaily(1, 13); Run the task daily at 1:00 & 13:00
->twiceDailyAt(1, 13, 15); Run the task daily at 1:15 & 13:15
->weekly(); Run the task every Sunday at 00:00
->weeklyOn(1, '8:00'); Run the task every week on Monday at 8:00
->monthly(); Run the task on the first day of every month at 00:00
->monthlyOn(4, '15:00'); Run the task every month on the 4th at 15:00
->twiceMonthly(1, 16, '13:00'); Run the task monthly on the 1st and 16th at 13:00
->lastDayOfMonth('15:00'); Run the task on the last day of the month at 15:00
->quarterly(); Run the task on the first day of every quarter at 00:00
->quarterlyOn(4, '14:00'); Run the task every quarter on the 4th at 14:00
->yearly(); Run the task on the first day of every year at 00:00
->yearlyOn(6, 1, '17:00'); Run the task every year on June 1st at 17:00
->timezone('America/New_York'); Set the timezone for the task

Running The Scheduler

You can run the scheduler by php artisan schedule:run locally. But on a production server, you will need to configure the cron task. Do note you have to configure the corn task only once. After that, you can add more tasks in app/Console/Kernel.php . Make sure to schedule a cron task with the user you are using to serve the application to avoid permission-related errors.

First, log in to your server and check if there’s an existing cron scheduled. The following command will show the list of corn tasks:

crontab -l

If you don’t see any line like * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1 then you can add the cron line by running:

crontab -e

If you are running this command for the first time, this will ask you to select the editor. For example:

$ crontab -e
no crontab for ansible - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- easiest
  2. /usr/bin/vim.basic
  3. /usr/bin/vim.tiny
  4. /bin/ed

Choose 1-4 [1]:

I will continue with the option [1] which is the nano editor. This will open the crontab file which will look something like below. Add the line: * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1 at the end of the file. Make sure to update the path to your project.

# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

To save and close the file press ctrl+x and then press y to confirm. Now if you run the crontab -l will show your cron task entry.

This will automate the sitemap generation process, ensuring that your sitemap is always up-to-date with the latest URLs on your website.

Conclusion

In conclusion, automating sitemap generation in Laravel using Spatie Sitemap is a simple and effective way to improve your website’s visibility in search engine results. By following the steps outlined in this blog post, you can easily generate and customize your sitemap, add URLs to it, and automate the sitemap generation process using a cron job. Having an up-to-date sitemap can greatly improve your website’s search engine optimization, making it easier for search engines to index your pages and ultimately improving your website’s online visibility.