Linked variations in products - enterprise theme

Hello, I want to have linked variations.

If I have for example a product in 10 different colors. each color has it’s own name, SKU and description. I already made each color as a single product as I need all of them to be available in collections, however, i want to have them all linked with each other, so for example, if customers opens red product, they will see all the other colors in variants (brown, yellow etc.) but what is important is that the variants’ SKU is connected to a single product due to inventory tracking . So basically, I need the products LINKED with each other. and seen as variants. This is the example of what i want to achieve: https://concept-theme-tech.myshopify.com/products/air-beats-gold-tone

How can I achieve that?

I tried adding metafield values (type: product; list of products), but I didn’t find a way to show that on my product page. I use Enterprise theme.

Any help would be much appreciated, preferably if I can do it myself or with a free app!

@enterprise123 the Theme “Concept” (your example) as well as “Be Yours” have a build in feature for this.

If you want to do it by yourself, you’ll have to use the product reference (list) metafield, link the products and display them via custom liquid code.

This is an example of how the code should look like to display the variants as a list including a link.

{% assign siblings = product.metafield.[namespace].[key].value %}

{% for sibling in siblings %}
- {{ sibling.title }}
{% endfor %}

Please replace namespace and key with your definitions

When you are assigned the variants of a product, you have to repeat this process for each variant.

If you want to display the color instead of the product title, you’ll have to modify the code.

Hello @Finer ,

Your code worked, except there was a small mistake at the beginning (it should be product.metafields.[name]…, instead of product.metafield.[name]…) but I was able to figure that out. Thanks a lot!!!

Also, are you able to help me achieve the displaying first product image of the variant instead of the list?

That would fix all my problems :slightly_smiling_face:

@enterprise123 you can try the code by pasting it into a custom-liquid block.

{% assign siblings = product.metafields.custom.variation_products.value %}

{% for sibling in siblings %}
- {{ sibling.title }}
{% endfor %}

There was a small typo in the code — it should be “product.metafields” and not “product.metafield”.

Regarding the Image:

{% assign siblings = product.metafield.custom.variation_products.value %}

{% for sibling in siblings %}

{{ sibling.featured_image | image_url: width: 50 | image_tag }}
{{ sibling.title }}

{% endfor %}

This should display the images of the products (in one row), but you’ll have to modify the styling.

Awesome, I made some changes to make it work for me, added tootip and styling and this is the final code, in case someone else needs help.

{% assign siblings = product.metafields.custom.variation_products.value %}

  {% for sibling in siblings %}
    
      
      {{ sibling.title }} 
    
  {% endfor %}

Thanks a lot @Finer , your help is much appreciated!

This post was helpful. I was able to take it a step further and display the swatches/swatch images associated with the shopify category metafield for color. As suggested, I used a metaobject to hold my various sibling groups and a metafield with the metaobject reference on the product. In case anyone finds it helpful:

{% assign sibling_group = product.metafields.custom.siblinggroup.value %}
{% assign siblings = blank %}
{% if sibling_group != blank %}
  {% assign siblings = sibling_group.products.value %}
{% endif %}

{% if siblings != blank %}
<div class="siblinglabel"><legend class="label">Additional Colors</legend></div>
  <div class="siblings">

    {% for sibling in siblings %}
      {% assign cps = sibling.metafields.shopify["color-pattern"].value %}
      {% assign cp = blank %}

      {% if cps != blank %}
        {% assign cp = cps | first %}
        
        {% if cp != blank and cp.first %}

          {% assign cp = cp | first %}
        {% endif %}
      {% endif %}

      {% assign cp_label = blank %}
      {% assign cp_image = blank %}
      {% assign cp_color = blank %}

      {% if cp != blank %}
        {% assign cp_label = cp["label"] %}
        {% assign cp_image = cp["image"] %}
        {% assign cp_color = cp["color"] %}
      {% endif %}

      {% assign swatch_url = blank %}
      {% if cp_image != blank %}
        {% if cp_image.preview_image != blank %}
          {% assign swatch_url = cp_image.preview_image | image_url: width: 60, height: 50, crop: 'center' %}
        {% else %}
          {% assign swatch_url = cp_image | image_url: width: 60, height: 50, crop: 'center' %}
        {% endif %}
      {% endif %}

      <a
        href="{{ sibling.url }}"
        title="{{ sibling.title | escape }}"
        class="siblings__item {% if sibling.id == product.id %}is-active{% endif %}"
      >
        {% if swatch_url != blank %}
          <img
            loading="lazy"
            src="{{ swatch_url }}"
            width="60"
            height="50"
            alt="{{ cp_label | default: sibling.title | escape }}"
          >
        {% elsif cp_color != blank %}
          <span
            class="siblings__swatch"
            style="--swatch-color: {{ cp_color }};"
            aria-label="{{ cp_label | default: sibling.title | escape }}"
          ></span>
        {% else %}
          {{ sibling.featured_image
            | image_url: width: 60
            | image_tag: alt: sibling.title, width: 60, height: 50, loading: 'lazy'
          }}
        {% endif %}
      </a>
    {% endfor %}
  </div>

  <style>
    /* tweak these if you want */
    .siblings { --thumbh: 50px; --thumbw: 60px; --pad: 3px; --radius: 4px; }
    .siblinglabel {margin: 10px 0;}

    .siblings{
      margin: 10px 0;
      display: flex;
      flex-wrap: wrap;
      gap: 4px;
      align-items: center;
    }

    /* Reserve space (prevents CLS) + creates the "gap" via padding */
    .siblings__item{
      display: inline-flex;
      align-items: center;
      justify-content: center;

      width: calc(var(--thumbw) + (var(--pad) * 2));
      height: calc(var(--thumbh) + (var(--pad) * 2));

      padding: var(--pad);
      border-radius: calc(var(--radius) + var(--pad));
      box-sizing: border-box;

      transition: box-shadow 0.2s ease;
    }

    .siblings__item img,
    .siblings__swatch{
      display: block;
      width: var(--thumbw);
      height: var(--thumbh);
      border-radius: var(--radius);
    }

    .siblings__item img{
      object-fit: cover;
    }

    .siblings__swatch{
      background: var(--swatch-color, transparent);
    }

    /* Hover ring sits OUTSIDE the padding, so you see space */
    .siblings__item:hover{
      box-shadow: 0 0 0 2px rgba(0,0,0,0.6);
    }

    /* Active ring */
    .siblings__item.is-active{
      box-shadow: 0 0 0 2px rgba(0,0,0,0.85);
    }
  </style>
{% endif %}