Get query params in liquid

Hello everyone,

Hope you’re all doing well!

I’m currently working on a project with a mobile sticky bottom bar and have run into an issue with handling URL query parameters directly in Liquid (not JavaScript). I have a single page but need to handle it differently based on the query parameters. Here’s the setup:

  • For the URL with the query type=product, I want to run a specific set of conditions.
  • For the URL with view=wishlist, a different set of conditions should apply.

Here are the example URLs:

  • /search?type=product&options
  • /search/?view=wishlist

I’m looking for help on how to write this logic in Liquid to check the query parameters in order to conditionally render the right content.

Thank you in advance for any guidance or advice on this!

image

 <div class="sr4-toolbart-{{block_type}} sr4-toolbar-item -{{ request.query }}-" {% if request.query.view == "wishlist" %}aria-current="page"{% endif %} >
                <a data-link-wishlist href="{% if settings.wishlist_mode != '3' %}{{ search_url }}/?view=wishlist{%- else -%}/pages/wishlist{%- endif -%}">
                    <span class="sr4-toolbar-icon sr4-pr">
                      <svg class="feather feather-heart" width="25" height="22" viewBox="0 0 25 22" fill="none" xmlns="http://www.w3.org/2000/svg">
                      <g clip-path="url(#clip0_740_70674)">
                      <path d="M6.56995 0.635825C3.3196 0.61887 0.665727 3.19613 0.648438 6.39228C0.648438 8.96107 1.68578 15.0482 11.895 21.2031C12.2667 21.4235 12.7335 21.4235 13.1052 21.2031C23.3144 15.0482 24.3518 8.96107 24.3518 6.39228C24.3345 3.19613 21.6806 0.627348 18.4302 0.635825C15.1626 0.635825 12.5087 4.12022 12.5087 4.12022C12.5087 4.12022 9.85487 0.635825 6.57859 0.635825H6.56995Z" stroke="#2A2A2A" stroke-width="1.47732" stroke-linecap="round" stroke-linejoin="round"/>
                      </g>
                      <defs>
                      <clipPath id="clip0_740_70674">
                      <rect width="25" height="22" fill="white"/>
                      </clipPath>
                      </defs>
                      </svg>
                      <!-- <span data-count-wishlist class="MB_TOOLBAR-W sr4-pa sr4-op-0 sr4-ts-op sr4-count-box">0</span> -->
                    </span>           
                    {%- if show_txt -%}<span class="sr4-toolbar-label">{{bk_stts.title}}</span>{%- endif -%}
                </a>
            </div>

There is currently no ‘native’ way to achieve this, but it can still be done via a hacky way that involves using content_for_header, but be advised this could break at any time should content_for_header change.

Just FYI, the view parameter is used by Shopify to present different templates, so be careful using that.

This is the setup I use.

{% comment %}
  Retrieves parameters from the URL

  Accepts:
    - key: {String} Pass a key to retrieve certain data

  Usage:
    {% render 'data-url-parameters' key: 'handle' %}
{% endcomment %}

{%- liquid
  # theme-check-disable
  capture content_for_query_string
    echo content_for_header
  endcapture
  # theme-check-enable

  assign page_url = content_for_query_string | split: '"pageurl":"' | last | split: '"' | first | split: '.myshopify.com' | last | replace: '\/', '/' | replace: '%20', ' ' | replace: '\u0026', '&'

  assign page_query_string = page_url | split: '/' | last
  assign split_string = page_query_string | split: '?'
  assign parameters = split_string[1] | downcase | split: '&'

  if key
    assign parameter_found = false

    assign key_downcase = key | downcase

    for parameter in parameters
      assign parameter_arr = parameter | split: '='
      assign parameter_property = parameter_arr[0] | downcase
      if parameter_property == key_downcase and parameter_found == false
        assign parameter_found = parameter_arr[1]
      endif
    endfor

    if parameter_found
      echo parameter_found
    endif
  else
    assign parameters = parameters | join: ','
    echo parameters
  endif
-%}
1 Like

Thank you, Luke, for your response and for sharing your setup! Your code gave me some helpful insights.

I noticed you used the key variable within the if condition but didn’t define it explicitly at the top. I wasn’t sure if that was intentional, so I took inspiration from your approach and made some adjustments to fit my use case.

Here’s the code I’m using now:

{%- liquid
  # theme-check-disable
  capture content_for_query_string
    echo content_for_header
  endcapture
-%}

{% assign getfullurl = content_for_query_string | split: '"pageurl":"' | last | split: '"' | first | split: '.myshopify.com' | last | replace: '\/', '/' | replace: '%20', ' ' | replace: '\u0026', '&' %}

<div class="sr4-toolbart-{{block_type}} sr4-toolbar-item" {% if getfullurl contains "/search?view=wishlist" %}aria-current="page"{% endif %} >

This setup works to check if the URL contains view=wishlist and applies the condition accordingly. Let me know if you have any further suggestions or if there’s anything else I should consider. Thanks again for your help!

You could store the data in cart attributes and get it in Liquid that way.

You could still utilize the URLs like you were mentioning but you would just have the data in Liquid via cart attributes without needing to rely on something that could break anytime as @Luke noted…

Hi Rob,

Thank you for the suggestion! I understand the concept of using cart attributes to store the data and access it in Liquid, but could you provide a specific example? I’d like to see how the process would work end-to-end, especially for detecting the query parameter and setting it as a cart attribute.

Thanks again for the help!

For example, if you are linking to the pages with those URLs, you could instead link to something like:

/cart/update?attributes[view]=wishlist&return_to=/search%3fview=wishlist

Then whenever you do not need them, for example before going to checkout you would just remove them like this:

/cart/update?attributes[view]=&return_to=/checkout

The ability to add custom data for use within Liquid via URLs (or AJAX Cart API) is one of the main reasons I love Shopify.

You could even use them with URL redirects to mask the main URL with something like /wishlist. On the customer end they would see that path then the final one with the view parameter but never the one in between via their URL bar/history.

My approach is to use the url path as pseudo query parameters:
/search/type/products
and then
assign url_segments = request.path | split: '/'
and analyze the segments with liquid.
I believe this may be more stable than content_for_header, but no way to know for sure.

1 Like

That approach certainly works in at least some cases, and could probably work here given that /search still seems to function normally with a variable path length.

The approach I shared would keep the end URL structure the same and not require use of parsing {{ content_for_header }} for details. Depending on your requirements it may be the most suitable approach for future-proof sake, but I guess ultimately Shopify could cause none of them to work in the future… :upside_down_face:

If the end URL structure does not matter much then the approach @Daniel_G may be quickest to implement.

At this point the ball is in your court @Ahsan_Ahmed. Any of these approaches seem like they could work well for you at least for now.

Not really relevant to what @Ahsan_Ahmed is trying to do, but thought it was worth mentioning that I ran into some issues using the content_for_header method on a page type that seems to be more aggressively cached, a blog post in my case. Basically, the URL/parameter that was in the content_for_header didn’t always match what I loaded in the browser.

Thanks for adding that heads-up to the discussion! Situations like that are definitely something to consider in this case!

Maybe this will help~

Doesn’t that interfere with the normal functioning of the search page?

Not if you choose a marker that isn’t used in normal
searches , which is most unicode characters.