Craft Tags in sitemap.xml

One of the features of ChangingFace.org, a documentary film directory I released recently, is a big ol' tag cloud that lets your browse films by theme.

Tag Cloud
The Tag Cloud on ChangingFace.org

Craft has a field type for tags that makes it a breeze to incorporate this into the site's template. But when it came time to launch the site I wanted to automate the generation of the sitemap.xml file (sitemaps are machine-readable files that tell search engines where to find all of the pages on your site). There are freely available plugins that do this for you, but because tags aren't presumed to have URLs associated with them they weren't being included by the plugin.

But it turns out you can generate the xml code yourself using a twig template and a few simple Craft entry queries. Save the twig file with the .xml extension in your templates directory and everything just works. Aside from the tags, the site only has a single Section serving entries from Craft. It took just a few quick minutes to generate the code for those entries (which is what the plugin was already doing successfully).

{% set myEntryQuery = craft.entries()
.section('***SECTION NAME***')
.all() 
%}

{% set entries = myEntryQuery %}

{% for entry in entries %}

<url>
 <loc>{{ entry.url }}</loc>
 <lastmod>{{ entry.dateUpdated|date("c") }}</lastmod>
</url>
 
{% endfor %}

But the tags needed special treatment. Here's the loop:

{% set tagQuery = craft.tags()
.group('***TAG GROUP***') %}

{% set tags = tagQuery.all() %}

{% for tag in tags %}

<url>
 <loc>{{ siteUrl }}tags/{{ tag|url_encode }}</loc>
</url>

{% endfor %}

The url_encode Twig filter is important, because tags often get titled with spaces, and that filter will encode them in a URL-friendly format.

It was nice to have such a straightforward solution to the problem, and it's always refreshing to not have to rely on a third-party plugin when there's a simple solution like this on hand.