Last week, I refactored parts of this website and broke the endpoint that creates this sitemap. I decided to read up on sitemaps before fixing the route. Here is what I learned.
Google's take on sitemaps
Web developers often assume that Google might only index their site regularly with a sitemap. But is this true? In the Google Search Console docs, Google answers the question "Do I need a sitemap?" with "it depends". Google recommends a sitemap when
- you launch a new site, and no or few external links point to your site or
- your site is large, and not all pages are linked and discoverable by Google's crawler.
You do not need a sitemap if
- your site is small (up to 500 relevant pages) or
- your site is linked correctly, and Google can find all relevant pages by crawling it.
My website maier.tech is small, and all pages are discoverable by a crawler, so I would not need a sitemap. Yet, I submitted a sitemap in May 2021 as an initial SEO boost. You can see when Google last read a sitemap in the Google Search Console. For my site, it was almost two years ago:
Different types of sitemaps
Google supports different types of sitemaps. If your site already has an RSS feed, you can submit the feed URL as a sitemap and call it a day. But the most common sitemap type is XML. A simple XML sitemap that indexes only the homepage looks like this:
Every indexed page goes in a <url>
tag. The <loc>
tag
contains the URL of the indexed page. The <lastmod>
tag contains the last modified date. You may have encountered posts
mentioning two more tags, <priority>
and <changefreq>
. There
is no need to worry about choosing values for these two tags. Google ignores both (and so does Bing).
Creating a sitemap with SvelteKit
SvelteKit's SEO docs show an
example of a sitemap implemented as an endpoint in src/routes/sitemap.xml/+server.js
.
The GET
handler assembles an XML string to which you add relevant routes. There is no
need to add all routes, only those you want to be indexed by Google. The catch is that you need to
figure out how to retrieve the entries for your sitemap. There is no copy-paste blueprint for how to
create a sitemap with SvelteKit because a sitemap depends on how you manage the content of your site.
But I will walk you through the steps.
Create endpoints to retrieve relevant pages
I created an endpoint src/api/posts/+server.js
that returns a list of all posts, which it obtains from a file that contains an array with metadata
for all posts. If I managed my posts in a CMS, the endpoint would retrieve them via an API call to
the CMS. Add an endpoint for each type of content you want to include in your sitemap.
Create a sitemap endpoint
Create an endpoint src/routes/sitemap.xml/+server.js
and add an async GET
handler with the following structure:
Since this endpoint returns XML, I set the content type to application/xml
. Then I
fetch all posts from my endpoint /api/posts
. At the end of the handler, I create the
XML string, wrap it in a response object and return it.
function create_entry(path, lastmod) {
return `<url>
<loc>${new URL(path, PUBLIC_CANONICAL_ORIGIN).href}</loc>
${lastmod ? `<lastmod>${lastmod}</lastmod>` : ''}
</url>`;
}
path
is a relative path, and lastmod
is a date string in ISO format. I
get both from my /api/posts
endpoint. Google expects absolute URLs in a sitemap.
Since I prerender the sitemap, I cannot obtain the origin of the URL from which the app is served
in production. Therefore, I created an environment variable PUBLIC_CANONICAL_ORIGIN
,
which contains my site's canonical origin https://maier.tech. This variable could also be private
and named CANONICAL_ORIGIN
. But I also need access to the canonical origin in my SEO
components client-side, which means that the variable has to be public.
Let's add error handling to wrap up the handler:
The above code is a simplified version of my actual endpoint, which you can explore on GitHub. My actual endpoint adds caching, validation, and prerendering.
Alternative sitemap creation
If your SvelteKit site uses adapter-static, you can use package svelte-sitemap. With this package,
instead of implementing an endpoint for a sitemap, you can configure the postbuild
hook in package.json
to scan all routes in the build
directory and create build/sitemap.xml
. This approach only works with adapter-static, since svelte-sitemap
cannot determine all possible routes for other adapters.