Справочник темы
Панель темы
Страница настроек: WP Admin → Внешний вид → Theme Settings (всегда доступна).
Разделы
- Admin Panel — Gutenberg переключатель, админ-бар, виджеты дашборда
- Security — XML-RPC, REST API, скрытие версии, URL входа
- Extensions — Обработчик форм, SMTP, Telegram, reCAPTCHA
- WooCommerce — Настройки WooCommerce
- Theme Settings — Бэкенд полей (SCF/ACF), инструменты миграции
- Search — Настройки страницы поиска
Запросы
Создавайте многоразовые выборки WP_Query / get_terms(). Используйте их двумя способами: вызывайте пресет запроса из PHP-шаблона или привязывайте «Custom Query» к элементу-циклу прямо через HTML-атрибуты.
Из PHP-шаблона (Query Presets)
Создайте пресет в под-вкладке Post/Term Query Presets, задайте Query Code и вызывайте его в коде шаблона:
- Posts:
$q = new WP_Query(tf_get_query('your-code')); - Terms:
$terms = tf_get_term_query('your-code'); - Auto-apply: привяжите пресет к архиву типа записи или таксономии на вкладке «Auto-apply», и он автоматически переопределит основной запрос (через pre_get_posts) — без правки шаблона.
Через HTML-атрибуты (Custom Queries)
Назовите запрос в под-вкладке Custom Queries / Term Queries, затем сошлитесь на него на элементе-цикле — или впишите аргументы прямо в атрибут. Шаблоном повторения служит только первый дочерний элемент.
- По имени:
<div wp-select="catalog"> … </div>(псевдоним:wp-query-name) - Инлайн:
<div wp-query="'post_type'=>'product','posts_per_page'=>8"> - Список термов:
<div wp-term-query="'taxonomy'=>'product_cat','parent'=>0">·wp-term-select="name" - WooCommerce:
<div wp-product-query="get_related_products(4)">
Внутри цикла — поля
На элементах внутри цикла выводите значения через атрибуты WordPress или атрибуты полей ACF/SCF:
- WordPress:
wp="post-title",wp="post-image",wp="post-link",wp="term-title",wp="term-link" - ACF / SCF:
fld-text,fld-image,fld-link,fld-loop(альтернативный формат:f_text,f_image,f_loop)
Совместимость
Рантайм читает три источника по приоритету: пресеты TF, затем Query Master (старые импортированные сайты), затем запросы устаревшего конфигуратора. Новые пресеты всегда сохраняются в хранилище TF; существующие данные продолжают работать.
Произвольные типы записей и таксономии
Регистрируйте произвольные типы записей и таксономии прямо из панели — каждая строка повторителя соответствует вызову регистрации WordPress, код не нужен.
Произвольные типы записей
Каждая строка соответствует register_post_type(). Поле «Name» — это ключ типа записи (строчные латинские буквы, без пробелов). Задайте множественное/единственное/меню-название, иконку Dashicons, поддерживаемые возможности (заголовок, редактор, миниатюра, …), URL-слаг архива, REST/Gutenberg, публичную доступность, тумблер «Публичный архив» (выключите ленту /slug/ для служебных типов) — и необязательную «Страницу разводящей», которая делает архив редактируемым (см. раздел «Разводящие страницы архивов» ниже).
Произвольные таксономии
Каждая строка соответствует register_taxonomy(). Выберите «Иерархическая» (как категории) или «Плоская» (как метки), свяжите с одним или несколькими типами записей и задайте слаг и видимость в REST.
Как они связаны
Новые типы записей и таксономии автоматически появляются в выпадающих списках пресетов запросов. Постоянные ссылки обновляются при сохранении. Шаблоны следуют соглашениям WordPress: single-{type}.php, archive-{type}.php, taxonomy-{taxonomy}.php.
Разводящие страницы архивов
URL архива (блог, каталог магазина, архив произвольного типа записей) выводит СПИСОК записей — собственной страницы у него нет, поэтому обычно на нём нечего редактировать. ThemeForge даёт каждому архиву разводящую страницу: настоящую страницу из списка «Страницы», поля которой становятся редактируемым содержимым архива (заголовок-«герой», вводный текст, изображения, SEO), при этом сама лента продолжает выводить список. Редактор меняет архив так же, как любую другую страницу.
Как это работает
На архивной странице вашего Webflow-проекта (archive-post, archive-product, archive-{type}) разместите атрибуты полей ВНЕ цикла списка — то есть вне элемента с меткой wp="posts" / wp="products". Такие поля автоматически прикрепляются к разводящей странице в админке и выводятся с неё на URL архива.
- Вне цикла работает любое одиночное поле: fld-text, fld-image, fld-link, fld-bg-image, fld-editor и остальное семейство fld-*, а также wp="post-title" и wp="post-content" — они печатают заголовок и содержимое самой разводящей страницы.
- Поля ВНУТРИ цикла сохраняют обычный смысл: они читают каждую выводимую запись, как и раньше.
- На мультиязычных сайтах разводящая страница определяется для каждого языка автоматически (Polylang / WPML): каждая локаль редактирует свой перевод разводящей.
- SEO: для архивов произвольных типов записей разводящая страница также питает Yoast — архив получает её SEO-заголовок и корректный canonical, включая страницы пагинации.
Блог
Разводящая блога — это родная «Страница записей» WordPress. Создайте страницу (например /blog/), назначьте её в Настройки → Чтение, и поля, размещённые вне цикла на шаблоне archive-post, прикрепятся к этой странице — дополнительной настройки не нужно.
archive-postКаталог WooCommerce
Каталог магазина использует страницу «Магазин» WooCommerce как разводящую. Поля вне цикла товаров на шаблоне archive-product прикрепляются к странице магазина и выводятся на URL каталога.
archive-productПроизвольные типы записей
У архива произвольного типа записей в WordPress нет родной разводящей, поэтому её добавляет ThemeForge: создайте страницу, URL которой совпадает со слагом архива (например /portfolio/ для типа со слагом архива «portfolio»), затем выберите её в строке этого типа в панели темы. URL архива продолжает выводить шаблон ленты, а выбранная страница несёт его редактируемые поля. Если архивный шаблон вашего Webflow-проекта объявляет группу полей, ThemeForge создаёт (или усыновляет) разводящую автоматически — на всех языках сайта, так же как WooCommerce создаёт свою страницу «Магазин».
archive-{type}Привязанная страница ВЛАДЕЕТ URL архива: переименуйте страницу — и архив переедет вместе с ней (поле слага скрывается, пока страница привязана). Без привязанной страницы слаг берётся из панели темы. Сама страница напрямую никогда не показывается — она поверхность редактирования позади архива.
Полезно знать
- Групповые поля вне цикла (повторитель, группа, flexible content, галерея) читаются с разводящей так же, как одиночные. Единственное исключение — группа с loop-mode="0": вкладка «Логи» проекта помечает её как «archive-scope-unsupported».
- Поле, размещённое ВНУТРИ цикла списка, принадлежит выводимым записям — объявите его на соответствующем шаблоне single-{type}, чтобы оно появилось на экранах редактирования этих записей.
- Если разводящая не настроена, ничего не ломается: архив выводится ровно как раньше. Добавить разводящую можно в любой момент без перегенерации темы.
Расширение форм
Встроенная обработка форм с SMTP, Telegram, валидацией и хранением заявок.
Возможности
- SMTP отправка email (по умолчанию: smtp.gmail.com:465/SSL)
- reCAPTCHA v3 / v2
- Telegram уведомления
- Защита от спама без ключей — включена на новых сайтах
- Автоответ отправителю формы
- JustValidate клиентская валидация
- CPT
tf_form_entry— хранение заявок в WordPress - CSV экспорт
Защита от спама
Работает без ключей и внешних сервисов. На новом сайте включена сразу; на сайте, который уже принимает заявки, включается переключателем «Базовая защита от спама» в «Формы → Настройки».
- Отсеивает заявки, в которых заполнено скрытое поле-ловушка, отправленные без скрипта страницы или быстрее, чем человек успевает набрать текст, с несколькими ссылками или в обход картинки-капчи. Частота отправки с одного адреса ограничена.
- Отсеянные заявки никуда не отправляются: 30 дней они лежат в папке «Спам» раздела «Записи». Ошибочно отсеянную можно вернуть действием «Не спам».
- Собственные формы WordPress защищает отдельный переключатель «Защита от спама для форм WordPress», включённый по умолчанию: комментарии и отзывы о товарах, регистрация и сброс пароля. Комментарий, который бот отправил, не открывая страницу, отклоняется и никуда не сохраняется; пограничный попадает в «Комментарии → Спам»; подозрительная регистрация или запрос сброса отклоняется с просьбой повторить. Форма входа и вошедшие пользователи не проверяются.
- Картинка-капча говорит на языке страницы: тексты задаются для каждого языка, а символы — те, что посетитель наберёт без переключения раскладки (украинские буквы, русские, латиница или цифры).
От ботов, которые целенаправленно имитируют человека, защищает reCAPTCHA с ключами Google — её можно включить в тех же настройках.
wp-field — ключ поля, переживающий переименование
По умолчанию поле формы уезжает под подписью, набранной в Webflow. Переименуете подпись позже — шаблон письма и карта передачи, которые на неё ссылались, перестанут совпадать, причём молча: заявка всё равно приходит. Разметьте поле (или его обёртку с подписью) — и ключ перестанет зависеть от подписи.
<input type="tel" wp-field="phone">
<div class="row" wp-field="phone">
<label for="tel">Телефон</label>
<input type="tel" id="tel">
</div>
Ключ проставляется в поле при генерации темы, поэтому настраивать потом ничего не нужно. Используйте латиницу, цифры, _ и -; имена, занятые конвейером форм, не принимаются и попадают в журнал проекта. Поля, имя которых задано WordPress или WooCommerce — комментарии, отзывы, оформление заказа — размечаются своими метками.
Движок произвольных полей
Тема хранит произвольные поля через ACF-совместимый движок. Два взаимозаменяемых движка используют одни и те же поля и данные, поэтому переключаться можно без потери значений.
Два движка, один формат данных
По умолчанию — Secure Custom Fields: бесплатный плагин с WordPress.org, который сам обновляется и даёт все типы полей ACF PRO без лицензии. Хотите свой лицензированный ACF PRO? Установите его — тема определит его автоматически.
Мультиязычные опции
Встроенная мультиязычная поддержка для опций темы и полей страниц. Автоматически активируется с Polylang или WPML.
Как это работает
Тема автоматически определяет Polylang или WPML и загружает соответствующую интеграцию.
- Автоопределение: Polylang (pll_current_language) или WPML (ICL_SITEPRESS_VERSION)
- Хранение по локалям: каждый язык получает свой набор значений опций
- Фоллбэк: пустые поля локали наследуют значения из «Все (по умолчанию)»
- Пользовательские флаги: загрузка собственных флагов языков из Медиатеки
Управление опциями по языкам
Используйте переключатель языков на странице опций для редактирования значений каждого языка.
| Действие | Описание |
|---|---|
| «Все (по умолчанию)» | Мастер-значения. Используются как фоллбэк, когда у локали нет своего значения. |
| Редактирование по языкам | Переключитесь на язык, чтобы редактировать его значения. Пустые поля наследуют от «Все». |
| Наследование | Оставьте поле пустым на странице локали, чтобы на фронтенде использовалось значение «Все (по умолчанию)». |
Автоперевод полей
Встроенный машинный перевод значений полей. Доступен в сайдбаре на страницах редактирования записей и опций.
- Кнопка «Перевести» у каждого текстового поля
- «Перевести всё» в сайдбаре — переводит все поля разом, включая скрытые вкладки и повторители
- Поля-ссылки пропускаются автоматически (определение по имени поля и паттерну URL)
- API-ключ не требуется — используется бесплатный Google Translate
- Поддержка WYSIWYG (визуальный редактор) — HTML-структура сохраняется
Защищённые файлы
Эти файлы сохраняются при обновлении темы и никогда не перезаписываются.
user-functions.php— Пользовательские PHP функцииcss/user.css— Пользовательские CSS стилиjs/user.js— Пользовательский JavaScript
Порядок загрузки CSS: main.css → themeforge.css → user.css. Используйте user.css для переопределения стилей темы.
Система импорта
Импорт данных и медиа из pages.json и menus.json, сгенерированных при создании темы.
Порядок импорта (Важно!)
- Шаг 1: Загрузить изображения (import_images) — загружает все медиа в WordPress
- Шаг 2: Импорт данных (import_data) — импортирует значения полей, связывает изображения с attachment ID
Изображения должны быть загружены ДО импорта данных. Причина: поля изображений привязываются к WordPress attachment ID в момент импорта.
Действия импорта
| Действие | Описание |
|---|---|
/?action=import_images | Загрузить все медиафайлы со всех страниц |
/?action=import_data | Импортировать все данные полей для всех страниц + опции темы |
/?action=import_page_media&slug=X | Загрузить медиа для конкретной страницы |
/?action=import_page_data&slug=X | Импортировать данные полей для конкретной страницы |
/?action=import_menu_data | Импортировать все меню (или одно: &menu=slug) |
Источник названия страницы
При создании WordPress-страниц во время импорта название берётся из исходного HTML в порядке приоритета:
<meta property="og:title">— Open Graph<title>— HTML title tag- Имя шаблона (например, «About» из page-about)
Разрешение имён изображений
Система импорта находит WordPress attachment ID по имени файла через цепочку fallback:
- URL-декодирование (обработка кириллицы: %D0%94%D0%B5... → Десерт...)
- Удаление 24-hex Webflow хеш-префикса (695a454c..._ → исходное имя)
- sanitize_file_name() + DB LIKE запрос для надёжного поиска
Импорт с учётом локали
Добавьте &lang=xx для импорта данных в конкретный язык. Метабокс импорта на странице редактирования автоматически определяет язык страницы.
/?action=import_page_data&slug=theme-options&lang=en| Контекст | Описание |
|---|---|
| Опции темы | Сохраняет опции с суффиксом локали (options_LOCALE_field). Используйте переключатель языка на странице «Опции». |
| Страницы | Находит или создаёт перевод страницы через Polylang, импортирует данные в него. Оригинальная страница находится независимо от языкового фильтра. |
| Метабокс импорта | На странице: определяет язык из поста (pll_get_post_language). На опциях: читает ?lang= из URL. |
Справочник разработчика
Технические детали для разработчиков и AI-ассистентов. HTML-атрибуты, типы полей, система меню, JavaScript-хуки, вспомогательные функции.
Типы полей
Сопоставление типов полей ACF / SCF. Каждый тип атрибута соответствует определённому HTML-элементу.
| ACF / SCF Type | Элемент | Пример атрибута |
|---|---|---|
| text | div, span, p, h1-h6 | fld-text="name" |
| textarea | div, p | fld-area="name" |
| wysiwyg | div | fld-editor="name" |
| image | img (src) | fld-image="name" |
| link / url | a (href) | fld-link="name" |
| true_false | wrapper div | fld-show="name" |
| color_picker | any (bg) | fld-bg-color="name" |
| repeater | wrapper div | fld-loop="name" |
| group | wrapper div | fld-group="name" |
| gallery | wrapper div | fld-gallery="name" |
| tab | container div | fld-tab="name" |
Группы полей (wp-fields-group)
Атрибут wp-fields-group создаёт группы полей ACF/SCF в админке WordPress.
Использование
<div wp-fields-group="Section Name"> ... fields ... </div>- Оборачивает поля в именованную группу (метабокс в админке)
- Несколько wp-fields-group групп на странице поддерживаются
- На странице theme-options: все группы объединяются в один контейнер опций
- Без wp-fields-group: поля генерируют только PHP (без UI в админке)
wp-show-editor
Сохранить текстовый редактор WordPress на страницах с кастомными полями.
Использование
<body wp-show-editor wp-fields-group="Section">- Ставится на тег <body> — по умолчанию редактор скрыт на шаблонах страниц с полями
- Используйте вместе с wp-fields-group, когда странице нужны и кастомные поля, и the_content()
- Не влияет на шаблоны записей (single, single-product) — у них редактор всегда виден
Совместимость данных ACF / SCF
Secure Custom Fields — это бесплатный совместимый форк ACF PRO, поддерживаемый на WordPress.org. Он идентичен по API и хранит значения в точности там же, поэтому SCF, ACF PRO и любые существующие данные ACF полностью взаимозаменяемы.
Одни и те же поля и данные
Переключение движка никогда не мигрирует и не переписывает контент — оба движка читают одни и те же ключи полей из wp_postmeta / wp_options. Существующие данные ACF из другой темы или ручной настройки подхватываются по имени поля, независимо от того, какой движок их создал.
Существующие и сторонние данные ACF
Если данные ACF (или SCF) уже есть — от другого генератора, прежней темы или вручную созданной группы полей — тема читает их как есть по имени поля. Ничего импортировать или конвертировать не нужно; значения появляются в редакторе под любым активным движком.
JavaScript-хуки
Пользовательские callback-функции, доступные в custom.js. Тема проверяет наличие этих функций и вызывает их в нужный момент.
Общие хуки
| Хук | Когда вызывается |
|---|---|
tf_webflow_init() | После AJAX-загрузки контента (переинициализация Webflow-взаимодействий) |
tf_after_filter() | После загрузки результатов AJAX-фильтра |
WooCommerce-хуки
| Хук | Когда вызывается |
|---|---|
tf_cart_data_modify(data) | Перед добавлением в корзину (модификация данных) |
tf_after_add_to_cart() | После добавления товара в корзину |
tf_after_cart_data_modify() | После изменения данных корзины |
tf_after_variation_change() | После смены вариации товара |
tf_after_recalc_checkout() | После пересчёта итогов оформления заказа |
Определите эти функции в custom.js. Устаревшие имена с префиксом wfp_ также поддерживаются для обратной совместимости.
Пользовательские запросы
Создавайте WP_Query и запросы терминов через интерфейс Панели темы — без кода.
Запрос записей
Настраивается в Панель темы → Custom Queries. Каждый запрос содержит: имя, тип записи, количество на странице, пагинацию, фильтры таксономий.
$args = select_query_by_name('my_query');
$query = new WP_Query($args);Запрос терминов
Настраивается в Панель темы → Custom Term Queries. Каждый запрос содержит: имя, таксономию, hide_empty, orderby, order.
$args = select_term_query_by_name('my_terms');
$terms = get_terms($args);Вспомогательные функции
PHP-функции, доступные в шаблонах и user-functions.php.
Общие
| Функция | Возвращает |
|---|---|
tf_default_thumbnail() | URL изображения-заглушки по умолчанию (настраивается в Настройках темы) |
tf_declense($n, $f1, $f2, $f5) | Славянское склонение: выбор правильной формы слова для числа (1 товар / 2 товара / 5 товаров) |
tf_num_decline($n, $titles) | Склонение с числом: «5 товаров». Принимает массив или строку через запятую. |
search_context($chars) | Выводит фрагмент текста вокруг найденного поискового запроса |
device_is($type) | Определение устройства: phone, tablet, mobile, desktop, ios, android |
WooCommerce
| Функция | Возвращает |
|---|---|
is_sale() | Участвует ли текущий товар в распродаже |
get_price($type, $format) | Цена товара: "price", "price_sale", "price_regular". Формат: "default", "extreme", "range" |
get_cart_info($info) | Итоги корзины: total_without_discount, total_with_discount, discount_amount, discount_percentage, coupon_discounts |
get_cart_volume() | Общий объём корзины в кубических метрах |