Розробка кастомної теми Shopify (Liquid)
Кастомна тема — це коли жодна з тем Theme Store не підходить по дизайну, структурі або продуктивності. Розробка на Liquid — шаблонізаторе Shopify — в зв'язці з CSS (зазвичай Tailwind або BEM) і Vanilla JS / Alpine.js.
Online Store 2.0 — обов'язковий стандарт
Усі сучасні теми будуються на архітектурі OS 2.0. Ключові відмінності від legacy-тем:
-
JSON-шаблони замість Liquid-шаблонів для сторінок (
templates/product.json,templates/collection.json) - Sections Everywhere — секції можна додавати на будь-яку сторінку, не тільки на головну
- Blocks всередині секцій — вкладена структура з редагуванням у Theme Editor
- app blocks — приложення вбудовуються через офіційний App Extension, не хардкодом
Структура файлів теми:
theme/
├── assets/ # CSS, JS, зображення, шрифти
├── config/ # settings_schema.json, settings_data.json
├── layout/ # theme.liquid, password.liquid
├── locales/ # переводи рядків
├── sections/ # .liquid файли секцій
├── snippets/ # переиспользуемі фрагменти
└── templates/ # .json шаблони сторінок
Секція — основна одиниця
Секція — це .liquid файл в /sections/ з обов'язковим {% schema %} блоком:
{%- comment -%} sections/product-hero.liquid {%- endcomment -%}
<div class="product-hero" style="--accent: {{ section.settings.accent_color }}">
{% for block in section.blocks %}
{% case block.type %}
{% when 'title' %}
<h1 class="product-hero__title">{{ product.title }}</h1>
{% when 'price' %}
<div class="product-hero__price">
{{ product.selected_or_first_available_variant.price | money }}
</div>
{% when 'add_to_cart' %}
<button
type="submit"
form="product-form-{{ section.id }}"
class="btn btn--primary"
{% unless product.available %}disabled{% endunless %}
>
{{ block.settings.button_text | default: 'У кошик' }}
</button>
{% endcase %}
{% endfor %}
</div>
{% schema %}
{
"name": "Product Hero",
"tag": "section",
"class": "section-product-hero",
"settings": [
{
"type": "color",
"id": "accent_color",
"label": "Акцентний колір",
"default": "#0066cc"
}
],
"blocks": [
{ "type": "title", "name": "Назва товару", "limit": 1 },
{
"type": "price",
"name": "Ціна",
"limit": 1
},
{
"type": "add_to_cart",
"name": "Кнопка «У кошик»",
"limit": 1,
"settings": [
{
"type": "text",
"id": "button_text",
"label": "Текст кнопки",
"default": "У кошик"
}
]
}
],
"presets": [
{
"name": "Product Hero",
"blocks": [
{ "type": "title" },
{ "type": "price" },
{ "type": "add_to_cart" }
]
}
]
}
{% endschema %}
Робота з даними Shopify в Liquid
Основні об'єкти, доступні в шаблонах:
{%- comment -%} Варіант товару з URL-параметром {%- endcomment -%}
{%- assign current_variant = product.selected_or_first_available_variant -%}
{%- comment -%} Коллекція з сортуванням {%- endcomment -%}
{%- assign sorted_products = collection.products | sort: 'price' -%}
{%- comment -%} Метаполя {%- endcomment -%}
{%- assign delivery_days = product.metafields.custom.delivery_days.value -%}
{%- comment -%} Покупець {%- endcomment -%}
{%- if customer -%}
Привіт, {{ customer.first_name }}!
{%- endif -%}
JavaScript у темі
Shopify не навязує фреймворк. Рекомендований підхід у 2024–2025 — Web Components або Alpine.js для інтерактивності без важкого бандла:
// assets/product-form.js
class ProductForm extends HTMLElement {
connectedCallback() {
this.form = this.querySelector('form');
this.submitButton = this.querySelector('[type="submit"]');
this.form.addEventListener('submit', this.onSubmit.bind(this));
}
async onSubmit(event) {
event.preventDefault();
this.submitButton.setAttribute('disabled', '');
const formData = new FormData(this.form);
const response = await fetch('/cart/add.js', {
method: 'POST',
body: formData
});
if (!response.ok) {
const error = await response.json();
console.error('Cart error:', error.description);
return;
}
document.dispatchEvent(new CustomEvent('cart:item-added', {
detail: await response.json()
}));
this.submitButton.removeAttribute('disabled');
}
}
customElements.define('product-form', ProductForm);
Продуктивність теми
Lighthouse Score — непрямий фактор ранжирування і прямий фактор конверсії. Типові проблеми кастомних тем та їх рішення:
Render-blocking скрипти — усі сторонні скрипти тільки з defer або async. Вбудовані скрипти теми — в кінці </body> або через DOMContentLoaded.
Неоптимізовані зображення — Shopify CDN обробляє через URL-параметри:
{{ product.featured_image
| image_url: width: 800
| image_tag:
loading: 'lazy',
widths: '400, 800, 1200',
sizes: '(max-width: 768px) 100vw, 50vw'
}}
Надлишковий CSS — розподіл критичного і некритичного. Критичний inline у <head>, некритичний з rel="preload" і onload.
Font loading — preconnect + font-display: swap:
{%- comment -%} У layout/theme.liquid <head> {%- endcomment -%}
<link rel="preconnect" href="https://fonts.shopifycdn.com" crossorigin>
Інструменти розробки
# Shopify CLI 3.x
npm install -g @shopify/cli
# Запуск локального сервера з hot-reload
shopify theme dev --store=mystore.myshopify.com --live-reload=hot-reload
# Пуш змін на стейджинг-тему
shopify theme push --theme=THEME_ID
# Створення нового проекту теми на базі Dawn
shopify theme init my-custom-theme
Збірка CSS і JS — зазвичай Vite або webpack, результати копіюються в /assets/. Shopify CLI не замінює бандлер — тільки синхронізує файли з магазином.
Тестування
- Функціональне: перевірка кошика, чекауту, фільтрів через браузер
- Кросс-браузерне: Chrome, Firefox, Safari (особливо iOS Safari — свої баги)
- Продуктивність: Lighthouse в режимі інкогніто, WebPageTest з throttling 4G
- Theme Check — лінтер від Shopify:
shopify theme check
# Перевіряє: застарілі фільтри, відсутність alt у зображень,
# неправильні посилання на ассеті, проблеми з перекладами
Терміни
Кастомна тема з нуля по готовому дизайну (до 15 типів сторінок): 3–6 тижнів. Кастомізація існуючої теми під брендбук з збереженням оновлюваності: 1–2 тижні. Рефакторинг legacy-теми в OS 2.0: 2–3 тижні.







