Phase 4:
Metafields

Conditional Rendering of Product Metafields on the PDP

WinSport Theme · 3 Metafield Types · Defensive Rendering

What Are Metafields

3
Field Types
0
Broken If Blank
Products Supported

Metafields extend Shopify's product model with custom data. Most Shopify apps (reviews, sizing, subscriptions) store data as metafields — themes must read them defensively: render only when present, never break if missing.

  • Defined once in Admin → Settings → Custom Data
  • Filled per-product in Admin → Products → [product]
  • Read in Liquid via product.metafields.namespace.key.value

3 Field Types Used

boolean

is_new_arrival

True or false — renders a “New Arrival” pill badge above the product info

Renders: badge pill
New Arrival
number_integer

difficulty_rating

Integer 1–5 — renders a “Skill Level” row with filled & empty dots

Renders: ●●●○○ dots
Skill Level
multi_line_text

care_instructions

Long text — renders a collapsible “Care & Maintenance” accordion

Renders: expandable tab
Care & Maintenance ⌄

Before & After

Before — No Metafields
PDP before metafields
After — With Metafields
PDP after metafields

Admin Metafield Panel

Custom Data Definitions
Admin metafield definitions
Product Metafield Values
Admin product metafield values
  • Definitions created once in Settings → Custom Data → Products
  • Values filled per-product — different products can have different values
  • Products with no values → nothing renders, no empty space

Code Highlights

{# Safe access — never assume metafield exists #}
{%- assign is_new = product.metafields.custom.is_new_arrival.value -%}
{%- assign difficulty = product.metafields.custom.difficulty_rating.value -%}
{%- assign care = product.metafields.custom.care_instructions.value -%}

{# Boolean — compare to true, not truthiness #}
{%- if is_new == true -%}
  <span class="product-metafields__badge">New Arrival</span>
{%- endif -%}

{# Integer — dot loop using for range #}
{%- if difficulty != blank -%}
  {%- for i in (1..5) -%}
    {%- if i <= difficulty -%}<span class="dot--filled"></span>{%- else -%}<span class="dot"></span>{%- endif -%}
  {%- endfor -%}
{%- endif -%}

{# Text — newline_to_br preserves line breaks #}
{%- if care != blank -%}
  <div class="care-content">{{ care | newline_to_br }}</div>
{%- endif -%}

Key Takeaways

  • 3 value types — boolean, integer, and multi_line_text each require different render logic
  • Defensive rendering — every metafield is checked with != blank before output
  • Zero output when blank — products without metafields render no empty space, no broken layout
  • App-compatible pattern — same approach used for third-party app data (reviews, subscriptions, sizing)
  • Theme Customizer block — metafields block can be repositioned by merchants in the visual editor

WinSport Theme · Phase 4 Complete · Dawn v15.4.1 · Shopify 2.0