Passing a variable across liquid files - Pulling my hair out :-)

Topic summary

A Shopify developer working with the Horizon theme needed to pass a selected product size option ID from variant-main-picker.liquid to slideshow-controls.liquid to create dynamic URLs for product thumbnail images.

Original Problem:

  • When customers clicked product thumbnail images (different colors), the color swatch didn’t update to match
  • The developer wanted thumbnails to link directly to specific variant URLs using option_values parameters
  • Needed to preserve the currently selected size when switching colors to prevent cart errors

Initial Approach (Failed):

  • Used {% capture %} and {% render %} to pass size_id variable between files
  • Variable returned multiple null values in loops, making it unusable in href strings

Solution Found:
Using globally available product.options_with_values:

{% assign selected_options = product.options_with_values | map: "selected_value" %}
{{ selected_options | map: "id" | split: ',' | last | split: '\]' | first | strip }}

Additional Fix:
Added JavaScript to clean URLs after thumbnail clicks, removing option_values parameters to prevent conflicts when customers subsequently click color swatches.

Caution Noted:
Removing URL parameters may break tracking functionality (web pixels, analytics) or apps that rely on variant URL parameters to determine selected variants.

Status: Resolved with working implementation, pending further testing.

Summarized with AI on October 23. AI used: claude-sonnet-4-5-20250929.

Horizon Theme

Hoping anyone can shine some light. From reading other threads and scouring the web, I have learned how to pass a variable from variant-main-picker.liquid over to slideshow-controls.liquid. Long story short, trying to pass 1 variable (related to selected shirt size option) over from ‘variant’ file to my ‘slideshow’ file to use inside a href attached to my product thumbnails. So far I have done:

In variant-main-picker, I added the following code in bold:

{% if product_option_value.selected %}

checked                    

**{% capture size_id %}{{ product_option_value.id }}{% endcapture %}**

{% endif %}

and also used the following in the same file:

{% render ‘slideshow-controls’, size_id: size_id %}

Now if I hop over to the slideshow file and insert the following code at random on the page for testing results:

{{ size_id | json }}

it returns the following on my product page:

I assume it shows ‘null’ in there multiple times before showing the number I need because it is looping through all the sizes. But there lies the problem. I want to enter the {{ size_id }} elsewhere on the slidehow page into a URL string, but when I do that, it comes back completely empty. I can only assume that might be because it is using the first or last one of the iterations of null, instead of the ‘3770076725421’ that I need it to use in this particular case.

How can I use the {{ size_id }} in a href string and it not come up blank? Hope that made sense. Yes, I am very beginner at this, so please help in any way you can. Thanks.

PS - I even temporarily played around with if/then == ‘3770076725421’ for example, and it always comes up false. I think because when looking at {{ size_id }} it sees the null entries in there so no match??? HELPPPPPP

1 Like

Hi @ndisgii_shopify :waving_hand: recognizing the effort you put into respecting others time by providing the level of detail others might need.

Buried the lead a bit but if that’s all that’s needed, try this INSIDE the forloop

    {%- capture size_id -%}{{ product_option_value.id }}{%- endcapture -%}
    {%- if size_id  != blank -%}
      {%- break -%}
    {%- endif -%}

This does mean it should apply to the FIRST non-blank value, which depending on your logic can itself be a different bug.

:technologist: blank vs null can have some over under in matching for falsey or blankness.
And note how i’m also using white space control characters, dashes {%- -%} {{- -}}, to avoid false positives and minimize deadspace rendering.

Advanced
Depending on what your doing if it’s an array, it’s type, and if A LOT of resources/objects.
Using the uniq filter might get rid of most duplicate blanks and be a miniscule performance increase.
Or using the where or reject filters in an assign statement may be better than a forloop with a capture.

I just tried this without success. It actually jumbled up the screen somehow, and still did not allow me to use the variable in my custom url. Let’s attack this in a different way all together.

In your thought, if you needed to grab the size option id code of the currently active/selected product size, which can be found in the variant.main.picker file, and send that id code over to the slideshow.controls file, so it can be used inside a custom href url tag on my thumbnail images, how would you go about doing it yourself?

I have already figured out how to achieve the following url successfully within the slideshow.controls file with my custom coding:

/wealth-of-god-unisex-t-shirt?option_values=3770076430509

That takes care of the color choice, but what I cannot get to work is to add the above red circled id code to the end of it for the size choice. It should look like this:

/wealth-of-god-unisex-t-shirt?option_values=3770076430509,3770076725421

What is the best/optimal way to do this? Thank you to anyone willing to tackle this ::clap: . I’m soooo close.

I do not quite understand what you’re trying to achieve.

Here is some general info:

If your snippets are render-ed, then any variable defined inside those snippets stays inside and does not get passed to calling sinppet/section/block.
To make your snippet variables visible to caller, you’d need to use include instead of render (though include is deprecated for performance reasons)

None of variables you define gets passed into render-ed snippet unless they are specifically mentioned in the render call.

Same goes to blocks (and sections) – variables defined inside the block are scoped to this block. Except you can’t really pass any variables into sections…

So far, based on what I’ve seen I’d say that what you’re trying to do is not possible (with Liquid only).

But – give more information (and use </> button to paste your code to avoid it being mangled) …

1 Like

That would indicate a bug somewhere that may be causing tail chasing and voodoo.
Try to make a minimal test case that only outputs the size_id as a string, free of snippets, free of other layout concerns, apps, etc etc etc.

I’d start with the selected variant or product.options_with_values and work my way down

Also see available to possibly handle skipping blanks https://shopify.dev/docs/api/liquid/objects/product_option_value#product_option_value-available

ugh I don’t know how to get discourse to NOT truncate/title the urls so you can see the # anchors to specific properties, that’s annoying. edit: surround full urls with angle brackets <https://url> to prevent autotitling.

1 Like

Thank you so much for the response. Ultimately, what I am trying to achieve is something that, in my personal opinion, should be the default way things work on product pages, but does not. I feel that when customers are clicking on my product images on the color they like, the swatch option should also change to match whatever image color they are clicking on. By default, when they click a thumbnail image (a color they like), you can see the variant url change in the address bar, but it does not actually select the matching swatch option. Example…I have a shirt that has 15 color choices. The primary image shows the 1st color choice, and the thumbnails show the remaining color choices. However, when someone clicks one of the thumbnails (lets say orange color shirt), it simply changes the main product image to the orange shirt image, but it does not change the actual swatch option to match it. So if a customer picks a thumbnail of the color they like, and are not paying attention, they may then add the product to cart as the wrong color. The image should match the swatch option.

I only found one existing shopify app to fix this specific issue called Variant Wizard, but of course it costs extra money every month and messes up my Google Insights scoring and load times because of how it functions. So I am trying to come up with my own way to achieve something similar.

My simple solution is to make my image thumbnails (when clicked on) physically take you directly to that specific color’s URL page. That will also force the color swatch option to then match the thumbnail image color they clicked on due to page reload. This can be achieved using ‘color’ option_value ID code, such as:

wealth-of-god-unisex-t-shirt?option_values=3770076430509

where 3770076430509 takes them straight to the green shirt for example. This can all be done with one line of code (onclick="location.href=……custom url coding……) in the slideshow.controls.liquid file. That is the easy part.

The problem with this technique is that it automatically takes you to the ‘small’ size option every time. I want it to take them to whatever size they may have already been looking at before clicking a new color image. For example, if they were just looking at green shirt in XL size, when they then switch to orange color, I want the size to stay at XL and not reset to small again. Again, to prevent confusion and the possibility for a customer to add wrong item to cart. But to accomplish this task, we need to now add the ‘size’ option_value ID code on the back of the url they are clicking, such as:

wealth-of-god-unisex-t-shirt?option_values=3770076430509**,3770076758189**

where 3770076758189 signifies XL. That url would now take them to the green/XL shirt based on the fact that they were last looking at XL.

But this is the part I cannot figure out . That info is stored in the variant.main.picker.liquid file. Properly getting that last size ID code over to the slideshow.controls.liquid file, and being able append it to the back of the url, is where I am stuck. It must be possible somehow.

Thank you as well. I will dig through those links tomorrow. While you were posting, I also made a long post trying to explain better my idea. Thanks.

By the way, I want to make it clear that there are many apps that allow you to click on a color option swatch and the actual image changes to match it. BUT I have only found one app that will do the reverse, which is allow you to click on the product image itself, and it will then change the swatch option to match. That is important to note.

Yes, that’s what many people want and there was a ton of solutions for the old themes, however, Shopify’s stance on this issue is that variant selectors are the source of truth.

They think people might accidentally tap a product thumb and change the variant,
which is reasonable.

Especially, on mobile where you often see either images or variant selectors, not both at the same time.
Basically their fear is the same as yours, but kinda “opposite” :slight_smile:

Also – you can select current variant by ?variant=XXX in the URL (which is what most themes use), and (only relatively recently) you can use combination of product options, like you mentioned –
?option_values=3770076430509,3770076758189

And yes, if your product has more than one option, specifying only one will get you to the first variant bearing the selected option value.

Back to your current task.

You should be able to pull the currently selected data from the product.options, like this:

{% assign selected_options = product.options_with_values | map: "selected_value" %}
Selected options names: {{ selected_options | json }}
Selected options IDs: {{ selected_options | map: "id" | json }}

product is globally available variable on the product template page, or you can reference closest.product in blocks, so no need to pass data from one snippet to another.

2 Likes

OMG thank you so much. This seems to do the trick. I used your provided code as follows:

At the top of my slideshow-controls.liquid, I placed the following line:

{% assign selected_options = product.options_with_values | map: “selected_value” %}

And then further down in my custom thumbnail URL string, I used this code at the end:

{{ selected_options | map: “id” | split: ‘,’ | last | split: ‘]’ | first | strip}}

That worked great.

I then ran into a totally new problem, where after clicking a thumbnail and going to that product using the option_values parameters custom url, if they then clicked on another actual color swatch option, it would add the variant id behind my option_values ids. Something like this:

wealth-of-god-unisex-t-shirt?option_values=3770076430509%2C3770076954797&variant=44883555745965

The problem with that is that if they then hit ‘refresh’ or reloaded the page at that point, it would reset back to 1st image and 1st size because of the odd url.

To fix this problem, I also added the following code directly beneath the of the theme.liquid, in order to clean up the final url after clicking thumbnail. It gets rid of the option_values parameters, and only leaves the ?variant=xxxxxxxxxxxx when there is one.

{% if template.name == ‘product’ %}

{% endif %}

I will continue testing, but this setup seems to be working well so far. I cannot thank you all enough.

1 Like

Looks like it removed my script. Let me try again:

{% if template.name == ‘product’ %}
<script>
(function() {
const url = window.location.href;

  if (url.includes('?option_values')) {        
    const cleanUrl = url.split('?')[0];        
    window.history.replaceState({}, document.title, cleanUrl);
  }
})();

</script>
{% endif %}

1 Like

@ndisgii_shopify to help future merchants & searchers like yourself, if your able to can you edit your title to include “of selected options”, or more word “of products selected options” , thanks.

1 Like

I am not seeing where I can edit the post in any way. This was my very first post on here, so maybe that is why???

Yeah probably from first time posting, there should be a little pencil icon next to the title, but it may be an elevate privagle :frowning: . Thanks for trying.

1 Like

Most of this function updates the current page URL according to the variant change. So you may look at it.

One thing to be aware of – several apps and maybe some other code actually use this URL parameter to determine currently selected variant (say web pixels?). So, changing to ?option_values notation or removing it completely may break that functionality.

Can’t say how important this can be to you, but worth mentioning.

1 Like

Thank you for that added info. I will look into that as well. I don’t even know what Web Pixels is to be honest. As I mentioned, very new to all of this and learning as I go. Your input is greatly appreciated!!!

Web pixels term is used to denote code used to track what visitor does on your pages. Google Analytics is an example of this functionality.

1 Like

OK, thank you Tim. Much appreciated!