Obtaining Values from Metaobjects referenced in Metafields in Product Template

Solved

Obtaining Values from Metaobjects referenced in Metafields in Product Template

Maxplaining
Tourist
4 1 0

Problem Description:

I’m trying to access a metaobject’s fields directly in Liquid, but the fields are returning null, even though the metaobject is properly created and assigned.

Here are the details of my setup:

  1. Metafield Configuration:

    • Metafield: custom.primary_material
    • Type: Single metaobject reference
    • References: Metaobject of type material
  2. Metaobject Configuration:

    • Metaobject Type: material
    • Fields in Metaobject:
      • material.name (Name of the material)
      • material.description (Description of the material)
    • Status: The metaobject is set to Active in Shopify Admin.
  3. Liquid Code: I’m using the following Liquid code to access the metaobject fields:

    {% assign material = shop.metaobjects.material['teak'] %}
    
    <div>
      <h3>Debugging Material Metaobject</h3>
    
      {% if material %}
        <!-- Debug Metaobject Fields -->
        <p><strong>Raw Fields:</strong> {{ material.fields | json }}</p>
        <p><strong>Material Name:</strong> {{ material.fields['material.name'] }}</p>
        <p><strong>Material Description:</strong> {{ material.fields['material.description'] }}</p>
      {% else %}
        <p>No material metaobject found.</p>
      {% endif %}
    </div>
    1. Expected Behavior:

      • The metaobject with the handle teak exists in the material type.
      • I expect to see material.name and material.description fields populated in the rendered output.
    2. Actual Behavior:

      • The material metaobject is found (Raw Value: MetaobjectDrop), but material.fields returns null.
      • As a result, material.fields['material.name'] and material.fields['material.description'] are empty.

    Debugging Attempts:

    • Verified that the material metaobject type has fields material.name and material.description.
    • Ensured the metaobject handle (teak) is correct.
    • Set the metaobject status to Active.
    • Checked metafield assignment in the product, and it is referencing the correct metaobject.
    • Referred to this page for guidance: How can I access metaobject values in product metafields?.

    Full Debugging Output:

    Here’s the rendered output when I use the debugging code:

    Debugging Material Metaobject
    Raw Fields: null
    Material Name: 
    Material Description: 

     

    Additional Observations:

    • If I try to list all metaobjects of type material using:

      {% for material_entry in shop.metaobjects.material.values %}
        <p>Handle: {{ material_entry.system.handle }}</p>
      {% endfor %}

      It correctly displays the handle teak, confirming the metaobject exists.

    Question:

    1. Why is material.fields returning null even though the metaobject is set to Active and has fields configured?
    2. Is there something wrong with how I’m accessing the fields, or could there be an issue with the metaobject setup?

    MWE (Minimal Working Example):

    Here’s the code I’m using to directly access and debug the metaobject fields:

     

     

    {% assign material = shop.metaobjects.material['teak'] %}
    
    <div>
      <h3>Debugging Material Metaobject</h3>
    
      {% if material %}
        <!-- Debug Metaobject Fields -->
        <p><strong>Raw Fields:</strong> {{ material.fields | json }}</p>
        <p><strong>Material Name:</strong> {{ material.fields['material.name'] }}</p>
        <p><strong>Material Description:</strong> {{ material.fields['material.description'] }}</p>
      {% else %}
        <p>No material metaobject found.</p>
      {% endif %}
    </div>
    I now try to access a specific material but obviously this should be populated dynamically for each product.

    Context:

    • Theme: Custom theme (Next) using Custom Liquid blocks in Product Template.
    • Objective: To display material.name (and material.description) for the metaobject teak.
    • Extra: I can scale this for other metafields referencing metaobjects.

    What I Need Help With:

    1. Why are the fields returning null?
    2. Are there additional steps or configurations needed for accessing metaobject fields in Liquid?

    Any guidance or suggestions would be greatly appreciated. Thank you! 😊

    How can I create this product specification table?

Accepted Solution (1)
Maxplaining
Tourist
4 1 0

This is an accepted solution.

Solved my problem with below code:

<table class="product-specifications">
<thead>
<tr>
<th>Product Specificaties</th>
<th></th>
</tr>
</thead>
<tbody>
<!-- Materials (List of Metaobjects) -->
{% assign materials = product.metafields.custom.materials.value %}
{% if materials %}
<tr>
<td>Materials</td>
<td>
{% for material in materials %}
{{ material.name }}{% if forloop.last == false %}, {% endif %}
{% endfor %}
</td>
</tr>
{% else %}
<tr>
<td>Materials</td>
<td>No materials available for this product.</td>
</tr>
{% endif %}

<!-- Primary Material -->
{% assign primary_material = product.metafields.custom.primary_material.value %}
{% if primary_material %}
<tr>
<td>Primary Material</td>
<td>{{ primary_material.name }}</td>
</tr>
{% endif %}

<!-- Secondary Material -->
{% assign secondary_material = product.metafields.custom.secondary_material.value %}
{% if secondary_material %}
<tr>
<td>Secondary Material</td>
<td>{{ secondary_material.name }}</td>
</tr>
{% endif %}

<!-- Colors with Swatches -->
{% assign colors = product.metafields.shopify['color-pattern'].value %}
{% if colors %}
<tr>
<td>Colors</td>
<td>
{% for color in colors %}
<div style="display: flex; align-items: center; margin-bottom: 5px;">
<!-- Color Swatch -->
<div
style="width: 20px; height: 20px; border: 1px solid #ddd; background-color: {{ color.color }}; margin-right: 10px; border-radius: 50%;"
title="{{ color.label }}">
</div>
<!-- Color Name -->
<span>{{ color.label }}{% if forloop.last == false %}, {% endif %}</span>
</div>
{% endfor %}
</td>
</tr>
{% else %}
<tr>
<td>Colors</td>
<td>No colors available for this product.</td>
</tr>
{% endif %}

<!-- Stackable -->
{% assign stackable = product.metafields.custom.stackable.value %}
{% if stackable %}
<tr>
<td>Stackable</td>
<td>{{ stackable | capitalize }}</td>
</tr>
{% endif %}

<!-- Maximum Seats -->
{% assign maximum_seats = product.metafields.custom.maximum_seats.value %}
{% if maximum_seats %}
<tr>
<td>Maximum Seats</td>
<td>{{ maximum_seats }}</td>
</tr>
{% endif %}

<!-- Shipment Weight -->
{% assign shipment_weight = product.metafields.custom.shipment_weight.value %}
{% if shipment_weight %}
<tr>
<td>Shipment Weight</td>
<td>{{ shipment_weight }} kg</td>
</tr>
{% endif %}

<!-- Shape -->
{% assign shape = product.metafields.custom.shape.value %}
{% if shape %}
<tr>
<td>Shape</td>
<td>{{ shape.label }}</td>
</tr>
{% endif %}

<!-- Item Quantity -->
{% assign item_quantity = product.metafields.custom.item_quantity.value %}
{% if item_quantity %}
<tr>
<td>Item Quantity</td>
<td>{{ item_quantity }}</td>
</tr>
{% endif %}

<!-- Fabric Description -->
{% assign fabric_description = product.metafields.custom.fabric_description.value %}
{% if fabric_description %}
<tr>
<td>Fabric Description</td>
<td>{{ fabric_description }}</td>
</tr>
{% endif %}

<!-- Collection -->
{% assign collection = product.metafields.custom.collection.value %}
{% if collection %}
<tr>
<td>Collection</td>
<td>{{ collection }}</td>
</tr>
{% endif %}
</tbody>
</table>

View solution in original post

Replies 5 (5)

made4Uo
Shopify Partner
3877 719 1231

Hi @Maxplaining 

 

First, Shopify metaobject is object array type so we have to treat it as such. 

1. Call the metaobject values. This will return an array. I am assuming your metaobject name is material

 

{% assign materials = shop.metaobjects['material'].values %}

 

OR

{% assign materials = shop.metaobjects.material.values %}

 

 

2. Since the material is an array, we have to use iterations e.g. forloop, 

 

{% for material in materials %}
{{ material }}
{% endfor %}

 

 

3. Depending on what data you have under material e.g. richtext, file, product. You have to treat it differently. I would suggest to console log the values to understand the data

 

Below is the updated code

{% assign materials = shop.metaobjects.material.values %}

<div>
  <h3>Debugging Material Metaobject</h3>

  {% for material in materials %}
    <!-- Debug Metaobject Fields -->
    <p><strong>Raw Fields:</strong> {{ material.fields | json }}</p>   <!-- You might have to use forloop on this -->
    <p><strong>Material Name:</strong> {{ material.fields['material.name'] }}</p>  <!-- I am a little confuse what data do you have -->
    <p><strong>Material Description:</strong> {{ material.fields['material.description'] }}</p>
  {% endfor %}
</div>

 

If this fixed your issue Likes and Accept as Solution is highly appreciated. Coffee tips fuels my dedication.
Get EXPERIENCED Shopify developers at affordable rates—visit Made4Uo.com for quick quote!
Do not lost your Shopify store! Get FREE trial with ✔️ Rewind Backup: Automatic, reliable, stress-free
Maxplaining
Tourist
4 1 0

Hi @made4Uo 

I got the list of available materials to work, but for the actual items listed from that metaobject in the metafield on the product page it remains blank.

<div>
  <h3>Materials for This Product</h3>

  <!-- Access Primary Material -->
  {% assign primary_material = product.metafields.custom.primary_material.value %}
  {% if primary_material %}
    <div>
      <p><strong>Primary Material:</strong> {{ primary_material.name }}</p>
    </div>
  {% else %}
    <p>No primary material is selected for this product.</p>
  {% endif %}

  <!-- Access Secondary Material -->
  {% assign secondary_material = product.metafields.custom.secondary_material.value %}
  {% if secondary_material %}
    <div>
      <p><strong>Secondary Material:</strong> {{ secondary_material.name }}</p>
    </div>
  {% else %}
    <p>No secondary material is selected for this product.</p>
  {% endif %}
</div>

{% assign materials = shop.metaobjects.material.values %}

<div>
  <h3>Material List</h3>

  {% for material in materials %}
    <div>
      <!-- Access fields directly -->
      <p><strong>Material Name:</strong> {{ material.name }}</p>
      <p><strong>Material Description:</strong> {{ material.description }}</p>
    </div>
  {% endfor %}
</div>


 

Below are some screenshots for reference. 

 

Maxplaining_0-1737738819866.png

Maxplaining_2-1737738921203.pngMaxplaining_3-1737738950131.png

 

Maxplaining_1-1737738879913.png

 

 

made4Uo
Shopify Partner
3877 719 1231

Hi @Maxplaining 

 

Thank you for providing your structure. To call the metaobject with your structure, you can just add a value on the end of the product metafield

{% assign material = product.metafields.custom.primary_material.value %}

 

If this fixed your issue Likes and Accept as Solution is highly appreciated. Coffee tips fuels my dedication.
Get EXPERIENCED Shopify developers at affordable rates—visit Made4Uo.com for quick quote!
Do not lost your Shopify store! Get FREE trial with ✔️ Rewind Backup: Automatic, reliable, stress-free
Maxplaining
Tourist
4 1 0

Hello @made4Uo 

This now works for me on the correct product:

 

{% assign material = product.metafields.custom.primary_material.value %}

<div>
  {% if material %}
    <p>Primary Material: {{ material.name.value }}</p>
    
  {% endif %}
</div>

 


When I try another metaobject (list) with the loop: 

 

{% assign usps = product.metafields.custom.usp.value %}

<div>
  <h3>Unique Selling Points (USPs)</h3>

  <!-- Debug Raw Metafield -->
  <p><strong>Debug - Raw Value:</strong> {{ usps | json }}</p>

  {% if usps and usps.size > 0 %}
    <p><strong>Debug - Number of USPs:</strong> {{ usps.size }}</p>

    <!-- Iterate Through USPs -->
    {% for usp in usps %}
      <div>
        <span>
          <strong>USP Title:</strong> {{ usp.title.value }}
        </span>
      </div>
    {% endfor %}
  {% else %}
    <p>No unique selling points available for this product.</p>
  {% endif %}
</div>

 

 
I get this result:

Unique Selling Points (USPs)
Debug - Raw Value: [{"icon":["gid:\/\/shopify\/MediaImage\/46545862558019"],"title":"Teak","url":"https:\/\/cdn.shopify.com\/s\/files\/1\/0790\/2281\/7603\/files\/4so-icon_Teak.png?v=1714041306"},{"icon":["gid:\/\/shopify\/MediaImage\/46545862525251"],"title":"Rope","url":"https:\/\/cdn.shopify.com\/s\/files\/1\/0790\/2281\/7603\/files\/4so-icon_Rope_603ecc5d-7e7d-4f1d-8f24-1027f7eff26c.png?v=1714041306"},{"icon":["gid:\/\/shopify\/MediaImage\/46545862590787"],"title":"5 Year Warranty","url":"https:\/\/cdn.shopify.com\/s\/files\/1\/0790\/2281\/7603\/files\/4so-icon_5_jaar_garantie.png?v=1714041305"}]

No unique selling points available for this product.


How can I now make sure I get those entries in a formatted record so that I could build a specifications table from both metafields with their values and metafields referencing a metaobject (single or list)?

Maxplaining
Tourist
4 1 0

This is an accepted solution.

Solved my problem with below code:

<table class="product-specifications">
<thead>
<tr>
<th>Product Specificaties</th>
<th></th>
</tr>
</thead>
<tbody>
<!-- Materials (List of Metaobjects) -->
{% assign materials = product.metafields.custom.materials.value %}
{% if materials %}
<tr>
<td>Materials</td>
<td>
{% for material in materials %}
{{ material.name }}{% if forloop.last == false %}, {% endif %}
{% endfor %}
</td>
</tr>
{% else %}
<tr>
<td>Materials</td>
<td>No materials available for this product.</td>
</tr>
{% endif %}

<!-- Primary Material -->
{% assign primary_material = product.metafields.custom.primary_material.value %}
{% if primary_material %}
<tr>
<td>Primary Material</td>
<td>{{ primary_material.name }}</td>
</tr>
{% endif %}

<!-- Secondary Material -->
{% assign secondary_material = product.metafields.custom.secondary_material.value %}
{% if secondary_material %}
<tr>
<td>Secondary Material</td>
<td>{{ secondary_material.name }}</td>
</tr>
{% endif %}

<!-- Colors with Swatches -->
{% assign colors = product.metafields.shopify['color-pattern'].value %}
{% if colors %}
<tr>
<td>Colors</td>
<td>
{% for color in colors %}
<div style="display: flex; align-items: center; margin-bottom: 5px;">
<!-- Color Swatch -->
<div
style="width: 20px; height: 20px; border: 1px solid #ddd; background-color: {{ color.color }}; margin-right: 10px; border-radius: 50%;"
title="{{ color.label }}">
</div>
<!-- Color Name -->
<span>{{ color.label }}{% if forloop.last == false %}, {% endif %}</span>
</div>
{% endfor %}
</td>
</tr>
{% else %}
<tr>
<td>Colors</td>
<td>No colors available for this product.</td>
</tr>
{% endif %}

<!-- Stackable -->
{% assign stackable = product.metafields.custom.stackable.value %}
{% if stackable %}
<tr>
<td>Stackable</td>
<td>{{ stackable | capitalize }}</td>
</tr>
{% endif %}

<!-- Maximum Seats -->
{% assign maximum_seats = product.metafields.custom.maximum_seats.value %}
{% if maximum_seats %}
<tr>
<td>Maximum Seats</td>
<td>{{ maximum_seats }}</td>
</tr>
{% endif %}

<!-- Shipment Weight -->
{% assign shipment_weight = product.metafields.custom.shipment_weight.value %}
{% if shipment_weight %}
<tr>
<td>Shipment Weight</td>
<td>{{ shipment_weight }} kg</td>
</tr>
{% endif %}

<!-- Shape -->
{% assign shape = product.metafields.custom.shape.value %}
{% if shape %}
<tr>
<td>Shape</td>
<td>{{ shape.label }}</td>
</tr>
{% endif %}

<!-- Item Quantity -->
{% assign item_quantity = product.metafields.custom.item_quantity.value %}
{% if item_quantity %}
<tr>
<td>Item Quantity</td>
<td>{{ item_quantity }}</td>
</tr>
{% endif %}

<!-- Fabric Description -->
{% assign fabric_description = product.metafields.custom.fabric_description.value %}
{% if fabric_description %}
<tr>
<td>Fabric Description</td>
<td>{{ fabric_description }}</td>
</tr>
{% endif %}

<!-- Collection -->
{% assign collection = product.metafields.custom.collection.value %}
{% if collection %}
<tr>
<td>Collection</td>
<td>{{ collection }}</td>
</tr>
{% endif %}
</tbody>
</table>