I have code similar to below that basically just outputs links with query parameters:

{% for country in craft.categories.group("country").all() %}
   <a href="{{ url('wine') }}?country={{ country.id }}">{{ country.title }}</a>
{% endfor %}

{% for varietal in craft.categories.group("varietal").all() %}
   <a href="{{ url('wine') }}?varietal={{ varietal.id }}">{{ varietal.title }}</a>
{% endfor %}

{% for vintage in craft.categories.group("vintage").all() %}
   <a href="{{ url('wine') }}?vintage={{ vintage.id }}">{{ vintage.title }}</a>
{% endfor %}

This is all fine. Clicking on a link gives me what I need. For instance, clicking on a country link, I get this URL: site.com/wine?country=1

Here's where I'm stuck: how do I go about adding to the query string when clicking on multiple links not in the same category group. In other words if I click on a country link and a varietal link right after, I want the URL to be updated to look like so: site.com/wine?country=1&varietal=2

Then, if I click on a third link, such as vintage, update the URL like so: site.com/wine?country=1&varietal=2&vintage=3

But then, if I click on, say a different vintage link, just update the value rather than adding to the string further, like so: site.com/wine?country=1&varietal=2&vintage=99

1 Answer 1


So I'd approach it something like this:

    {# Get the incoming query params #}
    {% set params = craft.app.request.queryParams %}
    {# Change/add the params we need to #}
    {% set params = params | merge({
        'vintage' : 4
    }) %}
    {# Map the array into a query string #}
    {% set queryString = params | url_encode %}
    {# Output our link #}
    <a href="{{ url('wine') }}?{{ queryString }}">Link</a>

Basically, get an array of query parameters from the incoming request, then modify or add the one(s) we want to change, and re-ouput the query string.

The benefit of this method is that it'll preserve whatever is already in the query string, including things like gclid or other tracking parameters.

  • You can replace the |map() filter with |url_encode to simplify the solution. Also, { url('wine' ~ '?' ~ queryString) }} might read cleaner.
    – Ben Croker
    Aug 13, 2022 at 13:23
  • Ah nice, forgot about the url_encode filter! twig.symfony.com/doc/3.x/filters/url_encode.html Aug 13, 2022 at 15:33
  • This is somewhat working. What I'm finding is that for each category group/loop, the last item in the loop is used in the next loop's query string. Using the same initial example, the last link in the country set/group is set to /wine?country=54 (others have their corresponding IDs) & all links in the varietal group have the country param set even though the url may have the country param set to 50 (if it's present in the url at all). Hope that makes sense.
    – A Herrera
    Aug 16, 2022 at 21:02
  • Here's a screenshot in case it helps to demonstrate the issue: share.cleanshot.com/31FoZf
    – A Herrera
    Aug 16, 2022 at 21:06
  • I'd need to see your code for context to help further. Can you provide some in the original question that is updated with what you're doing now? Aug 26, 2022 at 19:15

Your Answer

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

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