Assigning URLs to Tags

There is currently no built-in support for giving each tag its own URL, like there is with entries. That doesn’t mean you can’t do it yourself, though.

For the purposes of this tutorial, let’s say we want our tag URLs to look like “example.com/tags/[tag title]”, and we want those URLs to point to a template located at tags/_tag.html.

Create the Route #

First thing’s first: let’s create a new route from Settings → Routes with the following settings:

  • URI: tags/( ‘tag’ token )
  • Template: tags/_tag

Now, incoming requests pointing to example.com/tags/anything are going to be routed to our tags/_tag.html template, and there will be a tag variable predefined, set to whatever is in the second URL segment.

Create the Template #

The first thing we need to do in our tags/_tag.html template is fetch the requested tag:

{% set tag = craft.tags.title(tag).first() %}

Note: Up until this line, the tag variable will be set to whatever matched our ‘tag’ Route token, but after this line, it will either be a TagModel or null if no matching tag was found.

If someone tries to go to the page with an unknown tag title, we’re going to want to return a 404, so let’s do that:

{% if not tag %}
    {% exit 404 %}
{% endif %}

Any template code after that can be sure that tag is set to an actual TagModel. So what do we do with it? Let’s output a list of entries that are tagged with it:

<h1>Entries tagged with “{{ tag.title }}”</h1>

{% set entries = craft.entries.relatedTo(tag).order('title') %}

{% if entries | length %}
    <ul>
        {% for entry in entries %}
            <li>{{ entry.getLink() }}</li>
        {% endfor %}
    </ul>
{% else %}
    <p>No entries could be found with that tag.</p>
{% endif %}

Link to the Tag URLs #

Now that we’re all set up to handle tags URLs, we need to link to them.

Let’s say we want to output a list of the tags an entry is tagged with, at the bottom of each entry page. And we want to link those tags to their new tag URLs. Here’s how we’d do that, assuming our Tags field has a handle called “tags”:

{% if entry.tags | length %}
    <h3>This entry is tagged with:</h3>

    <ul>
        {% for tag in entry.tags %}
            <li><a href="{{ siteUrl }}tags/{{ tag.title | url_encode }}">{{ tag.title }}</a></li>
        {% endfor %}
    </ul>
{% endif %}

We’re using the url_encode filter to ensure that the tag title will be URL-safe when it’s output in the link URL.

And with that, our site now has some nice tag support!