{% comment %}
Linked Products block — SEO-friendly.
Renders sibling products of the current product as real, crawlable <a href>
links, server-side from the product metafield linked_products.group (written
by the app when a group is published). No JavaScript is required for the links
to exist in the HTML, so search engines crawl them and link equity flows
between the connected product pages.
{% endcomment %}
{%- assign raw = product.metafields.linked_products.group.value -%}
{%- if raw -%}
{%- comment -%} metafield type "json" gives us a parsed object in `raw`. {%- endcomment -%}
{%- assign members = raw.members -%}
{%- if members and members.size > 1 -%}
{%- assign swatch_size = block.settings.swatch_size | default: 36 -%}
<div class="lpx lpx--{{ raw.style | default: 'color' }}" style="--lpx-size: {{ swatch_size }}px;">
<div class="lpx__label">{{ raw.label | default: 'Color' }}:</div>
<div class="lpx__values">
{%- for m in members -%}
{%- assign is_current = false -%}
{%- if m.handle == product.handle -%}{%- assign is_current = true -%}{%- endif -%}
{%- capture inner -%}
{%- if raw.style == 'button' -%}
<span class="lpx__text">{{ m.value | default: m.title | escape }}</span>
{%- elsif raw.style == 'image' -%}
<span class="lpx__dot" style="background-image:url({{ m.image }}); background-size:cover;"></span>
{%- else -%}
<span class="lpx__dot" style="background:{{ m.color | default: '#ddd' }};"></span>
{%- endif -%}
{%- endcapture -%}
{%- if is_current -%}
<span class="lpx__swatch is-current" aria-current="true" title="{{ m.value | default: m.title | escape }}">
{{ inner }}
</span>
{%- else -%}
<a
class="lpx__swatch"
href="/products/{{ m.handle }}"
title="{{ m.value | default: m.title | escape }}"
aria-label="{{ m.title | escape }}"
>
{{ inner }}
</a>
{%- endif -%}
{%- endfor -%}
</div>
</div>
{{ 'linked.css' | asset_url | stylesheet_tag }}
{%- endif -%}
{%- endif -%}
{%- comment -%}
Collapse Shopify's app-block wrapper when this block renders nothing (no group
for the product), so an empty <div class="shopify-block"> can't add spacing or
break the layout. Scoped to THIS block's handle so other apps are unaffected.
The :has() rule hides the wrapper unless it actually contains our .lpx output.
{%- endcomment -%}
<style>
.shopify-app-block[data-block-handle="linked_products"]:not(:has(.lpx)) {
display: none !important;
}
</style>
{% schema %}
{
"name": "Linked Products",
"target": "section",
"settings": [
{
"type": "range",
"id": "swatch_size",
"label": "Swatch size",
"min": 20,
"max": 64,
"step": 2,
"unit": "px",
"default": 36
},
{
"type": "paragraph",
"content": "Shows links to connected products (configured in the Linked Products app). Renders server-side for SEO."
}
]
}
{% endschema %}