k-sync
Zurück zum Blog

Shopify theme customization for WooCommerce developers (2026)

How WooCommerce developers customize Shopify themes — Liquid syntax, theme sections, settings schema, Dawn architecture, overriding theme defaults, and porting WooCommerce template customizations to Shopify.

·Von k-sync
6 Min. Lesezeit · 1,182 Wörter

WooCommerce developers customizing storefronts used PHP template overrides, hooks, and filters — replacing woocommerce/templates/ files in the child theme and hooking into woocommerce_before_add_to_cart_button and similar action hooks. Shopify's equivalent is the Liquid template system with a completely different architecture. This guide maps WooCommerce developer patterns to their Shopify Liquid equivalents.

WooCommerce template system vs Shopify Liquid

ConceptWooCommerceShopify
Template languagePHPLiquid (Ruby-based)
Template overridesCopy to child-theme/woocommerce/Edit theme files directly (or use theme app extension)
Action hooksadd_action('woocommerce_before_add_to_cart_button', ...)No hook system — edit Liquid files directly
Filter hooksadd_filter('woocommerce_product_title', ...)No filter system — logic in Liquid or app embed
Dynamic sectionsPHP partial + AJAXLiquid sections + Section Rendering API
Theme settingsWordPress customizerShopify Theme Editor (settings_schema.json)
Metafields in templatesget_post_meta() in PHPproduct.metafields.namespace.key in Liquid
Conditional logicPHP if/else/foreachLiquid if/unless/for
SCSS/CSSChild theme style.cssassets/theme.css or inline CSS in sections
JavaScriptwp_enqueue_script() in functions.phpassets/*.js referenced in layout/theme.liquid or section files

Liquid syntax basics

Variables and output

{{ product.title }}
{{ product.price | money }}
{{ product.description }}
{{ product.metafields.sizing.fit_notes }}

Control flow

{% if product.available %}
  <button>Add to cart</button>
{% else %}
  <p>Sold out</p>
{% endif %}

{% for variant in product.variants %}
  <option value="{{ variant.id }}">{{ variant.title }} — {{ variant.price | money }}</option>
{% endfor %}

{% unless product.tags contains 'sale' %}
  <!-- not on sale -->
{% endunless %}

Filters (equivalent to WordPress/WooCommerce filters but built-in)

{{ product.price | money }}                    {# £29.99 #}
{{ product.title | upcase }}                   {# PRODUCT TITLE #}
{{ 'image.jpg' | asset_url | img_tag }}        {# <img src="cdn.shopify.com/..." #}
{{ product.description | strip_html | truncate: 150 }}
{{ collection.products | sort: 'title' }}

Dawn theme architecture

Dawn is Shopify's reference theme (free, open source). Understanding its structure maps to WooCommerce child theme structure:

dawn/
├── assets/              ← CSS, JS, fonts, images (all served as-is from CDN)
├── config/
│   ├── settings_schema.json   ← Theme Editor controls (like WordPress customizer)
│   └── settings_data.json     ← Saved theme setting values
├── layout/
│   ├── theme.liquid     ← Global layout (like WP header.php + footer.php + wp_head())
│   └── password.liquid  ← Pre-launch password page layout
├── locales/             ← i18n translation strings
├── sections/            ← Reusable, configurable page sections (draggable in editor)
├── snippets/            ← Reusable Liquid partials (like WP template-parts)
└── templates/           ← Page templates
    ├── product.json     ← Product page template (references sections)
    ├── collection.json  ← Collection page template
    ├── index.json       ← Home page template
    ├── cart.json
    ├── page.json
    └── page.about.json  ← Custom template for specific pages

Sections and blocks

Sections are the core building block of Shopify themes — merchant-editable, draggable regions. Each section has a {% schema %} block that defines its settings:

{%- comment -%} sections/product-badges.liquid {%- endcomment -%}

<div class="product-badges">
  {% if section.settings.show_sale_badge and product.compare_at_price > product.price %}
    <span class="badge badge--sale">{{ section.settings.sale_text }}</span>
  {% endif %}
  {% if section.settings.show_new_badge and product.tags contains 'new' %}
    <span class="badge badge--new">New</span>
  {% endif %}
{% for block in section.blocks %}
  {% if block.type == 'custom_badge' %}
    <span class="badge" style="background: {{ block.settings.color }}">{{ block.settings.text }}</span>
  {% endif %}
{% endfor %}
</div>

{% schema %}
{
  "name": "Product Badges",
  "settings": [
    { "type": "checkbox", "id": "show_sale_badge", "label": "Show sale badge", "default": true },
    { "type": "checkbox", "id": "show_new_badge", "label": "Show new badge", "default": false },
    { "type": "text", "id": "sale_text", "label": "Sale badge text", "default": "Sale" }
  ],
  "blocks": [
    {
      "type": "custom_badge",
      "name": "Custom Badge",
      "settings": [
        { "type": "text", "id": "text", "label": "Badge text" },
        { "type": "color", "id": "color", "label": "Badge colour", "default": "#c0392b" }
      ]
    }
  ]
}
{% endschema %}

Snippets (replaces WooCommerce template partials)

Snippets are reusable Liquid partials — the equivalent of WooCommerce template parts and wc_get_template_part():

{%- comment -%} snippets/product-card.liquid {%- endcomment -%}
{%- assign product = product_card_product -%}

<div class="product-card">
  <a href="{{ product.url }}">
    {{ product.featured_media | image_url: width: 600 | image_tag: class: 'product-card__image', loading: 'lazy', alt: product.featured_media.alt }}
  </a>
  <div class="product-card__info">
    <h3>{{ product.title }}</h3>
    <span class="product-card__price">{{ product.price | money }}</span>
  </div>
</div>

{%- comment -%} Usage in a section: {%- endcomment -%}
{% render 'product-card', product_card_product: product %}

Theme settings (settings_schema.json)

Theme settings define global controls visible in the Theme Editor — equivalent to WordPress customizer settings:

// config/settings_schema.json (excerpt)
[
  {
    "name": "Brand",
    "settings": [
      { "type": "color", "id": "accent_color", "label": "Accent colour", "default": "#3a8c9c" },
      { "type": "font_picker", "id": "heading_font", "label": "Heading font", "default": "helvetica_n4" },
      { "type": "checkbox", "id": "show_announcement_bar", "label": "Show announcement bar", "default": false },
      { "type": "text", "id": "announcement_text", "label": "Announcement text" }
    ]
  }
]

Access in Liquid: {{ settings.accent_color }}, {{ settings.announcement_text }}

Adding custom CSS

WooCommerce developers added CSS in child theme style.css or via WordPress customizer custom CSS. Shopify equivalent:

Adding custom JavaScript

{%- comment -%} In layout/theme.liquid, before </body> {%- endcomment -%}
<script src="{{ 'custom.js' | asset_url }}" defer="defer"></script>

{%- comment -%} In a section, event listeners scoped to section {%- endcomment -%}
<script>
document.addEventListener('DOMContentLoaded', function() {
  var section = document.getElementById('shopify-section-{{ section.id }}');
  // section-scoped JavaScript
});
</script>

Displaying metafields in templates

WooCommerce used get_post_meta($product_id, 'custom_field', true) in PHP templates. Shopify Liquid:

{% comment %} In snippets/product-metafields.liquid {% endcomment %}
{% if product.metafields.sizing.fit_notes != blank %}
  <div class="fit-notes">
    <h3>Fit guide</h3>
    <p>{{ product.metafields.sizing.fit_notes }}</p>
  </div>
{% endif %}

{% if product.metafields.bike.frame_material != blank %}
  <dl class="bike-specs">
    <dt>Frame</dt>
    <dd>{{ product.metafields.bike.frame_material }}</dd>
    <dt>Weight</dt>
    <dd>{{ product.metafields.bike.weight_kg }}kg</dd>
  </dl>
{% endif %}

Theme development workflow

Developer migration checklist

The biggest mindset shift from WooCommerce to Shopify theme development is moving from hooks to direct edits. WooCommerce encouraged never editing plugin templates — use hooks to inject code around them. Shopify has no hook system; you edit Liquid files directly. This is simultaneously simpler (you see exactly what renders) and more fragile (theme updates can overwrite edits). The mitigation is Shopify's theme versioning: always work in a development theme, commit changes to version control, and review diffs before applying theme updates to ensure your customizations survive.

Verwalten Sie Ihre Produkte mit k-sync

Verbinden Sie Ihren Shop, validieren Sie Produkte, optimieren Sie mit KI und pushen Sie zu Shopify in Minuten. Kostenlos bis zu 50 Produkte.

Kostenlos starten

Weitere Artikel

Alle Migrationsanleitungen ansehen