I'm building a site where I am linking entries based on their tags. If you click on a tag you go to a dedicated page with all entries that share the same tag.

{% for tag in craft.tags.relatedTo(entry) %}
    <li><a href="{{ siteUrl }}tags/{{ tag.title | url_encode }}">{{ tag.title }}</a></li>
{% endfor %}

The problem I have is that if a tag has more than 1 word, the URL displays like this:


How do I change "%20" to a dash?

  • 1
    I've updated my answer below. I'm not sure if you're still having your issue, but would this have solved it? Jul 15, 2016 at 16:41

1 Answer 1



I just learned this, but as of Craft 2.4, there's a kebab filter which you can use here. This would probably give you the effect you're after, where the string "two words" would become "two-words", and punctuation characters are dropped by default.

You could use this like so:

<li><a href="{{ siteUrl }}tags/{{ tag.title | kebab }}">{{ tag.title }}</a></li>


The %20 string is being added to replace spaces because you're using the url_encode filter on tag.title. A simple (though somewhat naïve) way to to solve this would be to use the replace filter:

{{ tag.title | url_encode | replace({"%20": "-"}) }}

However, you might still see some "%XX" characters in this string if the tag.title has other characters that url_encode might want to replace. The "%" character, for example, gets turned into "%25" after being run through url_encode.

This also probably won't do what you expect, as the link you're generating for the tag won't work unless you're doing special routing. The problem stems from the fact that tags don't have clean URL slugs at this time, so what you're doing right now is probably the best course of action.

You've probably already seen this, but there's a documentation page specially about linking to tags. This is the current best practice I know of. If you're really looking for cleaner slugs in URLs, I'd recommend using categories instead of tags if possible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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