Display only unique product metafields in email

Topic summary

A user is working on customizing an email template to display product metafields for class instructors. The challenge is preventing duplicate instructor information when a customer purchases multiple classes with the same instructor.

Original Approach:

  • Manually hardcoding instructor names (e.g., “James”) to check for duplicates
  • Not scalable as more instructors are added

Solution Provided:
Another user suggested using a trainers_rendered variable to track which instructors have already been displayed:

  • Creates an empty string to store rendered trainer names
  • Uses unless trainers_rendered contains to check if trainer was already shown
  • Appends each new trainer name to the tracking variable
  • Eliminates need for manual name entry

Outcome:
The solution worked after removing .value from the metafield reference. The original poster plans to incorporate metaobjects once granted access (expected next week), which would provide better data management for trainer information and more unique identifiers (like Instagram handle + name) to avoid ambiguity issues with similar names.

Summarized with AI on November 13. AI used: claude-sonnet-4-5-20250929.

Looking for an alternative way of displaying the information below. If the customer purchases multiple classes with the same instructor, (ex. James), I want James’ information to display only once. The code I have below works, though ideally, I would like to avoid having to manually input ‘James’, and rely solely on liquid to determine if the metafield has repeated. There are multiple instructors, and more will be added in the future. I’ve been playing with code all day, and haven’t found a solution. If you have any solutions to offer, I’m all ears! Thank you.

{% assign count = 0 %}
    {% for line in line_items %}
      {% if line.product.metafields.custom.trainer contains "James" and count < 1 %}

      {% assign url = line.product.metafields.custom.address_url %}
      {% assign trainer = line.product.metafields.custom.trainer %}
      {% assign bio = line.product.metafields.custom.trainer_bio %}
      {% assign handle = line.product.metafields.custom.instagram_handle %}
      {% assign image = line.product.metafields.custom.trainer_image %}

        {% assign count = count | plus: 1 %}

        

        {% elsif count == 1 %}
        {% break %}
      {% endif %}
    {% endfor %}

Hi @meganatmetro What you’ve go so far is great like you’ve avoided the count reset trap.

In this sample you might not even need to count:

{%- assign trainers_rendered = '' -%}
{%- for line in line_items -%}
  {% if line.product.metafields.custom.trainer %}
    {% unless trainers_rendered contains line.product.metafields.custom.trainer.value %}
      {%- comment -%}content here{%- endcomment -%}

      {%- assign trainers_rendered = trainers_rendered | append: line.product.metafields.custom.trainer.value | append:"," -%}
      {% assign count = count | plus: 1 %}
    {% endunless %}
  {% endif %}
{%- endfor %}

:bomb: Do note how string matching can introduce string ambiguity problems i.e. James will match Jameson, etc. So using name + instragram handle would probably be a better unique identifier.

For managing sets of related data, like a trainers info, you may want to look at metaobjects.

metaobjects also can automatically generate a page with entries.

https://help.shopify.com/en/manual/custom-data/metaobjects

Liquid usage basics https://shopify.dev/docs/api/liquid/objects/metaobject

With the exception that I had to remove ‘.value’ from 'line.product.metafields.custom.trainer.value’, this works perfectly!!! :glowing_star: Thank you so much for your input! As far as the ambiguity problems, the metafields do also include the trainers last name, which I just didn’t include in the clip, and should hopefully be specific enough that it prevents any issues.

I do plan on incorporating metaobjects as soon as I’m granted access, which won’t happen until next week. However, this solution still works for other parts of the code that I didn’t include in this clip! Thanks again!! :slightly_smiling_face: