the app-free approach
Product tab apps ($5–$15/month) do two things: store tab content and render it. You can do both with metafields and a snippet. The result is faster, has no third-party JS, and works on every OS 2.0 theme.
setting up metafields
Go to Settings → Custom data → Products and create metafields for each tab:
custom.size_guide— rich text or filecustom.shipping_info— rich textcustom.returns_policy— rich text
the liquid snippet
{% assign tabs = '' | split: '' %}
{% if product.description != blank %}{% assign tabs = tabs | push: 'description' %}{% endif %}
{% if product.metafields.custom.size_guide != blank %}{% assign tabs = tabs | push: 'size guide' %}{% endif %}
{% if product.metafields.custom.shipping_info != blank %}{% assign tabs = tabs | push: 'shipping' %}{% endif %}
<div class="tabs">
{% for tab in tabs %}
<button class="tab-btn{% if forloop.first %} active{% endif %}"
data-tab="{{ tab | handle }}">{{ tab }}</button>
{% endfor %}
</div>
tab content panels
For each tab, render a <div data-panel="tab-handle"> with the corresponding content. Use a small JS function to toggle the active class on click. Total JS: under 10 lines.
performance note
All tab content renders in the initial HTML response — no AJAX, no lazy loading. This means full SEO visibility for all tab content and no layout shift on tab switch.