Если вы когда-нибудь видели чистый лист бумаги после Вставив «небольшой фрагмент, найденный в интернете», вы уже знаете, о чём идёт речь: лучшие практики. WordPress Это не теория, это страховочная сетка.
Проблема / Необходимость
В WordPress 6.9.4 (апрель 2026 г.) большинство проблем с WordPress, которые я устраняю, связаны не с ядром, а с кодом, добавленным слишком быстро: эхо неправильный крючок, а Ставить Неправильно настроенный файл, ненужный SQL-запрос, форма без nonce или плагин для создания фрагментов кода, загружающийся до того, как WordPress будет к этому готов.
Задача проста: создать надежную и многократно используемую кодовую базу для добавления функций «блогера» (призывы к действию, вставки, формы, ресурсы) без нарушения работы сайта, замедления его работы и создания уязвимостей.
В итоге вы научитесь настраивать мини-плагин Mu (или классический плагин), демонстрирующий надежные методы работы: условную загрузку скриптов, безопасный шорткод, защищенную REST-конечную точку, корректно хранимые параметры, чистые журналы и средства защиты (возможности, nonce, санитаризация/экранирование).
Краткое резюме
- Мы разрабатываем мини-плагин. (совместимо с WordPress 6.9.4+ / PHP 8.1+) добавляет кнопку призыва к действию (CTA) через шорткод и блок совместимости с конструктором сайтов.
- Мы корректно загружаем CSS/JS. с
wp_enqueue_scriptsВерсионирование и условия (избегайте загрузки повсюду). - Мы добавляем REST-эндпоинт для записи кликов по призывам к действию, с предоставлением разрешений и проверкой данных.
- Мы храним настройки через настройки API (опция), и мы корректно экранируем/очищаем данные.
- Мы предоставляем вам контрольный список для тестирования. + диагностическая таблица + наиболее часто встречающиеся ошибки.
Когда использовать это решение
- Вы хотите добавить простую «бизнес-функцию» (призыв к действию, баннер, упрощенная форма, минимальное отслеживание) без установки громоздкого плагина.
- Вы поддерживаете несколько сайтов и вам нужен переносимый, версионируемый (Git) и легко активируемый/деактивируемый код.
- Если вы используете Divi 5, Elementor или Avada: вам необходима стабильная отрисовка через шорткод (универсальная) и загрузка ресурсов, которая не засоряет весь интерфейс.
- Следует избегать фрагментов текста, разбросанных по всему сайту.
functions.php(Я часто наблюдал, как из-за этого веб-сайты становились неуправляемыми).
Когда НЕ следует использовать это решение
- Вам необходима действительно комплексная аналитическая система: используйте специализированный инструмент или решение, соответствующее требованиям GDPR, с управлением согласием. Наш REST-эндпоинт намеренно минималистичен.
- Если вы создаёте продукт, распространяемый публично, выбирайте полноценную архитектуру (классы, автозагрузка, тесты, CI, интернационализация). В данном случае мы стремимся к «профессиональной», но компактной основе.
- Цель положить Для сложных страниц: форматирование выполняйте в конструкторе, а логику (данные, безопасность, конечные точки, параметры) оставьте для плагина.
- Вы не контролируете код (он заблокирован на стороне клиента): используйте существующий, хорошо поддерживаемый плагин, а не внедряйте код через плагин со случайными фрагментами кода.
Предварительные условия / перед началом обучения
- WordPress : 6.9.4 или более поздняя версия.
- PHP Минимальная версия ОС: 8.1 (рекомендуется 8.2/8.3, если ваш хостинг-провайдер её поддерживает).
- охрана : файлы + база данных до любых изменений (а не «позже»).
- Тестовая среда В идеале используйте тестовую среду. Избегайте тестирования в производственной среде, особенно при работе с хуками инициализации.
- Полезные инструменты :
- WP-CLI для быстрой проверки статуса (
wp core version,wp plugin list). - Плагин для ведения журналов (или
WP_DEBUG_LOG) для перехвата ошибок PHP без нарушения отображения.
- WP-CLI для быстрой проверки статуса (
- Безопасность : всё, что принимает входные данные (REST, форма, строка запроса), должно быть проверено, очищено и защищено правами доступа.
Официальные источники, которые следует держать под рукой:
- Плагин Руководство разработчика
- wp_enqueue_script ()
- Справочник по REST API
- Монахини
- Руководство по PHP
Наивный подход (и почему его следует избегать)
Наиболее часто встречающаяся схема: вставка кода в functions.phpСоздайте шорткод, который удаляет неэкранированный HTML-код, и загрузите JavaScript на всех страницах, «потому что это работает».
Наивный пример (которого следует избегать)
<?php
// ❌ À NE PAS FAIRE : code non conditionné, sorties non échappées, pas de versioning, pas de sécurité.
add_action('wp_enqueue_scripts', function () {
wp_enqueue_script('cta', get_stylesheet_directory_uri() . '/cta.js', array('jquery'));
});
add_shortcode('cta', function ($atts) {
$url = $atts['url']; // ❌ non validé
$text = $atts['text']; // ❌ non échappé
return '<a class="cta" href="' . $url . '">' . $text . '</a>';
});
Почему это проблема?
- Безопасность : шорткод принимает непроверенные атрибуты → возможна XSS-атака, если роль может публиковать контент (или если контент импортирован).
- Эффективности JavaScript загружается повсюду, даже там, где нет кнопки призыва к действию.
- Обслуживание :
functions.phpЗависит от темы. Вы меняете тему (или переключаетесь на другую). Jour (без детской тематики) и вы всё потеряете. - Отладка Простая забытая скобка → белый экран. А в рабочей среде, без логов, приходится искать вслепую.
Правильный подход — пошаговое руководство
Шаг 1 — Выберите место для размещения кода (плагин или mu-плагин)
Для блога я часто рекомендую следующее: мю-плагин Если функциональность должна оставаться активной независимо от темы оформления, то стандартный плагин отлично справится с этой задачей.
- Вариант А (рекомендуемый) : mu-plugin:
wp-content/mu-plugins/bpcab-cta/bpcab-cta.php - Вариант B : классический плагин:
wp-content/plugins/bpcab-cta/bpcab-cta.php
Если вы выберете mu-plugin, создайте папку. mu-plugins если его не существует.
Шаг 2 — Объявить плагин, заблокировать прямой доступ, исправить версию.
Цель: избежать выполнения кода вне WordPress и обеспечить постоянную версию кэша ресурсов.
Шаг 3 — Добавьте безопасный короткий код (очистка + экранирование)
Мы собираемся создать [bpcab_cta]Будет сгенерирована ссылка CTA с идентификатором. Этот идентификатор будет использоваться для отслеживания REST-запросов.
Шаг 4 — Загружайте CSS/JS только при необходимости.
Две надежные стратегии:
- Простой Загрузка на всех страницах (подходит, если страница очень легкая, но редко бывает оптимальным).
- Чистый : Загружать только в том случае, если шорткод присутствует в контенте или если конструктор отобразил шорткод.
По моему опыту, обнаружение "шорткода в контенте" охватывает 80% случаев. Для Divi/Elementor/Avada мы добавляем дополнительную защиту: если скрипт явно запрашивается через хук, мы его загружаем.
Шаг 5 — Создайте защищенную REST-конечную точку
Мы разоблачаем /wp-json/bpcab/v1/cta-click кто принимает cta_idМы проверяем формат, ограничиваем злоупотребления (мягкое ограничение скорости) и храним счетчик как опцию (простой вариант) или в метаданных (вариант).
Шаг 6 — Добавьте минималистичную страницу настроек (необязательно)
Мы добавляем настройку: включение/отключение отслеживания REST-запросов. Это позволит избежать необходимости «комментировать код» в рабочей среде.
Полный код
Скопируйте и вставьте этот файл как есть. Он намеренно выполнен в монолитном формате для обеспечения читаемости. Для более крупного проекта я бы разбил его на отдельные классы.
<?php
/**
* Plugin Name: BPCAB CTA (bonnes pratiques)
* Description: Ajoute un shortcode CTA, charge les assets proprement, et propose un endpoint REST sécurisé pour compter les clics.
* Version: 1.0.0
* Requires at least: 6.9
* Requires PHP: 8.1
* Author: Votre équipe
*
* Ce plugin est conçu pour WordPress 6.9.4+ (avril 2026).
*/
declare(strict_types=1);
if (!defined('ABSPATH')) {
exit; // Empêche l'accès direct au fichier.
}
define('BPCAB_CTA_VERSION', '1.0.0');
define('BPCAB_CTA_SLUG', 'bpcab-cta');
define('BPCAB_CTA_OPT', 'bpcab_cta_options');
/**
* Retourne les options du plugin avec des valeurs par défaut.
*/
function bpcab_cta_get_options(): array {
$defaults = array(
'enable_tracking' => true,
);
$opts = get_option(BPCAB_CTA_OPT, array());
if (!is_array($opts)) {
$opts = array();
}
// Fusion simple, sans surprises.
return array_merge($defaults, $opts);
}
/**
* Enregistre le shortcode [bpcab_cta].
*/
function bpcab_cta_register_shortcode(): void {
add_shortcode('bpcab_cta', 'bpcab_cta_shortcode_render');
}
add_action('init', 'bpcab_cta_register_shortcode');
/**
* Rend le shortcode.
*
* Exemples :
* [bpcab_cta text="Télécharger le guide" url="https://exemple.com/guide" id="guide-2026" rel="nofollow"]
*
* Sécurité :
* - Validation URL
* - Escaping HTML
*/
function bpcab_cta_shortcode_render($atts = array(), $content = null, $tag = ''): string {
$atts = shortcode_atts(
array(
'text' => 'En savoir plus',
'url' => '',
'id' => '',
'rel' => 'noopener',
'target' => '_blank',
'class' => '',
),
(array) $atts,
'bpcab_cta'
);
$text = sanitize_text_field((string) $atts['text']);
$url = esc_url_raw((string) $atts['url']);
// Un identifiant simple (pour tracking). Si absent, on en génère un stable basé sur l'URL.
$id = sanitize_key((string) $atts['id']);
if ($id === '' && $url !== '') {
$id = 'cta-' . substr(md5($url), 0, 10);
}
$rel = sanitize_text_field((string) $atts['rel']);
$target = sanitize_text_field((string) $atts['target']);
$extra_class = sanitize_html_class((string) $atts['class']);
$classes = trim('bpcab-cta ' . $extra_class);
// Si pas d'URL valide, on ne rend rien (évite un lien vide).
if ($url === '') {
return '';
}
// Marqueur pour permettre le chargement conditionnel des assets.
$GLOBALS['bpcab_cta_has_cta'] = true;
// Data attribute pour le JS.
$data_id_attr = $id !== '' ? ' data-cta-id="' . esc_attr($id) . '"' : '';
return '<a class="' . esc_attr($classes) . '" href="' . esc_url($url) . '" rel="' . esc_attr($rel) . '" target="' . esc_attr($target) . '"' . $data_id_attr . '>'
. esc_html($text)
. '</a>';
}
/**
* Enqueue des assets, si nécessaire.
*
* Notes :
* - On évite de charger partout.
* - On ajoute une variable JS localisée avec le nonce REST.
*/
function bpcab_cta_enqueue_assets(): void {
$should_enqueue = false;
// 1) Si un shortcode a été rendu (plus fiable que "has_shortcode" quand le contenu est filtré par un builder).
if (!empty($GLOBALS['bpcab_cta_has_cta'])) {
$should_enqueue = true;
}
// 2) Fallback : si le post courant contient le shortcode (utile si le rendu n'a pas encore eu lieu).
if (!$should_enqueue && is_singular()) {
$post = get_post();
if ($post instanceof WP_Post) {
// has_shortcode attend du contenu brut, ça marche dans la plupart des cas.
if (has_shortcode((string) $post->post_content, 'bpcab_cta')) {
$should_enqueue = true;
}
}
}
/**
* 3) Filtre pour forcer l'enqueue depuis un thème/builder.
* Exemple : add_filter('bpcab_cta_force_enqueue', '__return_true');
*/
$should_enqueue = (bool) apply_filters('bpcab_cta_force_enqueue', $should_enqueue);
if (!$should_enqueue) {
return;
}
$base_url = plugin_dir_url(__FILE__);
wp_enqueue_style(
'bpcab-cta',
$base_url . 'assets/cta.css',
array(),
BPCAB_CTA_VERSION
);
wp_enqueue_script(
'bpcab-cta',
$base_url . 'assets/cta.js',
array(),
BPCAB_CTA_VERSION,
true
);
$options = bpcab_cta_get_options();
wp_localize_script(
'bpcab-cta',
'BPCAB_CTA',
array(
'restUrl' => esc_url_raw(rest_url('bpcab/v1/cta-click')),
// Nonce REST : côté serveur, on vérifie via check_ajax_referer-like ? Non, pour REST on lit l'en-tête X-WP-Nonce.
'nonce' => wp_create_nonce('wp_rest'),
'enableTracking' => (bool) $options['enable_tracking'],
)
);
}
add_action('wp_enqueue_scripts', 'bpcab_cta_enqueue_assets');
/**
* Déclare la route REST.
*/
function bpcab_cta_register_rest_routes(): void {
register_rest_route(
'bpcab/v1',
'/cta-click',
array(
'methods' => WP_REST_Server::CREATABLE, // POST
'callback' => 'bpcab_cta_rest_click',
'permission_callback' => 'bpcab_cta_rest_permissions',
'args' => array(
'cta_id' => array(
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_key',
'validate_callback' => function ($param) {
$param = (string) $param;
// Limite simple : évite les IDs vides et trop longs.
return $param !== '' && strlen($param) <= 64;
},
),
),
)
);
}
add_action('rest_api_init', 'bpcab_cta_register_rest_routes');
/**
* Permissions REST :
* - Endpoint public, mais protégé par nonce REST + option d'activation.
* - On limite aussi le spam via un throttle basique par IP.
*
* Attention : si vous voulez du tracking sans nonce (visiteurs non connectés),
* vous devez gérer le consentement et la protection anti-abus autrement.
*/
function bpcab_cta_rest_permissions(WP_REST_Request $request): bool {
$options = bpcab_cta_get_options();
if (empty($options['enable_tracking'])) {
return false;
}
// Vérifie le nonce REST (header X-WP-Nonce).
$nonce = $request->get_header('x_wp_nonce');
if (!$nonce || !wp_verify_nonce($nonce, 'wp_rest')) {
return false;
}
// Throttle léger : 1 hit / 2s / IP (approximatif).
$ip = isset($_SERVER['REMOTE_ADDR']) ? (string) $_SERVER['REMOTE_ADDR'] : '';
$key = 'bpcab_cta_throttle_' . md5($ip);
$last = (int) get_transient($key);
$now = time();
if ($last > 0 && ($now - $last) < 2) {
return false;
}
set_transient($key, $now, 10);
return true;
}
/**
* Callback REST : incrémente un compteur par cta_id.
* Stockage simple en option (table wp_options).
*/
function bpcab_cta_rest_click(WP_REST_Request $request): WP_REST_Response {
$cta_id = (string) $request->get_param('cta_id');
$cta_id = sanitize_key($cta_id);
$counts = get_option('bpcab_cta_counts', array());
if (!is_array($counts)) {
$counts = array();
}
$current = isset($counts[$cta_id]) ? (int) $counts[$cta_id] : 0;
$counts[$cta_id] = $current + 1;
// Autoload = no pour éviter de gonfler les options chargées sur chaque page.
update_option('bpcab_cta_counts', $counts, false);
return new WP_REST_Response(
array(
'ok' => true,
'cta_id' => $cta_id,
'count' => (int) $counts[$cta_id],
),
200
);
}
/**
* Ajoute une page de réglages minimaliste (Réglages > BPCAB CTA).
*/
function bpcab_cta_register_settings_page(): void {
add_options_page(
'BPCAB CTA',
'BPCAB CTA',
'manage_options',
'bpcab-cta',
'bpcab_cta_render_settings_page'
);
}
add_action('admin_menu', 'bpcab_cta_register_settings_page');
/**
* Enregistre le setting.
*/
function bpcab_cta_register_settings(): void {
register_setting(
'bpcab_cta_settings',
BPCAB_CTA_OPT,
array(
'type' => 'array',
'sanitize_callback' => 'bpcab_cta_sanitize_options',
'default' => array(
'enable_tracking' => true,
),
)
);
add_settings_section(
'bpcab_cta_main',
'Réglages',
function () {
echo '<p>Réglages simples. Le tracking REST nécessite un nonce (visiteurs connectés).</p>';
},
'bpcab-cta'
);
add_settings_field(
'enable_tracking',
'Activer le tracking des clics (REST)',
'bpcab_cta_field_enable_tracking',
'bpcab-cta',
'bpcab_cta_main'
);
}
add_action('admin_init', 'bpcab_cta_register_settings');
/**
* Sanitize des options.
*/
function bpcab_cta_sanitize_options($input): array {
$input = is_array($input) ? $input : array();
return array(
'enable_tracking' => !empty($input['enable_tracking']),
);
}
/**
* Champ checkbox.
*/
function bpcab_cta_field_enable_tracking(): void {
$options = bpcab_cta_get_options();
$checked = !empty($options['enable_tracking']) ? 'checked' : '';
echo '<label>';
echo '<input type="checkbox" name="' . esc_attr(BPCAB_CTA_OPT) . '[enable_tracking]" value="1" ' . $checked . ' /> ';
echo 'Compter les clics via l’endpoint REST (nonce requis).';
echo '</label>';
}
/**
* Render page settings.
*/
function bpcab_cta_render_settings_page(): void {
if (!current_user_can('manage_options')) {
return;
}
echo '<div class="wrap">';
echo '<h1>BPCAB CTA</h1>';
echo '<form method="post" action="options.php">';
settings_fields('bpcab_cta_settings');
do_settings_sections('bpcab-cta');
submit_button();
echo '</form>';
echo '</div>';
}
CSS-файл
создать assets/cta.css в той же папке, что и плагин.
.bpcab-cta{
display:inline-block;
padding:0.7rem 1rem;
border-radius:10px;
background:#111827;
color:#fff;
text-decoration:none;
font-weight:600;
line-height:1.2;
}
.bpcab-cta:hover,
.bpcab-cta:focus{
background:#0b1220;
color:#fff;
}
JS-файл
создать assets/cta.jsЭтот JavaScript отправляет REST POST-запрос по клику, если эта функция включена.
(function () {
"use strict";
function postJson(url, data, nonce) {
return fetch(url, {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
"X-WP-Nonce": nonce
},
body: JSON.stringify(data)
});
}
document.addEventListener("click", function (e) {
var a = e.target.closest && e.target.closest("a.bpcab-cta");
if (!a) return;
if (typeof window.BPCAB_CTA === "undefined") return;
if (!window.BPCAB_CTA.enableTracking) return;
var ctaId = a.getAttribute("data-cta-id");
if (!ctaId) return;
// Fire-and-forget : on ne bloque pas la navigation.
try {
postJson(window.BPCAB_CTA.restUrl, { cta_id: ctaId }, window.BPCAB_CTA.nonce);
} catch (err) {
// Pas de console.error agressif en prod.
}
});
})();
Код Пояснение
Глобальная логика (простая)
- Этот шорткод делает ссылку CTA чистой и помечает глобальный флаг (
$GLOBALS['bpcab_cta_has_cta']). - При добавлении в очередь CSS/JS загружается только в том случае, если активен призыв к действию (флаг или
has_shortcode(или фильтр). - JavaScript отправляет REST POST-запрос по клику, используя REST nonce.
- Сервер проверяет параметр, значение nonce, применяет минимальное ограничение скорости, а затем увеличивает счетчик.
Технические детали, которые имеют решающее значение.
- Побег против дезинфекции :
- дезинфицировать очищает вход (например,
sanitize_text_field,sanitize_key). - бежать защищает выходные данные (например:
esc_html,esc_attr,esc_url).
- дезинфицировать очищает вход (например,
- ОТДЫХ Нет :
- Мы генерируем
wp_create_nonce('wp_rest')На стороне PHP. - Мы отправляем его через
X-WP-Nonceсо стороны JavaScript. - Мы связываемся с
wp_verify_nonceвpermission_callback.
- Мы генерируем
- Параметры автозагрузки :
- Счетчик хранится в опции, не загружаемой автоматически (
update_option(..., false)) чтобы избежать отекаwp_optionsзагружается с каждым запросом.
- Счетчик хранится в опции, не загружаемой автоматически (
- Зацепление :
initдля шорткода (WordPress готов сохранять шорткоды).wp_enqueue_scriptsдля фронтенд-активов.rest_api_initдля регистрации REST-маршрута.admin_init+admin_menuдля настроек.
Полезные документы:
Варианты и сценарии использования
Вариант 1 — Отключить отслеживание посетителей, не вошедших в систему (текущее поведение)
Код в текущем виде работает в основном для авторизованных пользователей (не REST API). Для публичного блога это часто именно то, что нужно, если у вас нет системы управления согласием или мер защиты от злоупотреблений.
Вариант 2 — Сохранять количество кликов по каждой публикации (метатеги публикации) вместо опции.
Если ваш призыв к действию связан со статьей, сохраните его в метаданных записи. Преимущество: целевые запросы, упрощенный экспорт по каждой записи. Недостаток: вам придется отправлять post_id и убедиться, что оно существует.
<?php
// Exemple partiel : logique de stockage en post meta (à intégrer dans le callback REST).
$post_id = (int) $request->get_param('post_id');
if ($post_id > 0 && get_post_status($post_id)) {
$key = '_bpcab_cta_clicks_' . $cta_id;
$current = (int) get_post_meta($post_id, $key, true);
update_post_meta($post_id, $key, $current + 1);
}
Вариант 3 — Принудительная загрузка ресурсов на определенной странице конструктора.
Когда разработчик "перекомпоновывает" контент, has_shortcode Может упустить свой шанс. Фильтр bpcab_cta_force_enqueue для этого есть.
<?php
// À placer dans un plugin site-specific ou thème enfant.
add_filter('bpcab_cta_force_enqueue', function ($should) {
// Exemple : forcer sur une page ID 123.
if (is_page(123)) {
return true;
}
return $should;
});
Совместимость с Divi 5 / Elementor / Avada
Дива 5
Divi отлично отображает шорткоды в модулях "Код" или "Текст". Следует отметить, что Divi может кэшировать отрисовку. Если вы изменили CSS/JS и ничего не видите, очистите кэш.
- Divi > Параметры темы > Конструктор > Кэш (в зависимости от конфигурации)
- Ваш плагин кэширования
- Кэш браузера
Если условная постановка элементов в очередь не срабатывает (редко, но я видел такое на очень динамичных макетах), используйте фильтр. bpcab_cta_force_enqueue на соответствующей странице.
Elementor
В Elementor есть виджет «Шорткод». Шорткод обычно находится в post_contentТаким образом, обнаружение работает. Если вы используете шаблоны и циклы, вы можете столкнуться с ситуациями, когда кнопка призыва к действию (CTA) отображается через шаблон, даже если «основное» содержимое не содержит шорткод. Опять же, для этого требуется фильтр принудительного отображения.
Авада (конструктор Fusion)
Avada поддерживает шорткоды в своих текстовых/кодовых элементах. Я часто сталкивался с тем, что CSS не применяется, потому что Avada объединяет/минифицирует ресурсы. Сначала протестируйте без оптимизации Avada, а затем снова включите её.
Практические рекомендации (для строителей)
Что касается конструкторов, я оставляю отрисовку внутри самого конструктора (макета), а остальное делегирую плагину:
- генерация кнопки призыва к действию (короткого кода),
- отслеживание,
- Чистая погрузка активов.
Послемонтажные проверки
- Убедитесь, что шорткод корректно отображает ссылку: add
[bpcab_cta text="Tester" url="https://example.com" id="test"]в статье. - Откройте страницу и проверьте это.
assets/cta.cssetassets/cta.jsзагружены (вкладка «Сеть»). - Если вы вошли в систему, нажмите на кнопку призыва к действию (CTA) и проверьте POST-запрос к
/wp-json/bpcab/v1/cta-click(статус 200). - В административной панели перейдите в «Настройки» > «BPCAB CTA», отключите отслеживание, затем повторите проверку: запрос должен завершиться ошибкой (403 или 401 в зависимости от контекста).
Диагностическая схема (симптом → решение)
| симптом | Причина вероятна | проверка | Решение |
|---|---|---|---|
| Короткий код отображает обычный текст. | Шорткод не зарегистрирован (неверный хук / плагин не загружен) | Убедитесь, что плагин активен (или что mu-плагин правильно расположен). | Поместите файл в нужное место и проверьте его. add_action('init', ...) |
| Призыв к действию появляется, но без стиля. | CSS не загружен (загрузка не активирована / кэширование) | Вкладка «Сеть»: cta.css отсутствуют |
Принудительное добавление в очередь с помощью фильтра, очистка кеша (плагина + конструктора + браузера) |
| ERREUR ОТДЫХ 403 | Отсутствует/недействителен одноразовый код REST. | Содержит ли запрос X-WP-Nonce ? |
Контрольник wp_localize_scriptЧтобы оставаться на связи, избегайте кэширования, которое отображает страницу без одноразового кода (nonce). |
| Показания одометра никогда не увеличиваются. | Отслеживание отключено | Настройки > BPCAB CTA | Повторно активируйте опцию «Включить отслеживание…» |
| Пустая страница после добавления плагина | Ошибка PHP (точка с запятой, скобка, PHP < 8.1) | советоваться wp-content/debug.log или журналы сервера |
Исправьте ошибку, проверьте версию PHP, разверните приложение через тестовую среду. |
Если это не сработает
1) Проверьте местоположение кода.
- Mu-плагин:
wp-content/mu-plugins/bpcab-cta/bpcab-cta.php(Файл должен быть доступен для чтения непосредственно WordPress). - Плагин:
wp-content/plugins/bpcab-cta/bpcab-cta.php+ активация в панели администратора.
Распространенная ошибка: создание mu-plugins/bpcab-cta.php но поместите ресурсы в другую папку. Здесь мы предполагаем... assets в той же папке, что и PHP-файл.
2) Включите корректное ведение журнала.
На сцене активируйте:
<?php
// wp-config.php (staging uniquement)
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Затем прочтите еще раз. wp-content/debug.log.
3) Проверьте обработчик постановки в очередь.
Я часто натыкался на фрагмент текста, вставленный на init для запросов к скриптам. «Иногда работает», а затем ломается при работе с кэшем или сборщиком. Здесь мы будем придерживаться этого подхода. wp_enqueue_scripts.
4) Очистите кэш (в правильном порядке).
- Плагин кэширования (кэш страниц / кэш объектов).
- Кэш конструктора (Divi/Avada).
- Кэш CDN, если он присутствует.
- Кэш браузера.
5) Протестируйте REST-интерфейс изолированно.
Если вы авторизованы, протестируйте с помощью curl (получив nonce со страницы или используя небольшой скрипт). Пример (имя пользователя):
curl -X POST "https://votre-site.tld/wp-json/bpcab/v1/cta-click"
-H "Content-Type: application/json"
-H "X-WP-Nonce: VOTRE_NONCE"
--data '{"cta_id":"test"}'
Распространенные ошибки и ловушки
| ERREUR | Вызывать | Решение |
|---|---|---|
Скопируйте код в functions.php родительской темы |
Обновление темы = потеря кода | Используйте плагин (или mu-плагин) или дочернюю тему. |
| Забыли точку с запятой → белый экран | Синтаксическая ошибка PHP | Прочитайте логи, устраните проблему и протестируйте на тестовой системе. |
| Использование неправильного хука для постановки в очередь. | init вместо wp_enqueue_scripts |
Опрос проводится только в wp_enqueue_scripts / admin_enqueue_scripts |
| Конфликт кэша: недействительный REST nonce | Кэшированная страница отображает истекший nonce или nonce от другого пользователя. | Исключите страницы, на которые подписаны пользователи, из кэша или отключите публичное отслеживание. |
| «REST 403» даже при подключении. | заголовок X-WP-Nonce отсутствует (JS не загружен) |
Проверьте условный запрос, принудительно используйте фильтр. |
| Шорткод работает в редакторе, но не в конструкторе. | Конструктор выполняет рендеринг через шаблон/цикл. post_content |
Принудительное выполнение запроса к странице (фильтр) или глобальная загрузка, если запрос очень маленький. |
| «Вызов неопределенной функции…» | Код выполняется слишком рано (до загрузки WordPress) или файл подключается вне контекста. | Контрольник ABSPATHРазместите код в плагине, используйте хуки. |
| Ошибка «Ваша версия PHP слишком старая» | PHP-хостинг < 8.1 | Обновите PHP-код на стороне хостинга (или адаптируйте код, но это не рекомендуется). |
| CSS/JS не загружается | Неверный путь plugin_dir_url(__FILE__) если активы утеряны |
Соблюдайте структуру каталогов и проверяйте наличие ошибок 404 на вкладке «Сеть». |
Советы по безопасности, производительности и техническому обслуживанию
Безопасность
- Никогда не отображайте неэкранированный HTML-код. Контент копируется, импортируется и иногда редактируется другими пользователями с другими ролями, даже если он используется «только администраторами».
- REST публичный = поверхность атакиЗдесь намеренно требовался REST-нонс, ограничивающий использование только подключенными сессиями. Для публичного отслеживания необходима комплексная стратегия (согласие + защита от злоупотреблений + хранение данных).
- Разрешения... Для маршрута, изменяющего конфиденциальные данные, используйте возможности. Здесь мы увеличиваем счетчик, но при этом ограничиваем его использование.
Эффективности
- Загружайте ресурсы только при необходимости.Это является прямым преимуществом для Core Web Vitals, если ваш сайт содержит много страниц.
- Не надувайте
wp_optionsавтозагрузкаАвтоматически загружаемые параметры загружаются (почти) при каждом запросе. Большие счетчики должны быть автозагрузка=нет или хранятся в другом месте. - Остерегайтесь дополнительных опций хранения. Если у вас сотни призывов к действию (CTA), то этот вариант подойдет.
bpcab_cta_countsОно может разрастаться. В таком случае переключитесь на отдельную таблицу или метаданные для постов.
Обслуживание
- Версия Этот плагин (Git). Неверсионированный фрагмент кода быстро становится «загадкой» во время редизайна.
- Задокументируйте фильтры что вы представляете (здесь)
bpcab_cta_force_enqueue). Именно такие детали спасают ситуацию, когда застройщик меняет визуализацию. - Избегайте устаревших руководств. Во многих фрагментах кода до PHP 8.1 используются ненадежные шаблоны (неконтролируемые глобальные переменные, устаревшие функции, встроенный JavaScript). В WordPress 6.9.4 следует придерживаться официальных API.
Ресурсы
- Плагин Руководство разработчика
- wp_enqueue_style ()
- wp_localize_script ()
- Справочник по REST API
- Нонсы (безопасность)
- WordPress Core Trac
- wordpress-develop (GitHub)
- PHP: filter_var()
FAQ
Почему плагин, а не... functions.php ?
Потому что код не должен зависеть от темы оформления. Плагин сохраняется после смены темы и корректно деактивируется, чтобы изолировать ошибку.
Почему для отслеживания по REST-запросам требуется одноразовый код (nonce)?
В противном случае ваша конечная точка становится удобным публичным каналом для рассылки спама. При использовании REST nonce доступ (по умолчанию) ограничивается авторизованными пользователями. Для публичного отслеживания требуется другой подход.
Мне нужно подсчитать количество кликов посетителей, которые не авторизованы. Как это сделать?
Технически: вы можете разрешить доступ без одноразового кода и внедрить более надежные меры по борьбе со злоупотреблениями (ограничение скорости запросов, подписи, хранение данных на стороне сервера). Юридически: вы должны управлять согласием в соответствии с вашим конкретным контекстом (GDPR). Я не рекомендую просто «открывать дверь».
Зачем использовать update_option(..., false) ?
Сила третьего параметра автозагрузка=нетСчетчик может увеличиваться в размере; вам не нужно, чтобы он загружался на каждой странице.
Шорткод не запускает добавление данных в очередь в моем конструкторе, что мне делать?
Воспользуйтесь фильтром bpcab_cta_force_enqueue на соответствующей странице или загрузить глобально, если ваш CSS/JS-код невелик. В некоторых шаблонах циклов... has_shortcode Он ничего не видит.
Почему именно «глобальный флаг»? $GLOBALS['bpcab_cta_has_cta'] ?
Потому что это простой и надежный способ узнать, что призыв к действию был отображен, даже если контент был преобразован сложными фильтрами. Это старый трюк, но эффективный, если использовать его умеренно.
Совместимо ли оно с несколькими сайтами?
Да, на базовом уровне: параметры и временные данные задаются для каждого сайта отдельно. Если вам нужна отчетность по сети, необходимо хранить данные на уровне сети (параметры сайта) или централизовать их в другом месте.
Соответствует ли оно стандартам WordPress?
Мы используем стандартные API (шорткод, добавление в очередь, REST, настройки). Для дальнейшего развития: разделим на классы, добавим тесты и более подробно задокументируем фильтры/действия.
Как отобразить счетчики в панели администратора?
Самое простое решение: отдельная административная страница, на которой отображается следующее: get_option('bpcab_cta_counts') и отображает таблицу. Если у вас много идентификаторов, запланируйте пагинацию и очистку данных.
Что делать, если я получаю ошибку «REST cookie is invalid nonce»?
Это часто происходит из-за агрессивного кэширования для авторизованных пользователей или плагина безопасности, изменяющего файлы cookie. Временно отключите кэширование для авторизованных пользователей, а затем повторите проверку. Также проверьте заголовок. X-WP-Nonce Отправка прошла успешно.
Могу ли я заменить wp_localize_script ?
Да: вы можете использовать wp_add_inline_script для внедрения объекта JSON. wp_localize_script Остается очень практичным и широко используемым способом передачи данных в JavaScript.