Sei un recruiter? Clicca qui!
Chatbot AI in WordPress con Groq guida pratica per inserirlo nel sito senza appesantirlo

Chatbot AI in WordPress con Groq: guida pratica per inserirlo nel sito senza appesantirlo

Scritto da Sergio Pinna il

08/05/2026

Inserire un chatbot in un sito WordPress può sembrare una cosa “da grande piattaforma”, ma oggi è molto più accessibile. Non serve per forza installare plugin pesanti, creare account su mille servizi o caricare script esterni che rallentano il sito. Con uno snippet ben costruito possiamo creare un piccolo assistente AI direttamente dentro WordPress, collegarlo a Groq e mostrare un box di chat nelle pagine pubbliche del sito.

L’idea di base è semplice: il visitatore scrive un messaggio nel chatbot, WordPress riceve la richiesta tramite una rotta REST personalizzata, il server contatta Groq usando una API key privata e poi restituisce la risposta al browser. La cosa importante è proprio questa: la chiave API non deve mai finire nel JavaScript visibile agli utenti. Groq espone un’API compatibile in larga parte con quella di OpenAI e documenta come base URL https://api.groq.com/openai/v1; per le chat, l’endpoint ufficiale è https://api.groq.com/openai/v1/chat/completions.

Perché usare un chatbot in un sito WordPress

Un chatbot non deve sostituire il sito, il form contatti o il lavoro umano. Deve fare una cosa più semplice: aiutare l’utente a orientarsi.

In un sito professionale può servire per rispondere a domande frequenti, spiegare i servizi, guidare verso la pagina contatti, chiarire come richiedere un preventivo o suggerire il contenuto giusto da leggere. Per esempio, in un sito da web designer il chatbot può aiutare l’utente a capire la differenza tra sito vetrina, landing page, restyling, SEO tecnica, manutenzione WordPress e ottimizzazione delle performance.

Il vantaggio è che l’interazione diventa più immediata. Invece di obbligare l’utente a cercare da solo tra menu, articoli e pagine, gli offri un piccolo punto di supporto sempre disponibile.

Perché usare Groq

Groq è interessante perché permette di usare modelli AI tramite API con un’impostazione molto familiare per chi ha già visto API compatibili con OpenAI. La documentazione ufficiale indica infatti una compatibilità “mostly compatible” con librerie e struttura OpenAI, cosa che rende più semplice adattare codice e logiche già conosciute.

Groq mette a disposizione una lista aggiornata di modelli supportati nella sua documentazione. Tra i modelli di produzione risulta disponibile, ad esempio, llama-3.1-8b-instant, che è adatto a risposte rapide e leggere per un chatbot di sito. Per progetti più esigenti si può valutare un modello più potente, ma per un assistente informativo semplice conviene partire da un modello veloce e poco costoso.

Architettura corretta: browser, WordPress, Groq

La struttura migliore è questa:

  1. Il visitatore apre il sito WordPress.
  2. Il sito mostra il bottone del chatbot.
  3. Il visitatore scrive una domanda.
  4. Il JavaScript invia la domanda a WordPress.
  5. WordPress riceve la domanda tramite REST API.
  6. WordPress chiama Groq dal server usando la API key.
  7. Groq restituisce la risposta a WordPress.
  8. WordPress manda la risposta al browser.
  9. Il chatbot la mostra all’utente.

Questo passaggio server-side è fondamentale. OWASP segnala che chiavi API, token e credenziali non dovrebbero essere esposti in URL o parti facilmente intercettabili, e in generale è buona pratica evitare di hardcodare informazioni sensibili nel frontend.

WordPress è adatto a questo tipo di integrazione perché permette di creare endpoint personalizzati con register_rest_route(), da registrare sull’hook rest_api_init.

Cosa serve prima di iniziare

Per questa guida servono:

  • un sito WordPress funzionante;
  • accesso da amministratore;
  • il plugin Code Snippets, oppure un piccolo plugin personalizzato;
  • un account Groq;
  • una API key Groq;
  • una pagina contatti, ad esempio /contatti/.

Il plugin Code Snippets è comodo perché permette di aggiungere funzionalità senza modificare direttamente il file functions.php del tema. La scheda ufficiale del plugin lo descrive proprio come un modo per aggiungere snippet senza intervenire manualmente nei file del tema.

Procedura passo passo

1. Crea una API key su Groq

Accedi alla console Groq, crea una nuova API key e copiala. La documentazione ufficiale consiglia di gestire la chiave come variabile d’ambiente, perché così si riduce il rischio di inserirla per errore nel codice sorgente.

In WordPress, la soluzione migliore sarebbe inserirla in wp-config.php, per esempio così:

define( 'SERGIO_GROQ_CHATBOT_API_KEY', 'LA_TUA_API_KEY_GROQ' );

Poi nello snippet non dovresti più scrivere la chiave. Però, per rendere lo snippet completo e subito utilizzabile, qui sotto trovi anche il punto in cui inserire direttamente la chiave dentro Code Snippets. Non è la soluzione più elegante, ma resta comunque server-side: non viene stampata nel JavaScript del frontend.

2. Installa Code Snippets

Da WordPress vai su:

Plugin → Aggiungi nuovo → cerca “Code Snippets” → Installa → Attiva

Poi vai su:

Snippet → Aggiungi nuovo

Dai un nome allo snippet, per esempio:

Chatbot AI WordPress con Groq

Imposta l’esecuzione su tutto il sito, perché sarà il codice stesso a evitare admin, REST, AJAX e contesti non necessari.

3. Incolla lo snippet completo

Nel box PHP di Code Snippets incolla questo codice senza aggiungere il tag <?php iniziale.

if ( ! defined( 'ABSPATH' ) ) {
exit;
}

/**
* Chatbot AI per WordPress collegato a Groq.
*
* Cosa fa:
* - mostra un piccolo chatbot nelle pagine pubbliche del sito;
* - usa WordPress REST API come ponte server-side;
* - non espone la chiave Groq nel frontend;
* - usa un rate limit base per IP;
* - mantiene una piccola cronologia lato browser;
* - guida l'utente verso la pagina Contatti;
* - include PHP, CSS e JavaScript in un unico snippet.
*/

/**
* 1. CONFIGURAZIONE BASE
*
* Soluzione migliore:
* definire SERGIO_GROQ_CHATBOT_API_KEY in wp-config.php.
*
* Soluzione veloce:
* sostituire INSERISCI_LA_TUA_API_KEY_GROQ con la tua API key.
*/
if ( ! defined( 'SERGIO_GROQ_CHATBOT_API_KEY' ) ) {
define( 'SERGIO_GROQ_CHATBOT_API_KEY', 'INSERISCI_LA_TUA_API_KEY_GROQ' );
}

if ( ! defined( 'SERGIO_GROQ_CHATBOT_MODEL' ) ) {
define( 'SERGIO_GROQ_CHATBOT_MODEL', 'llama-3.1-8b-instant' );
}

if ( ! defined( 'SERGIO_GROQ_CHATBOT_ENDPOINT' ) ) {
define( 'SERGIO_GROQ_CHATBOT_ENDPOINT', 'https://api.groq.com/openai/v1/chat/completions' );
}

if ( ! defined( 'SERGIO_GROQ_CHATBOT_MAX_INPUT_CHARS' ) ) {
define( 'SERGIO_GROQ_CHATBOT_MAX_INPUT_CHARS', 600 );
}

if ( ! defined( 'SERGIO_GROQ_CHATBOT_MAX_HISTORY_MESSAGES' ) ) {
define( 'SERGIO_GROQ_CHATBOT_MAX_HISTORY_MESSAGES', 8 );
}

if ( ! defined( 'SERGIO_GROQ_CHATBOT_RATE_LIMIT' ) ) {
define( 'SERGIO_GROQ_CHATBOT_RATE_LIMIT', 12 );
}

if ( ! defined( 'SERGIO_GROQ_CHATBOT_RATE_WINDOW' ) ) {
define( 'SERGIO_GROQ_CHATBOT_RATE_WINDOW', 5 * MINUTE_IN_SECONDS );
}

/**
* 2. DECIDE DOVE CARICARE IL CHATBOT
*/
function sergio_groq_chatbot_should_load() {

if (
is_admin() ||
wp_doing_ajax() ||
wp_doing_cron() ||
( defined( 'REST_REQUEST' ) && REST_REQUEST )
) {
return false;
}

/*
* Qui puoi escludere pagine specifiche.
* Esempio:
*
* if ( is_page( array( 'privacy-policy', 'cookie-policy' ) ) ) {
* return false;
* }
*/

return true;
}

/**
* 3. REGISTRA LA ROTTA REST DI WORDPRESS
*/
add_action( 'rest_api_init', 'sergio_groq_chatbot_register_rest_route' );

function sergio_groq_chatbot_register_rest_route() {

register_rest_route(
'sergio-groq-chatbot/v1',
'/message',
array(
'methods' => 'POST',
'callback' => 'sergio_groq_chatbot_handle_message',
'permission_callback' => '__return_true',
)
);
}

/**
* 4. RATE LIMIT BASE PER IP
*/
function sergio_groq_chatbot_get_ip_hash() {

$ip = isset( $_SERVER['REMOTE_ADDR'] )
? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) )
: 'unknown';

return hash( 'sha256', wp_salt( 'nonce' ) . '|' . $ip );
}

function sergio_groq_chatbot_rate_limit_is_allowed() {

$key = 'sergio_groq_chatbot_rate_' . sergio_groq_chatbot_get_ip_hash();
$count = get_transient( $key );

if ( false === $count ) {
set_transient( $key, 1, SERGIO_GROQ_CHATBOT_RATE_WINDOW );
return true;
}

$count = absint( $count );

if ( $count >= SERGIO_GROQ_CHATBOT_RATE_LIMIT ) {
return false;
}

set_transient( $key, $count + 1, SERGIO_GROQ_CHATBOT_RATE_WINDOW );

return true;
}

/**
* 5. NORMALIZZA TESTI LUNGHI
*/
function sergio_groq_chatbot_limit_text( $text, $max_chars ) {

$text = trim( (string) $text );

if ( function_exists( 'mb_strlen' ) && function_exists( 'mb_substr' ) ) {
if ( mb_strlen( $text, 'UTF-8' ) > $max_chars ) {
return mb_substr( $text, 0, $max_chars, 'UTF-8' );
}

return $text;
}

if ( strlen( $text ) > $max_chars ) {
return substr( $text, 0, $max_chars );
}

return $text;
}

/**
* 6. CALLBACK REST: RICEVE IL MESSAGGIO E CHIAMA GROQ
*/
function sergio_groq_chatbot_handle_message( WP_REST_Request $request ) {

if ( ! sergio_groq_chatbot_rate_limit_is_allowed() ) {
return new WP_REST_Response(
array(
'success' => false,
'message' => 'Hai inviato troppe richieste in poco tempo. Riprova tra qualche minuto.',
),
429
);
}

if (
empty( SERGIO_GROQ_CHATBOT_API_KEY ) ||
'INSERISCI_LA_TUA_API_KEY_GROQ' === SERGIO_GROQ_CHATBOT_API_KEY
) {
return new WP_REST_Response(
array(
'success' => false,
'message' => current_user_can( 'manage_options' )
? 'API key Groq mancante: inseriscila nello snippet o, meglio, nel file wp-config.php.'
: 'Il chatbot non è ancora configurato correttamente.',
),
500
);
}

$params = $request->get_json_params();

$user_message = '';

if ( isset( $params['message'] ) && is_string( $params['message'] ) ) {
$user_message = sanitize_textarea_field( $params['message'] );
$user_message = sergio_groq_chatbot_limit_text( $user_message, SERGIO_GROQ_CHATBOT_MAX_INPUT_CHARS );
}

if ( '' === $user_message ) {
return new WP_REST_Response(
array(
'success' => false,
'message' => 'Scrivi un messaggio prima di inviare.',
),
400
);
}

$messages = array();

$messages[] = array(
'role' => 'system',
'content' => implode(
"\n",
array(
'Sei il chatbot del sito di un web designer WordPress.',
'Rispondi sempre in italiano.',
'Usa un tono chiaro, professionale, semplice e utile.',
'Non inventare prezzi, scadenze, garanzie o informazioni non presenti.',
'Se l’utente vuole un preventivo, una consulenza o un lavoro personalizzato, invitalo con naturalezza a usare la pagina Contatti.',
'Mantieni risposte brevi ma complete, adatte a un visitatore di un sito web.',
)
),
);

if ( isset( $params['history'] ) && is_array( $params['history'] ) ) {
$history = array_slice( $params['history'], -SERGIO_GROQ_CHATBOT_MAX_HISTORY_MESSAGES );

foreach ( $history as $item ) {
if ( ! is_array( $item ) ) {
continue;
}

$role = isset( $item['role'] ) && 'assistant' === $item['role'] ? 'assistant' : 'user';

$content = isset( $item['content'] ) && is_string( $item['content'] )
? sanitize_textarea_field( $item['content'] )
: '';

$content = sergio_groq_chatbot_limit_text( $content, 700 );

if ( '' !== $content ) {
$messages[] = array(
'role' => $role,
'content' => $content,
);
}
}
}

$messages[] = array(
'role' => 'user',
'content' => $user_message,
);

$payload = array(
'model' => SERGIO_GROQ_CHATBOT_MODEL,
'messages' => $messages,
'temperature' => 0.4,
'max_completion_tokens' => 450,
'stream' => false,
);

$response = wp_remote_post(
SERGIO_GROQ_CHATBOT_ENDPOINT,
array(
'timeout' => 25,
'headers' => array(
'Authorization' => 'Bearer ' . SERGIO_GROQ_CHATBOT_API_KEY,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( $payload ),
)
);

if ( is_wp_error( $response ) ) {
return new WP_REST_Response(
array(
'success' => false,
'message' => current_user_can( 'manage_options' )
? 'Errore richiesta Groq: ' . $response->get_error_message()
: 'In questo momento non riesco a rispondere. Riprova tra poco.',
),
500
);
}

$status_code = wp_remote_retrieve_response_code( $response );
$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );

if ( $status_code < 200 || $status_code >= 300 ) {
$admin_message = 'Errore Groq. Codice HTTP: ' . absint( $status_code );

if ( is_array( $data ) && ! empty( $data['error']['message'] ) ) {
$admin_message .= ' - ' . sanitize_text_field( $data['error']['message'] );
}

return new WP_REST_Response(
array(
'success' => false,
'message' => current_user_can( 'manage_options' )
? $admin_message
: 'In questo momento il chatbot non riesce a rispondere. Riprova più tardi.',
),
500
);
}

$answer = '';

if (
is_array( $data ) &&
isset( $data['choices'][0]['message']['content'] ) &&
is_string( $data['choices'][0]['message']['content'] )
) {
$answer = trim( wp_strip_all_tags( $data['choices'][0]['message']['content'] ) );
}

if ( '' === $answer ) {
return new WP_REST_Response(
array(
'success' => false,
'message' => current_user_can( 'manage_options' )
? 'Risposta Groq vuota o formato risposta non riconosciuto.'
: 'Non sono riuscito a generare una risposta utile. Riprova con una domanda più semplice.',
),
500
);
}

return new WP_REST_Response(
array(
'success' => true,
'answer' => $answer,
),
200
);
}

/**
* 7. CSS DEL CHATBOT
*/
add_action( 'wp_head', 'sergio_groq_chatbot_print_css', 30 );

function sergio_groq_chatbot_print_css() {

if ( ! sergio_groq_chatbot_should_load() ) {
return;
}

?>
<style id="sergio-groq-chatbot-css">
.sergio-groq-chatbot {
position: fixed;
right: 24px;
bottom: 24px;
z-index: 99999;
font-family: inherit;
}

.sergio-groq-chatbot * {
box-sizing: border-box;
}

.sergio-groq-chatbot__button {
width: 62px;
height: 62px;
border: 0;
border-radius: 999px;
background: #1E2946;
color: #ffffff;
cursor: pointer;
box-shadow: 0 18px 45px rgba(0, 0, 0, 0.25);
display: inline-flex;
align-items: center;
justify-content: center;
transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}

.sergio-groq-chatbot__button:hover,
.sergio-groq-chatbot__button:focus-visible {
background: #26375f;
transform: translateY(-2px);
box-shadow: 0 22px 55px rgba(0, 0, 0, 0.32);
outline: none;
}

.sergio-groq-chatbot__icon {
width: 29px;
height: 29px;
display: block;
}

.sergio-groq-chatbot__panel {
position: absolute;
right: 0;
bottom: 78px;
width: min(390px, calc(100vw - 32px));
height: min(620px, calc(100vh - 120px));
background: #ffffff;
color: #1b1f2a;
border-radius: 24px;
overflow: hidden;
box-shadow: 0 28px 80px rgba(0, 0, 0, 0.28);
display: flex;
flex-direction: column;
opacity: 0;
visibility: hidden;
transform: translateY(16px) scale(0.98);
pointer-events: none;
transition: opacity 0.22s ease, visibility 0.22s ease, transform 0.22s ease;
border: 1px solid rgba(30, 41, 70, 0.12);
}

.sergio-groq-chatbot.is-open .sergio-groq-chatbot__panel {
opacity: 1;
visibility: visible;
transform: translateY(0) scale(1);
pointer-events: auto;
}

.sergio-groq-chatbot__header {
background: #1E2946;
color: #ffffff;
padding: 18px 18px 16px;
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
}

.sergio-groq-chatbot__title {
margin: 0;
font-size: 17px;
line-height: 1.25;
font-weight: 700;
}

.sergio-groq-chatbot__subtitle {
margin: 5px 0 0;
font-size: 13px;
line-height: 1.4;
opacity: 0.82;
}

.sergio-groq-chatbot__close {
width: 34px;
height: 34px;
border: 0;
border-radius: 999px;
background: rgba(255, 255, 255, 0.12);
color: #ffffff;
cursor: pointer;
font-size: 22px;
line-height: 1;
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
}

.sergio-groq-chatbot__close:hover,
.sergio-groq-chatbot__close:focus-visible {
background: rgba(255, 255, 255, 0.22);
outline: none;
}

.sergio-groq-chatbot__messages {
flex: 1;
overflow-y: auto;
padding: 18px;
background: #f5f7fb;
display: flex;
flex-direction: column;
gap: 12px;
scroll-behavior: smooth;
}

.sergio-groq-chatbot__message {
max-width: 88%;
padding: 12px 14px;
border-radius: 18px;
font-size: 14px;
line-height: 1.5;
white-space: pre-wrap;
word-wrap: break-word;
}

.sergio-groq-chatbot__message--assistant {
align-self: flex-start;
background: #ffffff;
color: #1b1f2a;
border: 1px solid rgba(30, 41, 70, 0.08);
border-bottom-left-radius: 6px;
}

.sergio-groq-chatbot__message--user {
align-self: flex-end;
background: #1E2946;
color: #ffffff;
border-bottom-right-radius: 6px;
}

.sergio-groq-chatbot__typing {
align-self: flex-start;
color: #5c6475;
font-size: 13px;
line-height: 1.4;
padding: 2px 4px;
}

.sergio-groq-chatbot__form {
padding: 14px;
background: #ffffff;
border-top: 1px solid rgba(30, 41, 70, 0.1);
display: flex;
gap: 10px;
align-items: flex-end;
}

.sergio-groq-chatbot__input {
flex: 1;
min-height: 46px;
max-height: 120px;
resize: none;
border: 1px solid rgba(30, 41, 70, 0.18);
border-radius: 16px;
padding: 12px 13px;
font: inherit;
font-size: 14px;
line-height: 1.4;
color: #1b1f2a;
background: #ffffff;
}

.sergio-groq-chatbot__input:focus {
border-color: #1E2946;
outline: 3px solid rgba(30, 41, 70, 0.15);
}

.sergio-groq-chatbot__send {
width: 46px;
height: 46px;
border: 0;
border-radius: 16px;
background: #1E2946;
color: #ffffff;
cursor: pointer;
font-weight: 700;
display: inline-flex;
align-items: center;
justify-content: center;
transition: background 0.2s ease, opacity 0.2s ease;
}

.sergio-groq-chatbot__send:hover,
.sergio-groq-chatbot__send:focus-visible {
background: #26375f;
outline: none;
}

.sergio-groq-chatbot__send:disabled {
cursor: not-allowed;
opacity: 0.55;
}

.sergio-groq-chatbot__footer-note {
padding: 0 16px 14px;
background: #ffffff;
color: #6a7282;
font-size: 12px;
line-height: 1.4;
}

.sergio-groq-chatbot__footer-note a {
color: #1E2946;
font-weight: 700;
text-decoration: underline;
text-underline-offset: 3px;
}

@media (max-width: 520px) {
.sergio-groq-chatbot {
right: 16px;
bottom: 16px;
}

.sergio-groq-chatbot__panel {
position: fixed;
inset: auto 12px 88px 12px;
width: auto;
height: min(620px, calc(100vh - 110px));
border-radius: 22px;
}

.sergio-groq-chatbot__button {
width: 58px;
height: 58px;
}
}

@media (prefers-reduced-motion: reduce) {
.sergio-groq-chatbot__button,
.sergio-groq-chatbot__panel,
.sergio-groq-chatbot__messages {
transition: none;
scroll-behavior: auto;
}
}
</style>
<?php
}

/**
* 8. HTML + JAVASCRIPT DEL CHATBOT
*/
add_action( 'wp_footer', 'sergio_groq_chatbot_print_markup_and_js', 30 );

function sergio_groq_chatbot_print_markup_and_js() {

if ( ! sergio_groq_chatbot_should_load() ) {
return;
}

$config = array(
'endpoint' => esc_url_raw( rest_url( 'sergio-groq-chatbot/v1/message' ) ),
'nonce' => wp_create_nonce( 'wp_rest' ),
'contactUrl' => esc_url_raw( home_url( '/contatti/' ) ),
'storageKey' => 'sergio_groq_chatbot_history_v1',
);

?>
<div class="sergio-groq-chatbot" data-sergio-groq-chatbot>
<section
class="sergio-groq-chatbot__panel"
id="sergio-groq-chatbot-panel"
aria-hidden="true"
aria-labelledby="sergio-groq-chatbot-title"
>
<header class="sergio-groq-chatbot__header">
<div>
<p class="sergio-groq-chatbot__title" id="sergio-groq-chatbot-title">
Assistente AI
</p>
<p class="sergio-groq-chatbot__subtitle">
Fai una domanda sul sito, sui servizi o su WordPress.
</p>
</div>

<button
class="sergio-groq-chatbot__close"
type="button"
aria-label="Chiudi chatbot"
data-sergio-groq-close
>
×
</button>
</header>

<div class="sergio-groq-chatbot__messages" data-sergio-groq-messages></div>

<form class="sergio-groq-chatbot__form" data-sergio-groq-form>
<textarea
class="sergio-groq-chatbot__input"
data-sergio-groq-input
rows="1"
maxlength="600"
placeholder="Scrivi qui la tua domanda..."
aria-label="Scrivi un messaggio al chatbot"
></textarea>

<button
class="sergio-groq-chatbot__send"
type="submit"
aria-label="Invia messaggio"
data-sergio-groq-send
>

</button>
</form>

<div class="sergio-groq-chatbot__footer-note">
Per richieste specifiche puoi usare la
<a href="<?php echo esc_url( home_url( '/contatti/' ) ); ?>">pagina Contatti</a>.
</div>
</section>

<button
class="sergio-groq-chatbot__button"
type="button"
aria-label="Apri chatbot"
aria-controls="sergio-groq-chatbot-panel"
aria-expanded="false"
data-sergio-groq-toggle
>
<svg class="sergio-groq-chatbot__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path fill="currentColor" d="M12 3C7.03 3 3 6.58 3 11c0 2.22 1.03 4.23 2.69 5.68L5 21l4.3-2.16c.85.1 1.75.16 2.7.16 4.97 0 9-3.58 9-8s-4.03-8-9-8Zm-4 9.25a1.25 1.25 0 1 1 0-2.5 1.25 1.25 0 0 1 0 2.5Zm4 0a1.25 1.25 0 1 1 0-2.5 1.25 1.25 0 0 1 0 2.5Zm4 0a1.25 1.25 0 1 1 0-2.5 1.25 1.25 0 0 1 0 2.5Z"/>
</svg>
</button>
</div>

<script id="sergio-groq-chatbot-js">
window.SergioGroqChatbot = <?php echo wp_json_encode( $config ); ?>;

(function () {
'use strict';

const config = window.SergioGroqChatbot || {};
const root = document.querySelector('[data-sergio-groq-chatbot]');

if (!root || !config.endpoint) {
return;
}

const toggleButton = root.querySelector('[data-sergio-groq-toggle]');
const closeButton = root.querySelector('[data-sergio-groq-close]');
const panel = root.querySelector('#sergio-groq-chatbot-panel');
const messagesEl = root.querySelector('[data-sergio-groq-messages]');
const form = root.querySelector('[data-sergio-groq-form]');
const input = root.querySelector('[data-sergio-groq-input]');
const sendButton = root.querySelector('[data-sergio-groq-send]');

let history = [];
let isSending = false;

function loadHistory() {
try {
const raw = window.localStorage.getItem(config.storageKey);
const parsed = raw ? JSON.parse(raw) : [];

if (Array.isArray(parsed)) {
history = parsed
.filter(function (item) {
return item &&
typeof item.role === 'string' &&
typeof item.content === 'string';
})
.slice(-8);
}
} catch (error) {
history = [];
}
}

function saveHistory() {
try {
window.localStorage.setItem(
config.storageKey,
JSON.stringify(history.slice(-8))
);
} catch (error) {
// localStorage non disponibile: nessun problema.
}
}

function scrollToBottom() {
messagesEl.scrollTop = messagesEl.scrollHeight;
}

function addMessage(role, text, save) {
const message = document.createElement('div');
message.className = 'sergio-groq-chatbot__message sergio-groq-chatbot__message--' + role;
message.textContent = text;

messagesEl.appendChild(message);
scrollToBottom();

if (save) {
history.push({
role: role,
content: text
});

history = history.slice(-8);
saveHistory();
}
}

function addTyping() {
const typing = document.createElement('div');
typing.className = 'sergio-groq-chatbot__typing';
typing.setAttribute('data-sergio-groq-typing', '');
typing.textContent = 'Sto scrivendo...';
messagesEl.appendChild(typing);
scrollToBottom();
}

function removeTyping() {
const typing = messagesEl.querySelector('[data-sergio-groq-typing]');

if (typing) {
typing.remove();
}
}

function renderInitialMessages() {
messagesEl.innerHTML = '';

if (!history.length) {
addMessage(
'assistant',
'Ciao! Sono l’assistente AI del sito. Posso aiutarti a capire meglio servizi, WordPress, siti web, performance e richieste di contatto.',
false
);
return;
}

history.forEach(function (item) {
addMessage(item.role === 'assistant' ? 'assistant' : 'user', item.content, false);
});
}

function openChatbot() {
root.classList.add('is-open');
panel.setAttribute('aria-hidden', 'false');
toggleButton.setAttribute('aria-expanded', 'true');

window.setTimeout(function () {
input.focus();
scrollToBottom();
}, 80);
}

function closeChatbot() {
root.classList.remove('is-open');
panel.setAttribute('aria-hidden', 'true');
toggleButton.setAttribute('aria-expanded', 'false');
toggleButton.focus();
}

function autoResizeTextarea() {
input.style.height = 'auto';
input.style.height = Math.min(input.scrollHeight, 120) + 'px';
}

async function sendMessage(text) {
isSending = true;
sendButton.disabled = true;
input.disabled = true;
addTyping();

try {
const response = await window.fetch(config.endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': config.nonce || ''
},
body: JSON.stringify({
message: text,
history: history.slice(-8)
})
});

const data = await response.json();

removeTyping();

if (!response.ok || !data || !data.success) {
addMessage(
'assistant',
data && data.message ? data.message : 'Non sono riuscito a rispondere. Riprova tra poco.',
true
);
return;
}

addMessage('assistant', data.answer, true);

} catch (error) {
removeTyping();
addMessage(
'assistant',
'C’è stato un problema di connessione. Riprova tra poco oppure usa la pagina Contatti.',
true
);
} finally {
isSending = false;
sendButton.disabled = false;
input.disabled = false;
input.focus();
}
}

loadHistory();
renderInitialMessages();

toggleButton.addEventListener('click', function () {
if (root.classList.contains('is-open')) {
closeChatbot();
} else {
openChatbot();
}
});

closeButton.addEventListener('click', closeChatbot);

input.addEventListener('input', autoResizeTextarea);

input.addEventListener('keydown', function (event) {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
form.requestSubmit();
}
});

document.addEventListener('keydown', function (event) {
if (event.key === 'Escape' && root.classList.contains('is-open')) {
closeChatbot();
}
});

form.addEventListener('submit', function (event) {
event.preventDefault();

if (isSending) {
return;
}

const text = input.value.trim();

if (!text) {
return;
}

addMessage('user', text, true);

input.value = '';
autoResizeTextarea();

sendMessage(text);
});
})();
</script>
<?php
}

Come funziona lo snippet

Lo snippet contiene tre parti in una: PHP, CSS e JavaScript.

La parte PHP crea la rotta REST di WordPress, riceve il messaggio dell’utente, lo pulisce, applica un piccolo rate limit e poi invia la richiesta a Groq con wp_remote_post(). La funzione wp_remote_post() è la funzione WordPress per effettuare richieste HTTP di tipo POST.

La parte PHP usa anche sanitize_textarea_field() per ripulire i testi inseriti dall’utente. Questa funzione è pensata per sanitizzare stringhe multilinea, mantenendo ritorni a capo e spazi legittimi dei campi textarea.

La parte CSS disegna il chatbot: bottone fisso in basso a destra, pannello flottante, messaggi dell’utente, messaggi dell’assistente, textarea e pulsante di invio. È tutto prefissato con classi sergio-groq-chatbot, così il rischio di conflitti con il tema è più basso.

La parte JavaScript gestisce apertura, chiusura, invio dei messaggi, cronologia locale e chiamata alla rotta REST. La cronologia viene salvata nel browser con localStorage, ma solo in modo leggero: serve a mantenere un minimo di contesto senza trasformare il sito in una piattaforma di chat complessa.

Configurare il prompt del chatbot

Dentro lo snippet c’è questa parte:

$messages[] = array(
'role' => 'system',
'content' => implode(
"\n",
array(
'Sei il chatbot del sito di un web designer WordPress.',
'Rispondi sempre in italiano.',
'Usa un tono chiaro, professionale, semplice e utile.',
'Non inventare prezzi, scadenze, garanzie o informazioni non presenti.',
'Se l’utente vuole un preventivo, una consulenza o un lavoro personalizzato, invitalo con naturalezza a usare la pagina Contatti.',
'Mantieni risposte brevi ma complete, adatte a un visitatore di un sito web.',
)
),
);

Questa è una delle parti più importanti. Qui decidi il comportamento del chatbot.

Per un sito professionale conviene evitare un assistente troppo “creativo”. Deve essere utile, chiaro e prudente. Non deve inventare prezzi, non deve promettere tempi di consegna, non deve sostituire un preventivo vero e non deve dare informazioni che non conosce.

Per esempio, per un sito da web designer potresti personalizzarlo così:

'Sei il chatbot del sito di Sergio Pinna, Web Designer specializzato in WordPress, GeneratePress, GenerateBlocks, SEO tecnica e siti web professionali.',

In questo modo il chatbot capisce meglio il contesto del sito.

Perché non chiamare Groq direttamente dal JavaScript

Tecnicamente sarebbe possibile scrivere una chiamata fetch() direttamente da JavaScript verso Groq. Ma sarebbe una pessima idea, perché la API key finirebbe nel codice visibile del browser.

Chiunque potrebbe aprire gli strumenti sviluppatore, leggere la chiave e usarla altrove. Per questo lo snippet usa WordPress come intermediario. Il browser parla con WordPress, WordPress parla con Groq. La chiave rimane lato server.

Questa è la differenza tra un’integrazione “che funziona” e un’integrazione pensata bene.

Dove inserire la API key

La soluzione più ordinata è inserirla in wp-config.php:

define( 'SERGIO_GROQ_CHATBOT_API_KEY', 'LA_TUA_API_KEY_GROQ' );

Poi nello snippet puoi lasciare questa parte così com’è:

if ( ! defined( 'SERGIO_GROQ_CHATBOT_API_KEY' ) ) {
define( 'SERGIO_GROQ_CHATBOT_API_KEY', 'INSERISCI_LA_TUA_API_KEY_GROQ' );
}

WordPress userà la costante già definita in wp-config.php.

Per un test veloce puoi anche inserire la chiave direttamente nello snippet, sostituendo:

INSERISCI_LA_TUA_API_KEY_GROQ

con la tua chiave reale. Però, su un sito in produzione, meglio usare wp-config.php.

Come testare il chatbot

Dopo aver attivato lo snippet:

  1. apri il sito in una finestra anonima;
  2. verifica che il bottone compaia in basso a destra;
  3. apri il chatbot;
  4. scrivi una domanda semplice, per esempio: “Che servizi offri?”;
  5. controlla che arrivi una risposta;
  6. apri la console del browser e verifica che non ci siano errori JavaScript;
  7. prova da utente non loggato;
  8. prova da mobile;
  9. verifica che la chiave Groq non compaia nel codice sorgente della pagina.

L’ultimo punto è fondamentale. La API key non deve essere visibile né nel sorgente HTML né nei file JavaScript caricati dal browser.

Possibili problemi e soluzioni

Il chatbot risponde “API key mancante”

Significa che non hai sostituito INSERISCI_LA_TUA_API_KEY_GROQ oppure non hai definito correttamente la costante in wp-config.php.

Il chatbot non appare

Controlla che lo snippet sia attivo e impostato per essere eseguito sul frontend. Controlla anche che il tema chiami correttamente wp_head() e wp_footer(), perché lo snippet usa questi hook per stampare CSS, HTML e JavaScript.

Il chatbot appare ma non risponde

Apri la console del browser e guarda la scheda Network. Cerca la chiamata verso:

/wp-json/sergio-groq-chatbot/v1/message

Se restituisce errore 500, probabilmente il problema è nella API key, nel modello scelto o nella risposta di Groq.

Ricevi errore di modello

Controlla nella documentazione Groq il nome aggiornato del modello. I modelli disponibili possono cambiare nel tempo, quindi è sempre meglio verificare la lista ufficiale prima di mettere il codice in produzione.

Miglioramenti possibili

Questo snippet è già completo per una prima integrazione, ma può essere migliorato ulteriormente.

Si può fare in modo che il chatbot compaia solo su certe pagine, per esempio home, servizi e contatti. Si può aggiungere un messaggio iniziale diverso in base alla pagina visitata. Si può integrare una piccola base di conoscenza del sito, per esempio passando al modello informazioni sui servizi principali. Si può anche registrare in modo anonimo il numero di richieste, così da capire se gli utenti lo usano davvero.

Un’altra evoluzione interessante è collegare il chatbot agli articoli del blog. Per esempio, se un utente chiede “come velocizzare WordPress?”, il chatbot potrebbe suggerire l’articolo più adatto invece di limitarsi a una risposta generica.

Attenzione a privacy, sicurezza e aspettative

Un chatbot non è solo un elemento grafico. È un punto di ingresso interattivo nel sito. Per questo conviene usarlo con criterio.

Meglio evitare di chiedere dati personali direttamente nella chat. Meglio non far inserire password, informazioni sensibili o dati riservati. Per richieste commerciali, preventivi o informazioni personali, è preferibile mandare l’utente alla pagina contatti o a un form gestito correttamente.

Dal punto di vista della sicurezza, il minimo indispensabile è:

  • non esporre la API key nel frontend;
  • limitare la lunghezza dei messaggi;
  • usare sanitizzazione lato server;
  • applicare un rate limit;
  • mostrare errori tecnici dettagliati solo agli amministratori;
  • verificare periodicamente consumo e limiti dell’account Groq.

Conclusione

Aggiungere un chatbot AI a WordPress non significa riempire il sito di automazioni inutili. Significa creare un piccolo assistente capace di aiutare l’utente nel momento in cui ha una domanda.

La soluzione migliore è costruirlo in modo leggero: interfaccia semplice, codice controllato, chiamata server-side, API key protetta e risposte guidate da un prompt chiaro. Groq rende la parte AI abbastanza accessibile grazie alla sua API compatibile con l’impostazione OpenAI, mentre WordPress offre gli strumenti giusti per creare un endpoint REST personalizzato e gestire la comunicazione in modo ordinato.

Il risultato è un chatbot utile, non invasivo e integrato nel sito: un supporto in più per accompagnare il visitatore verso le informazioni giuste e, quando serve, verso la pagina contatti.

Potrebbe interessarti anche...

Come velocizzare e testare la velocità di caricamento di un sito WordPress

Come velocizzare e testare la velocità di caricamento di un sito WordPress

08/05/2026

Articolo divulgativo su come velocizzare un sito WordPress e testarne le prestazioni. Spiega in modo semplice perché la velocità è importante, quali elementi possono rallentare un sito e quali strumenti usare per misurare i tempi di caricamento.

Leggi l'articolo
Perché la tua azienda dovrebbe avere un sito web

Perché la tua azienda dovrebbe avere un sito web

06/05/2026

Articolo pensato per chi è indeciso se creare un sito web per la propria attività. Spiega, in modo discorsivo e concreto, perché un sito aziendale resta importante anche nell’epoca dei social: aumenta la credibilità, permette di essere trovati su Google, organizza meglio le informazioni, rafforza il passaparola e offre uno spazio digitale stabile, professionale e controllabile.

Leggi l'articolo
Perché abbandonare Elementor e passare a GeneratePress e GenerateBlocks

Perché abbandonare Elementor e passare a GeneratePress e GenerateBlocks

04/05/2026

Un confronto pratico tra Elementor e la combinazione GeneratePress + GenerateBlocks, con focus su velocità, pulizia del codice, manutenzione, SEO e controllo del design.

Leggi l'articolo

Hai una domanda su questo articolo?

Scrivimi pure nei commenti: ti risponderò il prima possibile con un suggerimento pratico.

...aspetta un attimo!

Hai un’idea per un sito, una pagina da migliorare o un progetto ancora da mettere a fuoco? Raccontamelo: possiamo capire insieme da dove partire.

Parlami della tua idea