Display product metafield in collection product loop

BenPanda
New Member
8 0 0

I am wanting to display a product metafield within the product loop on a collection page, but haven't been able to get it to show.

On the product page I am using the following code to show the metafield:

   {% if product.metafields["global"]["Region"] != blank %}
      {{ product.metafields["global"]["Region"] }}
   {% endif %}

When I try and use the same code on the collection within the product loop template it doesn't work. Anybody any ideas what I need to change and if this is even doable?

0 Likes
Jason
Shopify Expert
10032 119 1871

It's doable. It's likely the reference to the product object is different. Got some code for how the products are output on the collection page at the moment - or even a website so we can guess the theme in place?

Check to see whether it uses the object name of product or something else.

Sidenote - you don't always need to bracket the namespace or key. You can just do this if you feel like typing a few less characters.

{{ product.metafields.global.Region }}

 

★ Winning Partner of the Build a Business competition. ★ http://freakdesign.com.au
BenPanda
New Member
8 0 0

Thanks Jason. 

I am usinga theme called Bootstrapify as I wanted to give it a go, but in hindsight probably wouldn't use it again. 

I've inculded code below showing the collection page, product list and product loop snippets, hopefully these are helpful. 

Here is the code for the collection page

{% include 'theme-variables' %}

{% if settings.collection-header-placement == 'above-products' %}
{% include 'collection-header' with collection %}
{% else %}
<div class="container">
  <h1 class="page-header">{{ page_title }}</h1>
</div>
{% endif %}

{{ collection_slider }}

{% include 'collection-nested' %}

{% unless hide_products %}
{% if collection.all_products_count == 0 %}
<section class="section-wrap noProducts">
	{% include '__containers-open' %}
	<p>Sorry, no {% include '__localize' with 'products' %} were found in the {{ collection.title }} collection.</p>
	{% include '__containers-close' %}
</section>
{% elsif collection.products_count == 0 %}
<section class="section-wrap">
	{% include '__containers-open' %}
	<h2>Whoops! You might need to broaden your search.</h2>
	<p>There {{ collection.all_products_count | pluralize: 'is', 'are' }}<strong> {{ collection.all_products_count | count }} {{ collection.all_products_count | pluralize: 'style', 'styles' }} of {% include '__localize' with 'Products' %}</strong> in the {{ collection.title }} collection&mdash;try removing some filters.</p>
	<ul>
		{% for tag in current_tags %}
		<li>{{ tag }} ({{ 'remove' | link_to_remove_tag: tag }})</li>
		{% endfor %}
	</ul>
	<p><br>Or, view <strong><a href="{{ collection.url }}">all {{ collection.all_products_count }} {% include '__localize' with 'Products' %} in the {{ collection.title }} {% include '__localize' with 'Collection' %}</a></strong>.</p>
	{% include '__containers-close' %}
</section>
{% else %}
{% if settings.tag-placement == 'main-content' or settings.show-product-sorter %}
<section id="collection-sort" class="section-wrap pull-right">
	{% include '__containers-open' %}
	<div class="clearfix">
		{% if settings.tag-placement == 'main-content' %}
		<div class="pull-left">
			{% include 'tag-buttons' %}
		</div>
		{% endif %}
      
      {% include 'collection-sort' %}
      
	</div>
	{% include '__containers-close' %}
</section>
{% endif %}

<section id="product-list" class="section-wrap">
{% assign is-product-list = true %}
{% include '__containers-open' %}
{% include '__default-pagination' %}
{% paginate collection.products by default-pagination %}
{% include 'products-list' %}
{% include 'pagination' %}
{% endpaginate %}
{% include '__containers-close' %}
</section>
{% endif %}
{% endunless %}

{% if settings.collection-header-placement == 'below-products' %}
{% include 'collection-header' with collection %}
{% endif %}

This then calls the product-list snippet:

<div class="row{% if thumbnail_layout == 'masonry' %} masonry-collection{% endif %}">
	{% if template contains 'index' %}
		{% if t_object != blank %}
			{% assign product_collection = t_object %}
		{% else %}
			{% assign product_collection = collections[settings.homepage-products-collection] %}
		{% endif %}
	{% elsif collection %}
		{% assign product_collection = collection %}
	{% endif %}
	{% if template contains 'index' or products-list == 'limit' %}
	  {% if settings.homepage-products-limit contains 'unlimited' %}{% assign limit = nil %}{% else %}{% assign limit = settings.homepage-products-limit %}{% endif %}
	{% endif %}
	{% for p in product_collection.products | limit: limit %}
		{% assign product_count = forloop.length %}
		{% include 'product-loop' with p %}
	{% endfor %}
</div>

and finally we have the product-loop where I am trying to place the metafield:

<div class="{% include '__thumbnail-span' %} {% for tag in product-loop.tags %}tag-{{ tag | downcase | handleize }} {% endfor %}{% if thumbnail_layout == 'masonry' %} masonry{% endif %}" {% include '__product-data-attr' with _product %}>
  <div class="product-thumbnail">
    <div class="thumbnail-image{% if product_collection.metafields.secondary-image.show == 'true' and product-loop.metafields.secondary-image.src != blank %} has-secondary-image{% endif %}">
      {% include '__product-image' %}
    </div>
    <a href="{{ product_url }}" class="caption clearfix">
      {% if settings.show-vendor-with-thumbnail == 'above-product-title' %}<div class="product-vendor">{{ product-loop.vendor }}</div>{% endif %}
      <h4 class="product-title">{{ product-loop.title }}</h4>
      {% if settings.show-vendor-with-thumbnail == 'below-product-title' %}<div class="product-vendor">{{ product-loop.vendor }}</div>{% endif %}
      <div class="shopify-product-reviews-badge" data-id="{{ product-loop.id }}"></div>
         
      <div class="productMetafield">
		{{ product.metafields.global.Region }}
      </div>
           
      {% if has_prices and product-loop.price > 0 %}
      <div class="product-price">
        {% if settings.show-compare-at-price and product-loop.compare_at_price > 0 %}	
          {% capture was %}
          {% include '__localize' with 'was' %}
          <span class="money">
          {% if settings.show-currency-with-prices == "with-currency" %}
          {{ product-loop.compare_at_price_max | money_with_currency }}
          {% else %}
          {{ product-loop.compare_at_price_max | money }}
          {% endif %}
          </span>
          {% endcapture %}
        <small class="text-muted"><del>{{ was | strip }}</del></small>&nbsp;
        {% elsif product-loop.price_varies %}
        <small class="text-muted">
          {% include '__localize' with 'from' %}
        </small>
        {% endif %}
				
				{% include '__poa-tag' with product-loop %}
				{% if price_is_poa %}
				<span>{% include '__localize' with 'POA' %}</span>
				{% else %}
				{% include 'product-price' with product-loop.price %}
				{% endif %}
				{% include 'product-labels' with product-loop %}
			</div>
			{% endif %}
		</a>

    {% if settings.show-stock-availability-on-collection %}
    <div class="product-deal">
      <div class="product-availability">
    		{% include 'product-availability' with product-loop %}
      </div>
      {% if product-loop.metafields.inventory.ShappifySaleEndDate %}
      <div class="sale-clock">
        {% include 'shappify-sales-clock' with product-loop %}
      </div>
      {% endif %}
    </div>
		{% endif %}

		{% if settings.quick-cart %}
		<div class="quick-cart">
		  <div class="quick-cart-btn-wrapper">
		    <form id="{% include '__advanced-layout-id' with 'product-form' %}" action="/cart/add" method="post" role="form" enctype="multipart/form-data">
		      <input type="hidden" name="id" value="{{ product-loop.selected_or_first_available_variant.id }}" />
		      <input type="hidden" name="quantity" value="1" />
		      <input type="submit" name="add" value="{% include '__localize' with 'Buy' %}" id="purchase" class="quick-cart-btn add-to-cart" />
		    </form>
		  </div>
		</div>
		{% endif %}
	</div>
</div>

 

0 Likes
Jason
Shopify Expert
10032 119 1871

Knowing the theme and seeing your code helps. It's an older open source theme by the Lucid team in NZ. Not a bad starter theme if it covers your needs.

A little context is needed first. When you include a snippet you have the option to pass along variables. More info on that here but it can be done in two ways:

  1. using the with statement
  2. or appending the variables with a key:value notation

This theme uses with. When you do that the actual snippet name is used as the variable name. In this case that's product-loop. You get a clue in the snippet itself where it's pulling in the title:

{{ product-loop.title }}

So the default product object has now been cloned to a new object called product-loop. Just change your metafield reference and you should be good to go.

{{ product-loop.metafields.global.Region }}

 

★ Winning Partner of the Build a Business competition. ★ http://freakdesign.com.au
0 Likes
BenPanda
New Member
8 0 0

Thanks very much Jason, that has worked now and in hindsight I should have seen that was what I needed to do. 

You contribution here and to the community in general is very much appreciated! 

0 Likes
johnlfitz
New Member
1 0 0

I have a similar quandry.  I'm building a personalised gifts website - see https://www.giftsfinder.co.uk/products/24-sleeps-til-christmas-personalised-book as an example.

There's thousands of products, and for each I'm going to be uploading (via Excelify) all the various different product personalisation details, using a custom "personalised" namespace for custom metafield data to store and control the capturing of the personalised gifts data from the customer.

For example, a personalised calendar might have:

Name
Message line 1:
Message line 2:
Message line 3:
Message line 4:
Message line 5:

The data in each of the fields would be the number of characters permissable for that given field.  So, "Name" above would have "12" as the data for a https://www.giftsfinder.co.uk/products/24-sleeps-til-christmas-personalised-book.  I want to have a nested query that combines the basic code here to use the data to capture the personalisation fields as per the metafields that exist for that product and use the data in that product to control the number of characters that the customer is allowed to type in, for each field that exists.

To prove my theory works I've setup https://www.giftsfinder.co.uk/products/24-sleeps-til-christmas-personalised-book to write out the metafields for this product using this code:

<div class="line-item-property__field">
<label for="name">Name</label>
<input required class="required" id="name" type="text" name="properties[Name]">
</div>

<ul>
{% for field in product.metafields.personalisation %}
<li>{{ field | first }}: {{ field | last }}</li>
{% endfor %}
</ul>

What I need is code that is a nested bit of script that displays the fields one by one for the personalisation, but uses perhaps javascript to countdown and restrict the number of characters based on the data held in that field, similar to https://www.personalise.co.uk/personalised-i-d-pick-you-glass-vase.html where it shows how many characters (space) you have left to type ....

So above would be 1 type of product customisation.  Another product might be an wedding champagne flute, which could have:

Wedding date:
Bride's name:
Groom's name:

Any ideas on the script?  I just can't work out the code to do this nested query and namespace data control to capture the data from the customer.

0 Likes