Take the 2-minute tour ×
Craft CMS Stack Exchange is a question and answer site for administrators, end users, developers and designers for Craft CMS. It's 100% free, no registration required.

It doesn't appear that tags are handled the same way as categories in the sense that categories have a slug (which results to a URI). I'd like to use tags to link to a "tag" page, similar to a category page, but "Really Cool Tag Name" doesn't work/look right as part of a URL. I've used the Slugify plugin to turn the tag in to a slug, however, I'm not sure the best approach to return the relationship of that tag as that slug is not related to the tag at all. Would the best practice be to add an additional slug field to the tag group? Then I'd be able to make that relationship. Thoughts?

share|improve this question

4 Answers 4

up vote 3 down vote accepted

Here's a really DRY way to do it.

Setup a route, something like "news/tags/(tag)" to load the "news/index" template (the same one used for listing all entries).

In the "news/index" template:

{# If there is a tag token in the URL, set a filtered variable. #}
{% if tag is defined %}

    <h2>Tag: {{ tag }}</h2>

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

    {% set entriesToShow = craft.entries.section('news').relatedTo(tag) %}

{% else %} {# No tag token in URL, assume unfiltered overview page. #}

    {% set entriesToShow = craft.entries.section('news') %}

{% endif %}

{# the entry loop for both filtered and unfiltered entries #}
{% for entry in entriesToShow %} 
    {# display entry #}
{% endfor %}

When templating tag links to this system use:

{{ siteUrl }}news/tag/{{ tag.name|url_encode }}

This method allows you to reuse your entry loop and you don't even need a "tags" template. I can also be expanded to filter by categories as well without needing another template.

share|improve this answer

There is a detailed help article dedicated to that in the help section of the Craft website.

In short

  • create a route
  • get all entries related to the tag
  • use {{ tag.name | url_encode }} to create the URL pointing to the tag page
share|improve this answer

I setup a route, in my case "news/tag/[tag]" with a template news/_tag. Then in the template I find the tag:

{% set actualTag = craft.tags.name(tag).first() %}
{% if not actualTag %}{% exit 404 %}{% endif %}

and get the entries related to the tag (could additionally restrict this by section):

{% set relevantEntries = craft.entries
  .relatedTo({
    targetElement: actualTag,
    field: 'tags'
  })
%}

[edited to add:] To get the list of tags with links to the tag pages (twig url_encode to translate tag name to url):

{% for tag in craft.tags.relatedTo({
    sourceElement: entries,
    field: 'tags'
  }).order('name')
%}
  {% set tagUrl = '/news/tag/'~(tag.name|url_encode) %}
  <a href="{{tagUrl}}">{{tag.name}}</a>
{% endfor %}
share|improve this answer
    
Do you use the tag as is in the URL or do you "slugify" it or create a secondary field for the "slug" field? –  Ryan Shrum Jul 8 at 17:25
    
I use the tag as is. My theory is that is what tags are designed for. –  Marion Newlevant Jul 8 at 17:28
    
So you use it with spaces if applies? i.e. "this is my tag" Which would render ".com/news/tag/this is my tag" –  Ryan Shrum Jul 8 at 17:28
    
craft turns that into "this+is+my+tag", and I use that –  Marion Newlevant Jul 8 at 17:31
    
Actually, I pass it through url_encode, and use that:{{tag.name|url_encode}}. Editing my original answer to include that... –  Marion Newlevant Jul 8 at 17:55

Not sure if this is the best way to go, but thus far I've used a custom route (in Settings->Routes) to setup tag listing/landing pages. Something like tags/* so the wildcard catches the tag slug.

{% set tagId = "" %} {# set the initial tagID variable outside of your loop to access it later in the template #}

{% if craft.request.getSegment(1) == "tags" %} {# if you're on the tag listing template #}
    {% set tags = craft.tags.find() %} {# get all tags in the system #}
    {% for tag in tags %}
        {% set tagUrl = tag.name|lower|replace({' ': '-'}) %} {# do the same string manipulation that you did to create the slug that links to this page #}
        {% if (tagUrl == craft.request.getSegment(2)) %} {# grab the tag that matches your URL #}
            {% set tagId = tag.id %}
        {% endif %}
    {% endfor %}
{% endif %}

Then, grab entries that are related to this tag:

{% set tag = craft.tags.id(tagId) %}
{% set entries = craft.entries.section('blog').relatedTo(tag).find() %}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.