Display entries that meet multiple tag params
Ideally, you'll use a dynamic route that can match any number of tags – negating the need to hard code the number of possible tag segments.

You can't pull this off using the Routes admin inside the CP, so crack open your /craft/config/routes.php file and add this:

return array(
    'tags/(.+)' =&gt; 'path_to_your_tags_template',
); 


The above route can have any number of segments under /tags, but will require at least one. Be sure to delete any conflicting routes defined in Settings -> Routes!

Inside your tags template, you can get an array of all the tags in the URI like this (the |slice(1) part removes the first segment, i.e. "tags"):

{% set tagSegments = craft.request.segments|slice(1) %}


To pull the actual tags, you can do something like this:

{% set tags = craft.tags.slug(tagSegments) %}


Pulling it all together, here's how a (simplified) version of your template could look:

{# Get tags #}
{% set tagSegments = craft.request.segments|slice(1) %}
{% set tags = craft.tags.slug(tagSegments) %}

{# Get entries related to tags #}
{% set relatedTo = [] %}
{% for tagId in tags.ids() %}
    {% set relatedTo = relatedTo|merge([{
        targetElement: tagId,
        field: 'tags'
    }]) %}
{% endfor %}
{% if relatedTo|length &gt; 1 %}
    {% set relatedTo = ['and']|merge(relatedTo) %}
{% endif %}
{% set entries = craft.entries.relatedTo(relatedTo) %}

{% if entries|length %}
    &lt;h1&gt;Entries tagged with {% for tag in tags %}{{ tag.title }}{% if not loop.last %}{{ loop.revindex == 2 ? ' and' : ',' }}{% endif %}{% endfor %}&lt;/h1&gt;
    &lt;ul&gt;
        {% for entry in entries %}
            &lt;li&gt;{{ entry.getLink() }}..&lt;/li&gt;
        {% endfor %}
    &lt;/ul&gt;
{% else %}
    &lt;p&gt;No entries could be found with {{ tagSegments|length &gt; 1 ? 'those tags' : 'that tag' }}.&lt;/p&gt;
{% endif %}