Ak ste niekedy dostali e-mail typu „Nenašiel som informácie na vašej stránke, môžete mi pomôcť?“, už máte dobrý príklad použitia minichatu s umelou inteligenciou. Cieľom nie je „nahradiť“ váš tím podpory, ale poskytnúť užitočnú počiatočnú odpoveď na základe obsahu vašej webovej stránky. sans inštalovať zapojiť.
Potreba / Prípad použitia
„Jednoduchý“ chatbot s umelou inteligenciou WordPress Jeho hlavným účelom je absorbovať opakujúce sa otázky: otváracie hodiny, pravidlá vrátenia tovaru, „kde nájsť taký a taký tovar“, súhrny dlhého sprievodcu alebo navigačnej pomoci („Hľadám návod na permanentné odkazy“). Na blogu som často videl, že 80 % prichádzajúcich požiadaviek sa zredukovalo na 10 otázok.
Čo prináša umelá inteligencia: minimalistické rozhranie chatu + bezpečnú trasu WordPress AJAX, ktorá odošle otázku do API rozhrania umelej inteligencie (napr. OpenAI) a vráti použiteľnú odpoveď. Zámerne sa snažíme zjednodušiť veci: žiadne widgety tretích strán, žiadne SDK, žiadne závislosti od Composera.
Nakoniec budete vedieť:
- Zobrazenie malej mačky (HTML/CSS/JS) pomocou shortcode WordPressu.
- Odošlite otázku na váš WordPress server (AJAX) s jednorazovým číslom (anti-CSRF token).
- Volanie AI API s
wp_remote_post(), spracovať chyby/časové limity a ukladať odpovede do vyrovnávacej pamäte pomocou prechodových javov. - Chráňte svoj API kľúč (uložený v
wp-config.php) a vyhnite sa jeho vystaveniu prehliadaču.
Rýchle zhrnutie
- Pridáte API konštantu do
wp-config.php(nikdy nie k téme). - Vytvoríte mu-plugin (plugin „povinný na použitie“), ktorý poskytuje skrátený kód
[ai_chatbot]. - Front (JS) volá
admin-ajax.phps jednorazovým číslom, nie priamo s rozhraním API AI. - Server volá API cez
wp_remote_post(), krátky časový limit, čisté spracovanie chýb. - Vyrovnávacia pamäť odpovedí (prechodových javov) na zníženie nákladov.
- Vyčistená odpoveď pred zobrazením (
wp_kses()) na obmedzenie rizík XSS.
Kedy na to použiť umelú inteligenciu
Použite tento typ chatbota, ak:
- Dostávate opakujúce sa otázky a chcete okamžitú „prvú odpoveď“.
- Váš obsah je už bohatý (FAQ, stránky „O nás“, sprievodcovia) a umelá inteligencia môže používateľa viesť.
- Akceptujete, že odpoveď môže byť niekedy nedokonalá a pridáte jasný odkaz („automatická odpoveď“).
- Chcete ľahký, kontrolovaný chatbot bez toho, aby ste sa museli spoliehať na nepriehľadný plugin, ktorý všade vkladá externé skripty.
Často ho odporúčam pre blogy s tutoriálmi, prezentačné stránky alebo špecializované oblasti, kde sú otázky veľmi stabilné (napr. „ako rezervovať“, „lehoty“, „ceny“).
Kedy NEPOUŽÍVAŤ AI
Vyhnite sa umelej inteligencii, ak klasické riešenie WordPressu robí lepšiu, jednoduchšiu a lacnejšiu prácu:
- Interný výskum Začnite vylepšením funkcie vyhľadávania (výňatky, kategórie, stránka „Mapa stránok“). Umelá inteligencia môže byť drahá len preto, aby vám povedala, aby ste „použili funkciu vyhľadávania“.
- Citlivá podpora (Zdravie, právne záležitosti, financie): Riziko halucinácií je reálne. V týchto prípadoch je bezpečnejší kontaktný formulár + báza vedomostí.
- Problémy s transakciami (príkazy, účty): ak odpoveď závisí od súkromných údajov, nevytvárajte „jednoduchý“ chat s umelou inteligenciou. Potrebujete skutočné overenie, povolenia a model hrozby.
- Napätý rozpočet Ak máte nízku návštevnosť, je to v poriadku. Ak máte 50 000 návštev denne, náklady môžu prudko stúpnuť, ak nemáte limit vyrovnávacej pamäte/rýchlosti.
predpoklady
Cielené verzie WordPress 6.9.4 (apríl 2026) a PHP 8.1+.
Kľúč API pre AI Ako príklad používam OpenAI, pretože API je stabilné a dobre zdokumentované, ale architektúra bude rovnaká ako v Anthropic/Mistral/Google.
Rýchle pochopenie: volania API a HTTP
Une API je rozhranie, ktoré vám umožňuje niečo vyžiadať od služby (tu: „odpovedať na túto otázku“). Technicky odosielate HTTP požiadavku (často v POST) s JSON a vy na oplátku dostanete JSON.
Vo WordPresse sa to robí správne cez HTTP API: wp_remote_post() (a wp_remote_get()Toto je odporúčaná metóda, pretože spracováva transport (cURL, streamy), proxy a integruje sa s WordPressom.
Oficiálny zdroj: HTTP API pre WordPress.
Kam uložiť API kľúč (povinné)
Kľúč si uložíte do wp-config.phpNie v súbore témy a už vôbec nie v JavaScripte. Ak sa váš kľúč dostane do prehliadača, bude do 30 sekúnd skopírovaný a použitý na vaše náklady.
Pridajte toto k wp-config.php (ideálne tesne pred riadkom „To je všetko, prestaňte s úpravami!“)
define('BPCAB_OPENAI_API_KEY', 'VOTRE_CLE_ICI');
náklady Každá správa odoslaná do API stojí peniaze (za token). Aj keď ide o „pár centov“, môže sa to nasčítať. Preto implementujeme ukladanie do vyrovnávacej pamäte a limit rýchlosti na strane servera.
Kam vložiť kód
- Odporúčaná možnosť : mu-plugin (poplatok automaticky). Cesta:
wp-content/mu-plugins/. - Alternatíva : klasický vlastný plugin v
wp-content/plugins/. - Vyhnúť sa :
functions.phptémy (najmä ak zmeníte témy alebo ak nástroj na tvorbu aktualizuje súbory).
Oficiálna dokumentácia k mu-pluginom: Pluginy, ktoré musíte použiť.
Architektúra riešenia
Tu je informačný kanál, zrozumiteľným spôsobom:
- Návštevník otvorí stránku, ktorá obsahuje
[ai_chatbot]. - Skrátený kód zobrazuje používateľské rozhranie (malé okno) + načítava JS.
- Keď používateľ odošle správu, JS odošle požiadavku POST.
admin-ajax.phps:- správa
- WordPress nonce (dopyt s ochranou proti sfalšovaniu)
- WordPress prijme požiadavku prostredníctvom AJAX hooku, overí nonce, použije limit rýchlosti a potom zavolá AI API prostredníctvom
wp_remote_post(). - WordPress vyčistí odpoveď, uloží ju do vyrovnávacej pamäte (prechodne) a potom odošle JSON späť do prehliadača.
- Prehliadač zobrazí odpoveď.
Prečo používať AJAX vo WordPresse (a nevolať AI API v JS)?
Pretože váš kľúč musí zostať na strane servera. Ak voláte OpenAI priamo z prehliadača, odhalíte kľúč... a stratíte kontrolu (náklady, zneužitie, scraping).
Kompletný kód – krok za krokom
Vytvoríme mu-plugin, ktorý:
- pridať krátky kód
[ai_chatbot] - Čisté zaradenie CSS/JS do frontu
- vytvára AJAX akciu pre prihlásených aj odhlásených používateľov
- volá rozhranie OpenAI API
- ukladá odpovede do vyrovnávacej pamäte
Krok 1 – Vytvorenie pluginu mu
Vytvorte priečinok wp-content/mu-plugins/ Ak neexistuje, vytvorte súbor:
wp-content/mu-plugins/bpcab-ai-chatbot.php
<?php
/**
* Plugin Name: BPCAB — Chatbot IA simple (sans plugin)
* Description: Ajoute un chatbot IA minimal via shortcode, avec appel serveur (wp_remote_post), cache transient, et sécurité de base.
* Author: Vous
* Version: 1.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
define('BPCAB_CHATBOT_VERSION', '1.0.0');
/**
* Petit helper : récupère l'IP (approx) pour rate limiting.
* Attention : derrière un proxy/CDN, l'IP peut être celle du proxy si mal configuré.
*/
function bpcab_get_client_ip(): string {
$keys = array('HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR');
foreach ($keys as $key) {
if (!empty($_SERVER[$key])) {
$ip = sanitize_text_field(wp_unslash($_SERVER[$key]));
// X-Forwarded-For peut contenir plusieurs IP : on prend la première.
if (str_contains($ip, ',')) {
$parts = explode(',', $ip);
$ip = trim($parts[0]);
}
return $ip;
}
}
return '0.0.0.0';
}
Krok 2 – Načítanie krátkeho kódu + CSS/JS
Un shortcode je tag v zátvorkách (napr. [ai_chatbot]), ktorý WordPress nahrádza HTML. Toto je pohodlné s Divi 5, Elementor a Avada: všetky vedia, ako vložiť shortcode (modul „Code“, widget „Shortcode“ atď.).
/**
* Enqueue des assets uniquement si le shortcode est présent sur la page.
*/
function bpcab_maybe_enqueue_assets(): void {
if (!is_singular()) {
return;
}
global $post;
if (!$post instanceof WP_Post) {
return;
}
if (!has_shortcode($post->post_content, 'ai_chatbot')) {
return;
}
$handle = 'bpcab-ai-chatbot';
wp_register_style(
$handle,
plugins_url('bpcab-ai-chatbot.css', __FILE__),
array(),
BPCAB_CHATBOT_VERSION
);
wp_register_script(
$handle,
plugins_url('bpcab-ai-chatbot.js', __FILE__),
array(),
BPCAB_CHATBOT_VERSION,
true
);
wp_enqueue_style($handle);
wp_enqueue_script($handle);
// Données côté JS (sans clé API !)
wp_localize_script($handle, 'BPCAB_CHATBOT', array(
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('bpcab_chatbot_nonce'),
'maxLen' => 400,
));
}
add_action('wp_enqueue_scripts', 'bpcab_maybe_enqueue_assets');
/**
* Shortcode [ai_chatbot]
*/
function bpcab_ai_chatbot_shortcode(): string {
// HTML volontairement simple, facile à styliser.
ob_start();
?>
<div class="bpcab-chatbot" data-bpcab-chatbot="1">
<div class="bpcab-chatbot__header">
<strong>Assistant</strong>
<span class="bpcab-chatbot__status" aria-live="polite">Prêt</span>
</div>
<div class="bpcab-chatbot__messages" role="log" aria-live="polite"></div>
<form class="bpcab-chatbot__form">
<input class="bpcab-chatbot__input" type="text" name="message" placeholder="Posez votre question…" autocomplete="off" />
<button class="bpcab-chatbot__send" type="submit">Envoyer</button>
</form>
<p class="bpcab-chatbot__hint">
<em>Réponse automatique. Ne partagez pas d’informations sensibles.</em>
</p>
</div>
<?php
return (string) ob_get_clean();
}
add_shortcode('ai_chatbot', 'bpcab_ai_chatbot_shortcode');
Častým problémom je vloženie tohto kódu do nesprávneho súboru (úryvok kódu pre builder alebo plugin úryvkov, ktorý sa spúšťa príliš neskoro). S pluginom mu sa vyhnete mnohým prekvapeniam.
Krok 3 – Vytvorenie súborov CSS/JS
V tom istom súbore mu-plugins, vytvoriť:
bpcab-ai-chatbot.cssbpcab-ai-chatbot.js
Minimálne CSS (Môžete si ho prispôsobiť téme/tvorcovi):
.bpcab-chatbot{
max-width: 520px;
border: 1px solid rgba(0,0,0,.12);
border-radius: 12px;
overflow: hidden;
background: #fff;
}
.bpcab-chatbot__header{
display:flex;
justify-content: space-between;
align-items:center;
padding: 12px 14px;
background: #111827;
color: #fff;
}
.bpcab-chatbot__messages{
padding: 12px 14px;
min-height: 220px;
max-height: 360px;
overflow:auto;
background: #f9fafb;
}
.bpcab-chatbot__msg{
margin: 0 0 10px 0;
padding: 10px 12px;
border-radius: 10px;
line-height: 1.35;
}
.bpcab-chatbot__msg--user{
background: #dbeafe;
}
.bpcab-chatbot__msg--bot{
background: #fff;
border: 1px solid rgba(0,0,0,.08);
}
.bpcab-chatbot__form{
display:flex;
gap: 8px;
padding: 12px 14px;
border-top: 1px solid rgba(0,0,0,.08);
background: #fff;
}
.bpcab-chatbot__input{
flex:1;
padding: 10px 12px;
border: 1px solid rgba(0,0,0,.18);
border-radius: 10px;
}
.bpcab-chatbot__send{
padding: 10px 14px;
border-radius: 10px;
border: 0;
background: #111827;
color: #fff;
cursor: pointer;
}
.bpcab-chatbot__hint{
padding: 0 14px 14px 14px;
margin: 0;
color: #6b7280;
font-size: 13px;
}
Minimálny JS Odosielanie správ do WordPressu pomocou AJAXu, zobrazovanie správ, správa stavu.
(function () {
function qs(root, sel) { return root.querySelector(sel); }
function addMsg(messagesEl, text, who) {
var p = document.createElement('p');
p.className = 'bpcab-chatbot__msg bpcab-chatbot__msg--' + who;
p.textContent = text;
messagesEl.appendChild(p);
messagesEl.scrollTop = messagesEl.scrollHeight;
}
function setStatus(root, text) {
var s = qs(root, '.bpcab-chatbot__status');
if (s) s.textContent = text;
}
function initChatbot(root) {
var form = qs(root, '.bpcab-chatbot__form');
var input = qs(root, '.bpcab-chatbot__input');
var messages = qs(root, '.bpcab-chatbot__messages');
if (!form || !input || !messages) return;
addMsg(messages, "Bonjour ! Posez votre question, je vais essayer de vous orienter.", "bot");
form.addEventListener('submit', function (e) {
e.preventDefault();
var msg = (input.value || '').trim();
if (!msg) return;
if (msg.length > (window.BPCAB_CHATBOT?.maxLen || 400)) {
addMsg(messages, "Message trop long. Essayez de faire plus court.", "bot");
return;
}
addMsg(messages, msg, "user");
input.value = '';
setStatus(root, 'Réflexion…');
var data = new FormData();
data.append('action', 'bpcab_chatbot_ask');
data.append('nonce', window.BPCAB_CHATBOT?.nonce || '');
data.append('message', msg);
fetch(window.BPCAB_CHATBOT?.ajaxUrl || '', {
method: 'POST',
credentials: 'same-origin',
body: data
})
.then(function (r) { return r.json(); })
.then(function (payload) {
if (!payload || !payload.success) {
var err = payload?.data?.message || "Erreur côté serveur.";
addMsg(messages, err, "bot");
setStatus(root, 'Erreur');
return;
}
addMsg(messages, payload.data.answer, "bot");
setStatus(root, 'Prêt');
})
.catch(function () {
addMsg(messages, "Impossible de contacter le serveur. Réessayez.", "bot");
setStatus(root, 'Hors ligne');
});
});
}
document.addEventListener('DOMContentLoaded', function () {
document.querySelectorAll('[data-bpcab-chatbot="1"]').forEach(initChatbot);
});
})();
Častá chyba: „JS sa nenačítava.“ V 90 % prípadov je to nesprávna cesta. plugins_url()alebo vyrovnávaciu pamäť (plugin/CDN), ktorá zobrazuje starú verziu. Zmeňte verziu BPCAB_CHATBOT_VERSION Vynútenie opätovného načítania alebo vymazanie vyrovnávacej pamäte.
Krok 4 – Koncový bod AJAX + nonce + limit rýchlosti
Un háčik WordPress je vstupný bod. Existujú dva typy:
- akčná „urobte tu niečo“ (napr.
wp_enqueue_scripts). - filtre : „upraviť túto hodnotu“ (napr.
the_content).
Tu používame akcie AJAX: wp_ajax_* (pripojené) a wp_ajax_nopriv_* (nie je pripojené).
/**
* Rate limit très simple : X requêtes par minute par IP.
* Ce n'est pas une protection parfaite, mais ça évite les abus basiques.
*/
function bpcab_rate_limit_or_die(string $ip, int $limit = 10, int $window_seconds = 60): void {
$key = 'bpcab_rl_' . md5($ip);
$hits = (int) get_transient($key);
if ($hits >= $limit) {
wp_send_json_error(array(
'message' => 'Trop de requêtes. Attendez une minute et réessayez.'
), 429);
}
set_transient($key, $hits + 1, $window_seconds);
}
/**
* Handler AJAX : reçoit la question et renvoie une réponse IA.
*/
function bpcab_ajax_chatbot_ask(): void {
// Vérification nonce (anti-CSRF)
$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
if (!wp_verify_nonce($nonce, 'bpcab_chatbot_nonce')) {
wp_send_json_error(array('message' => 'Requête refusée (nonce invalide).'), 403);
}
$ip = bpcab_get_client_ip();
bpcab_rate_limit_or_die($ip, 10, 60);
$message = isset($_POST['message']) ? (string) wp_unslash($_POST['message']) : '';
$message = trim($message);
if ($message === '') {
wp_send_json_error(array('message' => 'Message vide.'), 400);
}
if (mb_strlen($message) > 400) {
wp_send_json_error(array('message' => 'Message trop long (max 400 caractères).'), 400);
}
$answer = bpcab_get_ai_answer($message);
if (is_wp_error($answer)) {
wp_send_json_error(array(
'message' => $answer->get_error_message()
), 500);
}
wp_send_json_success(array(
'answer' => $answer,
));
}
add_action('wp_ajax_bpcab_chatbot_ask', 'bpcab_ajax_chatbot_ask');
add_action('wp_ajax_nopriv_bpcab_chatbot_ask', 'bpcab_ajax_chatbot_ask');
Krok 5 – Volanie OpenAI cez wp_remote_post() + prechodné ukladanie do vyrovnávacej pamäte
Ideme na to:
- Vytvorte kľúč vyrovnávacej pamäte na základe otázky (hash).
- Nastavte si TTL (napr. 24 hodín), aby ste sa vyhli opätovnému plateniu za tú istú odpoveď.
- Pridajte krátky časový limit (napr. 20 sekúnd), aby ste zabránili „zaseknutiu“ PHP.
- Vyčistite odpoveď (povolená je veľmi obmedzená podmnožina HTML).
/**
* Appelle l'API IA (OpenAI) et renvoie une réponse texte.
* IMPORTANT : la clé API doit être définie dans wp-config.php via BPCAB_OPENAI_API_KEY
*/
function bpcab_get_ai_answer(string $user_message) {
if (!defined('BPCAB_OPENAI_API_KEY') || BPCAB_OPENAI_API_KEY === '') {
return new WP_Error('bpcab_missing_key', 'Clé API manquante. Ajoutez BPCAB_OPENAI_API_KEY dans wp-config.php.');
}
// Cache : même question => même réponse pendant 24h
$cache_key = 'bpcab_ai_' . md5(mb_strtolower(trim($user_message)));
$cached = get_transient($cache_key);
if (is_string($cached) && $cached !== '') {
return $cached;
}
/**
* Prompt système : court, orienté "site".
* Ici, on ne fait PAS encore de RAG (recherche dans vos contenus).
* On limite la responsabilité : pas de conseils médicaux/juridiques.
*/
$system = "Vous êtes un assistant pour un site WordPress. Répondez en français, de façon courte et pratique. "
. "Si la question demande des infos sensibles (santé/juridique/finance), refusez et conseillez de contacter le propriétaire du site. "
. "Si vous ne savez pas, dites-le et proposez une piste (ex: consulter la page FAQ).";
/**
* API OpenAI (Chat Completions style Responses API selon évolution).
* En avril 2026, l'API a évolué plusieurs fois. Le principe reste :
* - endpoint HTTPS
* - JSON en entrée
* - JSON en sortie
*
* Si votre compte OpenAI recommande un endpoint différent, adaptez l'URL et le parsing.
* Référez-vous à la doc officielle.
*/
$endpoint = 'https://api.openai.com/v1/chat/completions';
$body = array(
'model' => 'gpt-4.1-mini',
'temperature' => 0.2,
'messages' => array(
array('role' => 'system', 'content' => $system),
array('role' => 'user', 'content' => $user_message),
),
);
$args = array(
'headers' => array(
'Authorization' => 'Bearer ' . BPCAB_OPENAI_API_KEY,
'Content-Type' => 'application/json',
),
'timeout' => 20,
'body' => wp_json_encode($body),
);
$response = wp_remote_post($endpoint, $args);
if (is_wp_error($response)) {
return new WP_Error('bpcab_http_error', 'Erreur HTTP : ' . $response->get_error_message());
}
$code = (int) wp_remote_retrieve_response_code($response);
$raw = (string) wp_remote_retrieve_body($response);
if ($code < 200 || $code >= 300) {
// On évite d'afficher tout le raw (peut contenir des détails techniques).
return new WP_Error('bpcab_api_error', 'API IA indisponible (code ' . $code . '). Vérifiez votre clé/quota.');
}
$data = json_decode($raw, true);
if (!is_array($data)) {
return new WP_Error('bpcab_json_error', 'Réponse API illisible (JSON invalide).');
}
// Parsing "chat.completions"
$text = $data['choices'][0]['message']['content'] ?? '';
$text = is_string($text) ? trim($text) : '';
if ($text === '') {
return new WP_Error('bpcab_empty_answer', 'Réponse vide de l’API IA.');
}
/**
* Assainissement :
* - on autorise un peu de HTML basique (liens, strong, em, br)
* - on supprime le reste
*/
$allowed = array(
'a' => array(
'href' => true,
'target' => true,
'rel' => true,
),
'strong' => array(),
'em' => array(),
'br' => array(),
);
$safe = wp_kses($text, $allowed);
// Cache 24h
set_transient($cache_key, $safe, DAY_IN_SECONDS);
return $safe;
}
Dve chyby, ktoré často vidím:
- Zabudnutie bodkočiarky v
wp-config.phpalebo v mu-plugine: výsledok, biela obrazovka (fatálna chyba). AktivovaťWP_DEBUGV štádiu prípravy, nie v produkcii. - Skopírujte starý tutoriál ktorý používa starú štruktúru API alebo zastaraný model. V tomto prípade máte základ WordPress 6.9.4 + PHP 8.1 a koncový bod upravujete iba v prípade, že OpenAI zmení svoje odporúčanie.
Kompletný zostavený kód
Nižšie je uvedený kompletný súbor mu-pluginBudete tiež musieť vytvoriť súbory CSS/JS (zobrazené vyššie). Kľúč do tohto súboru nevkladajte.
<?php
/**
* Plugin Name: BPCAB — Chatbot IA simple (sans plugin)
* Description: Chatbot IA minimal via shortcode, AJAX WordPress, appel OpenAI avec wp_remote_post(), cache transient, sécurité de base.
* Author: Vous
* Version: 1.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
define('BPCAB_CHATBOT_VERSION', '1.0.0');
function bpcab_get_client_ip(): string {
$keys = array('HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR');
foreach ($keys as $key) {
if (!empty($_SERVER[$key])) {
$ip = sanitize_text_field(wp_unslash($_SERVER[$key]));
if (str_contains($ip, ',')) {
$parts = explode(',', $ip);
$ip = trim($parts[0]);
}
return $ip;
}
}
return '0.0.0.0';
}
function bpcab_maybe_enqueue_assets(): void {
if (!is_singular()) {
return;
}
global $post;
if (!$post instanceof WP_Post) {
return;
}
if (!has_shortcode($post->post_content, 'ai_chatbot')) {
return;
}
$handle = 'bpcab-ai-chatbot';
wp_register_style(
$handle,
plugins_url('bpcab-ai-chatbot.css', __FILE__),
array(),
BPCAB_CHATBOT_VERSION
);
wp_register_script(
$handle,
plugins_url('bpcab-ai-chatbot.js', __FILE__),
array(),
BPCAB_CHATBOT_VERSION,
true
);
wp_enqueue_style($handle);
wp_enqueue_script($handle);
wp_localize_script($handle, 'BPCAB_CHATBOT', array(
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('bpcab_chatbot_nonce'),
'maxLen' => 400,
));
}
add_action('wp_enqueue_scripts', 'bpcab_maybe_enqueue_assets');
function bpcab_ai_chatbot_shortcode(): string {
ob_start();
?>
<div class="bpcab-chatbot" data-bpcab-chatbot="1">
<div class="bpcab-chatbot__header">
<strong>Assistant</strong>
<span class="bpcab-chatbot__status" aria-live="polite">Prêt</span>
</div>
<div class="bpcab-chatbot__messages" role="log" aria-live="polite"></div>
<form class="bpcab-chatbot__form">
<input class="bpcab-chatbot__input" type="text" name="message" placeholder="Posez votre question…" autocomplete="off" />
<button class="bpcab-chatbot__send" type="submit">Envoyer</button>
</form>
<p class="bpcab-chatbot__hint">
<em>Réponse automatique. Ne partagez pas d’informations sensibles.</em>
</p>
</div>
<?php
return (string) ob_get_clean();
}
add_shortcode('ai_chatbot', 'bpcab_ai_chatbot_shortcode');
function bpcab_rate_limit_or_die(string $ip, int $limit = 10, int $window_seconds = 60): void {
$key = 'bpcab_rl_' . md5($ip);
$hits = (int) get_transient($key);
if ($hits >= $limit) {
wp_send_json_error(array(
'message' => 'Trop de requêtes. Attendez une minute et réessayez.'
), 429);
}
set_transient($key, $hits + 1, $window_seconds);
}
function bpcab_get_ai_answer(string $user_message) {
if (!defined('BPCAB_OPENAI_API_KEY') || BPCAB_OPENAI_API_KEY === '') {
return new WP_Error('bpcab_missing_key', 'Clé API manquante. Ajoutez BPCAB_OPENAI_API_KEY dans wp-config.php.');
}
$cache_key = 'bpcab_ai_' . md5(mb_strtolower(trim($user_message)));
$cached = get_transient($cache_key);
if (is_string($cached) && $cached !== '') {
return $cached;
}
$system = "Vous êtes un assistant pour un site WordPress. Répondez en français, de façon courte et pratique. "
. "Si la question demande des infos sensibles (santé/juridique/finance), refusez et conseillez de contacter le propriétaire du site. "
. "Si vous ne savez pas, dites-le et proposez une piste (ex: consulter la page FAQ).";
$endpoint = 'https://api.openai.com/v1/chat/completions';
$body = array(
'model' => 'gpt-4.1-mini',
'temperature' => 0.2,
'messages' => array(
array('role' => 'system', 'content' => $system),
array('role' => 'user', 'content' => $user_message),
),
);
$args = array(
'headers' => array(
'Authorization' => 'Bearer ' . BPCAB_OPENAI_API_KEY,
'Content-Type' => 'application/json',
),
'timeout' => 20,
'body' => wp_json_encode($body),
);
$response = wp_remote_post($endpoint, $args);
if (is_wp_error($response)) {
return new WP_Error('bpcab_http_error', 'Erreur HTTP : ' . $response->get_error_message());
}
$code = (int) wp_remote_retrieve_response_code($response);
$raw = (string) wp_remote_retrieve_body($response);
if ($code < 200 || $code >= 300) {
return new WP_Error('bpcab_api_error', 'API IA indisponible (code ' . $code . '). Vérifiez votre clé/quota.');
}
$data = json_decode($raw, true);
if (!is_array($data)) {
return new WP_Error('bpcab_json_error', 'Réponse API illisible (JSON invalide).');
}
$text = $data['choices'][0]['message']['content'] ?? '';
$text = is_string($text) ? trim($text) : '';
if ($text === '') {
return new WP_Error('bpcab_empty_answer', 'Réponse vide de l’API IA.');
}
$allowed = array(
'a' => array('href' => true, 'target' => true, 'rel' => true),
'strong' => array(),
'em' => array(),
'br' => array(),
);
$safe = wp_kses($text, $allowed);
set_transient($cache_key, $safe, DAY_IN_SECONDS);
return $safe;
}
function bpcab_ajax_chatbot_ask(): void {
$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
if (!wp_verify_nonce($nonce, 'bpcab_chatbot_nonce')) {
wp_send_json_error(array('message' => 'Requête refusée (nonce invalide).'), 403);
}
$ip = bpcab_get_client_ip();
bpcab_rate_limit_or_die($ip, 10, 60);
$message = isset($_POST['message']) ? (string) wp_unslash($_POST['message']) : '';
$message = trim($message);
if ($message === '') {
wp_send_json_error(array('message' => 'Message vide.'), 400);
}
if (mb_strlen($message) > 400) {
wp_send_json_error(array('message' => 'Message trop long (max 400 caractères).'), 400);
}
$answer = bpcab_get_ai_answer($message);
if (is_wp_error($answer)) {
wp_send_json_error(array(
'message' => $answer->get_error_message()
), 500);
}
wp_send_json_success(array('answer' => $answer));
}
add_action('wp_ajax_bpcab_chatbot_ask', 'bpcab_ajax_chatbot_ask');
add_action('wp_ajax_nopriv_bpcab_chatbot_ask', 'bpcab_ajax_chatbot_ask');
Vysvetlenie kódu
Prečo mu-plugin?
MU-plugin sa načíta automaticky, bez aktivácie, a je menej „krehký“ ako úryvok kódu vložený do témy. Podľa mojej skúsenosti, keď začiatočník vloží kód do functions.php a potom zmení tému (alebo aktualizuje nadradenú tému), chatbot zmizne.
Pourquoi wp_localize_script()
Tu ho používame na prepnutie do JS:
- URL adresa AJAX (
admin-ajax.php) - nuncius
- obmedzenie dĺžky
Tým sa zabráni „pevnému kódovaniu“ URL adresy a funguje to, aj keď je WordPress nainštalovaný v podpriečinku.
Dokument: wp_localize_script ().
Nonce: čo to vlastne chráni
Jednoduchý kód WordPressu bráni inej stránke v odosielaní požiadaviek vo vašom mene prostredníctvom prehliadača vášho návštevníka (útok CSRF). Nenahrádza autentifikačný systém, ale pre verejného chatbota je to minimálna požiadavka.
Dokument: Nonce vo WordPresse.
Prechodové javy vyrovnávacej pamäte: Prečo je to dôležité
Les transients Ide o vyrovnávaciu pamäť kľúč/hodnota s dátumom expirácie. Ak sa návštevník 200-krát za mesiac opýta „Aká je vaša pracovná doba?“, nechcete platiť za 200 volaní umelej inteligencie. Zaplatíte za jedno volanie a potom zobrazíte odpoveď z vyrovnávacej pamäte.
Dokument: Prechodné javy API.
Čistenie reakcie
API rozhranie AI môže vrátiť neočakávaný text (alebo dokonca HTML). Ak ho vložíte priamo do DOM, otvoríte dvere zraniteľnostiam XSS. Tu:
- povoľujeme iba
a,strong,em,br - všetko ostatné je vymazané
Použitá funkcia: wp_kses()Dokument: wp_kses().
Náklady na API a optimalizácia
Presné ceny závisia od modelu a vašej zmluvy. Tu je to, čo je dôležité pre odhad:
- počet správ za mesiac
- priemerná dĺžka otázok a odpovedí (tokeny)
- miera úspešnosti vo vyrovnávacej pamäti (koľko identických otázok sa opakuje)
Odhad „na mieste“ (rádová hodnota)
Na jednoduchom „orientačnom“ chatbote často pozorujem:
- Otázka: 20 až 60 žetónov
- Odpoveď: 60 až 200 žetónov
- Celkom: 100 až 300 tokenov na interakciu
Ak máte 2 000 interakcií mesačne, je to 200 000 až 600 000 tokenov mesačne. V závislosti od modelu to môže byť rozumné... alebo nie. Ukladanie do vyrovnávacej pamäte a „mini“ model majú obrovský význam.
Okamžité optimalizácie
- 24-hodinová keška (už zavedené). Pre stabilné FAQ môžete interval predĺžiť na 7 dní.
- Kratšie odpovede doplniť k výzve „odpovedať maximálne v 5 vetách“.
- Nízka teplota Menej variácií, viac zásahov do vyrovnávacej pamäte.
- Obmedziť dĺžku Správy na strane JS aj PHP (už sú zavedené). Vždy dvojitá bariéra.
Pokročilé varianty a prípady použitia
Variant 1 – Pridanie „kontextu lokality“ (bez RAG)
Bez prehľadávania článkov môžete poskytnúť stručný statický kontext (napr. otváracie hodiny, URL adresu často kladených otázok). Toto je užitočné pre prezentačnú webovú stránku.
// Exemple : ajoutez ceci avant $body dans bpcab_get_ai_answer()
$site_context = "Contexte du site :n"
. "- FAQ : https://example.com/faq/n"
. "- Contact : https://example.com/contact/n"
. "- Horaires : lun-ven 9h-18hn";
$body['messages'] = array(
array('role' => 'system', 'content' => $system . "nn" . $site_context),
array('role' => 'user', 'content' => $user_message),
);
Variant 2 – Režim „Zhrnutie článku“ prostredníctvom atribútu shortcode
Môžete povoliť [ai_chatbot mode="resume"] a odoslať aktuálny výpis stránky umelej inteligencii. Poznámka: viac tokenov = vyššie náklady.
// Exemple (incomplet) : détecter un attribut et injecter le contenu
function bpcab_ai_chatbot_shortcode($atts = array()): string {
$atts = shortcode_atts(array('mode' => 'chat'), $atts, 'ai_chatbot');
// ... même HTML qu'avant, mais vous pourriez ajouter data-mode
// <div data-mode="chat"> etc.
// Ce snippet est volontairement partiel : il faut adapter le JS pour envoyer le mode.
return '...';
}
Aby som to uviedol na pravú mieru: tento úryvok je neúplný. Aby fungoval, je potrebné upraviť aj JavaScript (odoslať mode) a obslužný program AJAX (zmeniť výzvu podľa režimu).
Variant 3 — Divi 5 / Elementor / integrácia Avada
- Divi 5 Pridajte modul „Kód“ alebo „Krátky kód“ a vložte ho
[ai_chatbot]Ak Divi minifikuje/zreťazuje, vymažte jeho statickú vyrovnávaciu pamäť, ak sa CSS/JS neaktualizuje. - Elementor widget „Krátky kód“ →
[ai_chatbot]Ak používate optimalizáciu aktív Elementoru, skontrolujte, či skript nie je agresívne odložený (inakDOMContentLoadedmôže sa stať pred injekciou: v tomto prípade inicializujte aj naelementor/frontend/init). - Avada Prvok „Shortcode“ vo Fusion Builderi. Ak máte ukladanie do vyrovnávacej pamäte Avada, po pridaní súborov CSS/JS ich vymažte.
Bezpečnosť a osvedčené postupy
Nikdy nezverejňujte kľúč API na strane klienta
Jednoduché pravidlo: kľúč zostáva vnútri wp-config.phpPrehliadač by ho nikdy nemal vidieť. Aj keď je „skrytý“ v JS balíku, je stále obnoviteľný.
Overiť a obmedziť položky
- Maximálna dĺžka na strane JS (UX) + na strane PHP (bezpečnosť).
- Odmietnuť prázdne správy.
- Obmedzenie rýchlosti podľa IP adresy (už je zavedené). Ak chcete ísť ďalej, môžete obmedziť aj podľa relácie/súboru cookie.
Vyčistite východy
Zobraziť odpoveď ako text (ako v JS s textContent) alebo dôkladne dezinfikujeme, ak povolíte HTML. Tu robíme oboje: dezinfikujeme na strane servera a zobrazujeme ako text na strane klienta. Toto je zámerne „paranoidné“.
GDPR: údaje odoslané tretej strane
Ak návštevník zadá osobné údaje, potenciálne ich odosielate poskytovateľovi služieb (OpenAI). Naplánujte si to podľa toho:
- jasný odkaz („Nezdieľajte citlivé informácie.“)
- zmienka vo vašich zásadách ochrany osobných údajov
- Nastavenia dodávateľa (udržiavanie, odhlásenie atď.) podľa vašej zmluvy
Netestujte v produkcii bez zálohy.
MU-plugin s chybou PHP pokazí celú stránku (pretože sa načítava automaticky). Najprv pracujte na testovacej kópii. Ak potrebujete pracovať v produkčnom prostredí, udržujte prístup cez FTP/SSH, aby ste mohli súbor odstrániť v prípade bielej obrazovky.
Ako testovať a ladiť
Správne povoliť protokoly
V testovacom prostredí povoľte:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Dokument: Ladenie vo WordPresse.
Skontrolujte požiadavku AJAX
- Otvorte v prehliadači DevTools → kartu Sieť → zapnite filter
admin-ajax.php. - Skontrolujte stav HTTP (200/403/429/500) a odpoveď JSON.
- Ak sa namiesto JSON zobrazí HTML stránka, často ide o fatálnu chybu PHP (alebo bezpečnostný doplnok, ktorý zachytáva stránku).
Testovanie AI API „na suchu“
Pred integráciou JS môžete zavolať bpcab_get_ai_answer() v administrátorskom kontexte (dočasne) a zaznamenať odpoveď. Tento kód nenechávajte na mieste.
Ak to nefunguje
| symptóm | Príčina pravdepodobná | overenie | Riešenie |
|---|---|---|---|
| Na stránke sa nič nezobrazuje | Chýbajúci alebo neinterpretovaný skrátený kód | Skontrolujte, či stránka obsahuje [ai_chatbot] (nie v bloku „Kód“, ktorý escape zátvorky) |
Použite blok „Shortcode“ (Elementor) / modul Shortcode (Divi/Avada) |
| Okno chatu sa zobrazí, ale tlačidlo nereaguje | JavaScript sa nenačítal (vyrovnávacia pamäť, cesta, konflikt) | Nástroje pre vývojárov → Konzola (chyby) + Sieť (JS súbor 404?) | check plugins_url()vymazať vyrovnávaciu pamäť, prírastok BPCAB_CHATBOT_VERSION |
| Odpoveď „neplatná žiadna“ | Platnosť nonce vypršala, agresívna vyrovnávacia pamäť stránky alebo JS prijíma starý nonce | Pozrite sa na hodnotu BPCAB_CHATBOT.nonce v konzole |
Znížte vyrovnávaciu pamäť na stránkach s chatom alebo regenerujte nonce pri načítaní (pokročilejší prístup) |
| Chyba 429 „Príliš veľa požiadaviek“ | Príliš prísne limity frekvencií alebo opakované testovanie | Reprodukovať v súkromnom prehliadaní / s inou IP adresou | Zväčšiť okno/limit alebo obmedziť na prihlásených používateľov |
| Chyba „Rozhranie API umelej inteligencie nie je k dispozícii (kód 401/403)“ | Neplatný kľúč, kľúč nebol načítaný, povolenia | check BPCAB_OPENAI_API_KEY v wp-config.php (bez medzier) |
Znovu vygenerujte kľúč, skontrolujte fakturáciu/kvótu na strane dodávateľa |
| Chyba „Neplatný JSON“ | Skrátená odpoveď API (proxy, WAF) alebo zmenený koncový bod | Prihlásiť sa $raw v štádiu (všimnite si údaje) |
Upravte koncový bod/formát podľa oficiálnej dokumentácie, v prípade potreby predĺžte časový limit. |
| Biela obrazovka po pridaní pluginu mu | Chyba PHP (zátvorka, bodkočiarka), verzia PHP je príliš stará | konzultovať wp-content/debug.log alebo protokoly servera |
Opravte syntax, skontrolujte PHP 8.1+, v prípade potreby súbor vymažte cez FTP |
Realistické problémy a rýchle riešenia
- Kód vložený na nesprávne miesto Ak ste ho umiestnili do sekcie „Vlastný kód“ v nástroji na tvorbu, môže byť filtrovaný/escaped. Namiesto toho použite mu-plugin.
- Nevhodný háčik : ak zadáte dotaz na JS na
initRiskujete, že ho načítate príliš skoro/nesprávne. Tu používamewp_enqueue_scripts. - Konflikt vyrovnávacej pamäte Niektoré vyrovnávacie pamäte ukladajú HTML kód obsahujúci nonce. Výsledok: zastaraný nonce pre všetkých. Riešenie: vylúčte stránku z vyrovnávacej pamäte alebo implementujte trasu, ktorá vracia „nový“ nonce (pokročilý variant).
- permalinks Nesúvisí to priamo, ale videl som stránky, kde
admin_url()je filtrované nesprávne nakonfigurovaným bezpečnostným doplnkom. Ak AJAX nereaguje, otestujte URL adresu/wp-admin/admin-ajax.phppriamo v prehliadači.
zdroje
- HTTP API pre WordPress (wp_remote_post)
- API prechodných javov (vyrovnávacia pamäť)
- Jednorazové čísla (zabezpečenie)
- wp_kses() (sanitácia)
- Ladenie WordPressu (WP_DEBUG)
- Dokumentácia k OpenAI API
- PHP reťazec mbstring (mb_strlen)
- Oficiálny repozitár WordPressu (wordpress-develop)
Často kladené otázky
Je to naozaj „bez pluginov“, ak pridám mu-plugin?
Neinštalujete plugin tretej strany z wordpress.org, ale technicky pridávate kód vo forme pluginu. Toto je zámerné: je to najčistejší spôsob, ako udržať kód nezávislý od témy.
Môžem vložiť kód functions.php ?
Áno, ale neodporúčam to. Pri zmene tém riskujete stratu chatbota a nástroj na tvorbu tém môže skomplikovať ladenie. Ak to aj tak urobíte, použite podradenú tému.
Prečo používať admin-ajax.php namiesto REST API?
Obe fungujú. Pre začiatočníka sa AJAX WordPress rýchlo nastavuje. Ak chcete modernejší prístup, prejdite na REST trasu s register_rest_route() a oprávnenia na spätné volanie. Jadro (volanie wp_remote_post()(vyrovnávacia pamäť, zabezpečenie) zostáva rovnaké.
Kód nonce sa pokazí s mojím doplnkom pre ukladanie do vyrovnávacej pamäte: čo mám robiť?
Vylúčte stránku z vyrovnávacej pamäte (jednoduché riešenie) alebo implementujte koncový bod, ktorý na požiadanie vráti hodnotu nonce, a potom aktualizujte JS, aby ju načítal. Na stránkach s vysokou mierou vyrovnávacej pamäte (agresívna CDN) je to klasický prístup.
Ako môžem obmedziť chatbota na určité stránky?
Shortcode vám už poskytuje túto kontrolu: pridáte ho iba tam, kde ho potrebujete. A kód sa dotazuje na JS/CSS iba v prípade, že je shortcode prítomný.
Ako môžeme zabrániť umelej inteligencii v šírení nezmyslov?
Nemôžete to zaručiť na 100 %. Znížte riziko:
- krátke odpovede
- nízka teplota
- Odkaz je jasný: „Ak nevieš, povedz to.“
- Presmerovanie na vaše najčastejšie otázky/kontakt
Môžem v odpovedi zobraziť klikateľné odkazy?
Áno, ale robte to opatrne. V tomto návode si to vyčistíme pomocou wp_kses() autorizáciou aNa strane JS zobrazujeme pomocou textContent (takže žiadny HTML). Ak chcete klikateľné odkazy, musíte ich zobraziť v HTML (innerHTML) a postupovať s mimoriadnou opatrnosťou (prísna hygiena, automatické pridávanie rel="noopener nofollow").
Je kompatibilný s Divi 5 / Elementor / Avada?
Áno: použite modul/widget „Shortcode“ a vložte ho [ai_chatbot]Kód je nezávislý od témy. Jediné problémy zvyčajne vznikajú pri ukladaní do vyrovnávacej pamäte/minifikacii: vymazanie po pridaní súborov.
Prečo to obmedzujete na 400 znakov?
Aby ste sa vyhli obrovskému počtu výziev, znížili náklady a obmedzili zneužívanie, môžete ich počet zvýšiť, ale urobte tak s plným vedomím dôsledkov (tokeny, latencia, fakturácia).
Ako zmeniť model umelej inteligencie?
Zmeňte hodnotu model v $bodyPonechajte si „mini“ model pre chatbota s pokynmi. Ak sa rozširujete, monitorujte náklady a latenciu.
Zobrazuje sa mi chyba „HTTP chyba: cURL chyba 28“
Je to časový limit. Skontrolujte:
- Prístup k sieti povolený z hostiteľského servera (firewall)
- DNS
- zvýšenie
timeout(napr. 30), ak je váš server pomalý
Ak máte uzamknutý zdieľaný hostingový plán, je to bežné.