In WordPress la ricerca interna esiste già, ma spesso viene mostrata in modo un po’ anonimo: una classica barra di ricerca infilata nel menu, nella sidebar o nel footer.
Per un sito più pulito, soprattutto se stai lavorando con GeneratePress e GenerateBlocks, può essere molto più elegante usare una semplice icona a forma di lente d’ingrandimento. L’utente clicca sulla lente, si apre un piccolo pop-up vicino al pulsante e da lì può cercare nel sito.
La cosa interessante è che non serve installare un plugin di ricerca aggiuntivo. Si può fare tutto con uno snippet PHP, un po’ di CSS e un po’ di JavaScript.
L’obiettivo è questo:
- mostrare una lente cliccabile dove vogliamo;
- aprire un piccolo pop-up con il campo di ricerca;
- inviare la ricerca alla normale pagina risultati di WordPress;
- mostrare i risultati nella pagina costruita con GeneratePress e GenerateBlocks;
- mostrare anche una pagina personalizzata quando non ci sono risultati;
- migliorare la ricerca includendo anche categorie e tag.
In pratica, l’utente cerca una parola come “CSS”, “WordPress” o “GeneratePress” e WordPress non guarda soltanto nel titolo o nel contenuto degli articoli, ma tiene conto anche delle categorie e dei tag collegati.
Perché usare una lente di ricerca invece della classica barra sempre visibile
La barra di ricerca sempre visibile può funzionare bene in alcuni siti, ma non è sempre la scelta migliore.
Se il layout è molto pulito, magari con un header essenziale, una search bar completa può occupare troppo spazio. Questo succede soprattutto da mobile, dove ogni elemento dell’header deve essere misurato bene.
Una lente di ricerca invece è più discreta.
Occupa poco spazio, è riconoscibile, non appesantisce la grafica e permette comunque all’utente di cercare rapidamente qualcosa nel sito.
Nel caso specifico, la lente apre un piccolo pop-up posizionato vicino all’elemento cliccato. Quindi non compare una modale enorme al centro della pagina, ma una piccola form leggera, elegante e immediata.
Dal punto di vista UX, è una soluzione molto comoda perché l’utente non viene “strappato” dalla pagina. Clicca, scrive, cerca.
Come funziona la ricerca in WordPress
Prima di entrare nello snippet, vale la pena chiarire un concetto importante.
In WordPress la ricerca standard funziona tramite il parametro s.
Quando un utente cerca qualcosa, il sito viene portato a un URL simile a questo:
https://www.tuosito.it/?s=wordpress
Oppure, se i permalink e il tema lo gestiscono in un certo modo, può apparire una struttura diversa, ma il concetto rimane lo stesso: WordPress riceve una query di ricerca e carica la pagina dei risultati.
Il punto chiave è questo: non dobbiamo inventarci un nuovo sistema di ricerca da zero.
Dobbiamo soltanto creare una form che invii il termine cercato alla ricerca nativa di WordPress.
La form dello snippet infatti usa:
method="get"
action="<?php echo esc_url( home_url( '/' ) ); ?>"
e il campo input ha:
name="s"
Questo è fondamentale.
Il nome s dice a WordPress: “questo è il termine da cercare”.
Il risultato finale
Con lo snippet otteniamo una lente cliccabile richiamabile tramite shortcode:
[sergio_search_icon]
Oppure, se vogliamo mostrare anche un testo accanto all’icona:
[sergio_search_icon text="Cerca"]
La prima versione mostra solo la lente.
La seconda versione mostra lente più testo.
Questa cosa è molto utile perché possiamo usare lo stesso shortcode in punti diversi del sito.
Per esempio:
[sergio_search_icon]
può andare bene nell’header desktop.
Mentre:
[sergio_search_icon text="Cerca nel sito"]
può essere più adatto in una sezione interna, in una sidebar o in una pagina di supporto.
Dove inserire lo shortcode
Lo shortcode può essere inserito in diversi punti del sito.
Se usi GeneratePress e GenerateBlocks, puoi inserirlo per esempio:
- dentro un blocco Shortcode;
- dentro un Element di GeneratePress;
- in una sezione personalizzata dell’header;
- in una sidebar;
- in una pagina costruita con GenerateBlocks;
- in un’area CTA o in una sezione del blog.
L’importante è che nel punto in cui vuoi mostrare la lente venga stampato lo shortcode:
[sergio_search_icon]
Lo snippet si occupa poi di tutto il resto: markup del pop-up, stile, apertura, chiusura, posizionamento e gestione della ricerca.
Creare lo shortcode della lente
La prima parte dello snippet registra lo shortcode.
In pratica diciamo a WordPress: quando trovi
, stampa un bottone con dentro una SVG a forma di lente.
La parte principale è questa:
add_shortcode( 'sergio_search_icon', 'sergio_search_icon_shortcode' );
function sergio_search_icon_shortcode( $atts ) {
$atts = shortcode_atts(
array(
'label' => 'Apri la ricerca',
'text' => '',
),
$atts,
'sergio_search_icon'
);
$text = trim( wp_strip_all_tags( $atts['text'] ) );
ob_start();
?>
<button
class="sergio-search-trigger sergio-search-shortcode-button"
type="button"
aria-label="<?php echo esc_attr( $atts['label'] ); ?>"
data-sergio-search-open
>
<span class="sergio-search-shortcode-button__icon" aria-hidden="true">
<svg width="22" height="22" viewBox="0 0 24 24" focusable="false" aria-hidden="true">
<path d="M21 21l-4.35-4.35m1.1-5.4a6.5 6.5 0 11-13 0 6.5 6.5 0 0113 0z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
</span>
<?php if ( $text !== '' ) : ?>
<span class="sergio-search-shortcode-button__text">
<?php echo esc_html( $text ); ?>
</span>
<?php endif; ?>
</button>
<?php
return ob_get_clean();
}
Qui ci sono alcune cose fatte bene.
La lente è una SVG inline, quindi non bisogna caricare Font Awesome, librerie esterne o file aggiuntivi.
Il colore dell’icona usa currentColor, quindi prende automaticamente il colore del testo nel punto in cui viene inserita. Se la metti in un header bianco su sfondo scuro, puoi colorarla tramite CSS senza modificare l’SVG.
In più, il bottone ha un aria-label, utile per l’accessibilità.
Stampare il mini pop-up nel footer
La lente da sola non basta. Serve anche il contenitore che appare al click.
Per questo viene usata l’action wp_footer:
add_action( 'wp_footer', 'sergio_search_popover_markup', 20 );
Il pop-up viene stampato nel footer della pagina, ma inizialmente è nascosto grazie all’attributo hidden.
Dentro il pop-up c’è una normale form di ricerca WordPress:
<form
role="search"
method="get"
class="sergio-search-form"
action="<?php echo esc_url( home_url( '/' ) ); ?>"
>
<label class="screen-reader-text" for="sergio-search-field">
Cerca nel sito
</label>
<input
id="sergio-search-field"
class="sergio-search-form__field"
type="search"
name="s"
value="<?php echo esc_attr( get_search_query() ); ?>"
placeholder="Cerca..."
autocomplete="off"
minlength="2"
maxlength="80"
required
>
<button class="sergio-search-form__submit" type="submit">
Cerca
</button>
</form>
La cosa più importante, come dicevamo prima, è questa:
name="s"
Senza name="s", WordPress non capirebbe che quel campo deve essere usato come termine di ricerca.
Il CSS del pop-up
Il CSS viene inserito nella head del sito tramite:
add_action( 'wp_head', 'sergio_search_popover_css', 50 );
Questa parte serve a dare stile sia alla lente sia al pop-up.
La lente viene trasformata in un bottone rotondo:
.sergio-search-shortcode-button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
width: 44px;
height: 44px;
padding: 0;
border: 0;
border-radius: 999px;
background: transparent;
color: currentColor;
line-height: 1;
cursor: pointer;
-webkit-appearance: none;
appearance: none;
}
Il pop-up invece viene posizionato in modo fisso nella viewport:
.sergio-search-popover {
--sergio-search-arrow-left: 50%;
position: fixed;
z-index: 999999;
width: min(340px, calc(100vw - 28px));
opacity: 0;
visibility: hidden;
pointer-events: none;
transform: translateY(8px) scale(0.98);
transform-origin: top center;
transition:
opacity 0.18s ease,
visibility 0.18s ease,
transform 0.18s ease;
}
Quando il pop-up viene aperto, JavaScript aggiunge la classe .is-open:
.sergio-search-popover.is-open {
opacity: 1;
visibility: visible;
pointer-events: auto;
transform: translateY(0) scale(1);
}
In questo modo l’apertura non è secca, ma leggermente animata.
Il risultato è più piacevole e più moderno.
Il piccolo triangolo del pop-up
Un dettaglio interessante è la freccina del pop-up.
Quella specie di piccolo triangolo che punta verso la lente viene creata con uno pseudo-elemento CSS:
.sergio-search-popover::before {
content: "";
position: absolute;
top: -7px;
left: var(--sergio-search-arrow-left);
width: 14px;
height: 14px;
background: #ffffff;
transform: rotate(45deg);
box-shadow: -4px -4px 12px rgba(15, 23, 42, 0.04);
}
Tecnicamente non è un triangolo vero, ma un quadrato ruotato di 45 gradi.
La posizione della freccina viene gestita con una variabile CSS:
--sergio-search-arrow-left
Questa variabile viene aggiornata via JavaScript in base alla posizione della lente cliccata.
È un dettaglio piccolo, ma rende il pop-up molto più curato.
Il JavaScript: apertura, chiusura e posizionamento
La parte JavaScript gestisce il comportamento del pop-up.
Quando la pagina è caricata, lo script cerca:
const popover = document.getElementById('sergio-search-popover');
const triggers = document.querySelectorAll('.sergio-search-trigger, [data-sergio-search-open]');
const searchField = popover.querySelector('#sergio-search-field');
Quindi individua il pop-up, tutti i pulsanti che possono aprirlo e il campo di ricerca.
Quando l’utente clicca sulla lente, viene eseguita la funzione openSearch().
Questa funzione:
- blocca il comportamento predefinito del click;
- memorizza quale lente è stata cliccata;
- mostra il pop-up;
- calcola la posizione corretta;
- aggiunge la classe
.is-open; - porta automaticamente il focus nel campo di ricerca.
Questa parte è molto comoda:
if (searchField) {
window.setTimeout(function () {
searchField.focus();
}, 80);
}
L’utente clicca sulla lente e può iniziare subito a scrivere, senza dover cliccare manualmente dentro il campo.
È una piccola cosa, ma dal punto di vista dell’esperienza utente fa la differenza.
Il pop-up si apre sopra o sotto in base allo spazio disponibile
Una parte molto utile dello script è il calcolo della posizione.
Il pop-up viene normalmente aperto sotto la lente. Però, se non c’è spazio sufficiente sotto, viene aperto sopra.
Questo controllo evita che il box finisca tagliato fuori dallo schermo.
La logica è questa:
const hasSpaceBelow = top + popoverHeight <= window.innerHeight - margin;
const hasSpaceAbove = triggerRect.top - popoverHeight - gap >= margin;
if (!hasSpaceBelow && hasSpaceAbove) {
top = triggerRect.top - popoverHeight - gap;
placement = 'above';
}
Se il pop-up viene aperto sopra, viene aggiunta la classe:
.is-above
e anche la freccia cambia posizione.
È una soluzione utile soprattutto quando la lente viene inserita vicino al fondo della pagina o in elementi sticky.
Chiusura del pop-up
Il pop-up può essere chiuso in diversi modi.
Si chiude cliccando fuori:
document.addEventListener('click', function (event) {
if (popover.hidden) {
return;
}
if (popover.contains(event.target)) {
return;
}
if (event.target.closest('.sergio-search-trigger, [data-sergio-search-open]')) {
return;
}
closeSearch();
});
Si chiude anche premendo il tasto Escape:
document.addEventListener('keydown', function (event) {
if (popover.hidden) {
return;
}
if (event.key === 'Escape') {
closeSearch();
}
});
Questa è una buona attenzione lato accessibilità e usabilità.
Inoltre, quando il pop-up si chiude, il focus torna all’elemento che lo aveva aperto:
if (lastFocusedElement && typeof lastFocusedElement.focus === 'function') {
lastFocusedElement.focus();
}
Anche questo è un dettaglio da non sottovalutare.
Collegare la form alle pagine risultati create con GeneratePress e GenerateBlocks
Qui arriva la parte più importante.
La form non porta a una pagina personalizzata inventata da noi. Porta alla ricerca standard di WordPress.
Quando l’utente scrive, per esempio:
css
e clicca su “Cerca”, WordPress riceve una richiesta simile a:
/?s=css
A quel punto viene caricata la pagina dei risultati di ricerca.
Se hai costruito la pagina risultati con GeneratePress e GenerateBlocks, sarà proprio quella pagina/template a mostrare gli articoli trovati.
Se invece non ci sono risultati, verrà mostrato il layout che hai preparato per la pagina “nessun risultato”.
Quindi il flusso è questo:
Click sulla lente
↓
Apertura mini pop-up
↓
Inserimento termine di ricerca
↓
Invio della form
↓
WordPress carica la ricerca nativa
↓
GeneratePress/GenerateBlocks mostrano risultati o nessun risultato
Questa è la cosa bella della soluzione: il pop-up non sostituisce WordPress, ma si appoggia al suo comportamento naturale.
Migliorare la ricerca includendo categorie e tag
Di base, la ricerca WordPress cerca soprattutto nel titolo, nel contenuto e in alcuni campi del post.
Il problema è che spesso un articolo può essere molto rilevante anche per la categoria o per il tag a cui appartiene.
Per esempio, immaginiamo di avere una categoria chiamata:
CSS
Se un utente cerca “CSS”, sarebbe sensato mostrare anche gli articoli appartenenti alla categoria CSS, anche se magari nel titolo non hanno esattamente quella parola.
Lo stesso vale per un tag come:
GeneratePress
Se l’utente cerca “GeneratePress”, ha senso mostrare anche tutti gli articoli taggati GeneratePress.
Per questo nello snippet viene usato pre_get_posts.
Questa funzione intercetta la query principale della ricerca:
add_action( 'pre_get_posts', 'sergio_estendi_ricerca_sito' );
Dentro la funzione vengono fatti alcuni controlli:
if (
is_admin() ||
! $query->is_main_query() ||
! $query->is_search()
) {
return;
}
Tradotto: lo snippet deve intervenire solo nella ricerca principale del sito, non nell’admin, non in query secondarie e non in altre pagine.
Poi viene normalizzato il termine cercato:
$search_term = $query->get( 's' );
$search_term = sergio_normalizza_termine_ricerca( $search_term );
Questa pulizia è importante perché evita ricerche sporche, troppo lunghe o con caratteri strani.
Bloccare ricerche vuote o troppo corte
Un altro punto utile dello snippet è il blocco delle ricerche troppo brevi.
Per esempio:
/?s=
oppure:
/?s=a
non sono ricerche molto utili.
Per questo viene fatto un controllo sulla lunghezza:
if ( sergio_lunghezza_termine_ricerca( $search_term ) < 2 ) {
$query->set( 's', '__sergio_ricerca_non_valida__' );
$query->set( 'post__in', array( 0 ) );
return;
}
In pratica, se il termine ha meno di 2 caratteri, WordPress non mostra risultati.
È una piccola protezione utile sia per l’esperienza utente sia per evitare query inutili.
Limitare i post type cercabili
Lo snippet permette anche di decidere in quali contenuti cercare.
Per esempio:
$post_types_consentiti = array(
'post',
'page',
'portfolio',
);
Questo significa che la ricerca può mostrare:
- articoli;
- pagine;
- elementi portfolio, se il post type esiste.
Poi viene fatto un controllo:
$post_types_consentiti = array_filter(
$post_types_consentiti,
'post_type_exists'
);
Così, se il post type portfolio non esiste, WordPress non va in errore.
Questo rende lo snippet più robusto.
Cercare categorie e tag corrispondenti
La parte che cerca categorie e tag è questa:
$term_ids = get_terms(
array(
'taxonomy' => array( 'category', 'post_tag' ),
'hide_empty' => true,
'search' => $search_term,
'fields' => 'ids',
'number' => 20,
)
);
Qui WordPress cerca termini nelle tassonomie:
category
post_tag
Se trova una categoria o un tag che corrisponde al termine cercato, recupera gli ID.
Poi con:
$term_post_ids = get_objects_in_term(
$term_ids,
array( 'category', 'post_tag' )
);
vengono recuperati gli articoli collegati a quei termini.
Esempio pratico:
Cerco: CSS
↓
WordPress trova la categoria CSS
↓
Recupera gli articoli collegati alla categoria CSS
↓
Li aggiunge ai risultati
Unire la ricerca normale con quella per categorie e tag
La parte più tecnica dello snippet è il filtro posts_search.
Qui viene modificata la logica SQL della ricerca.
Normalmente WordPress fa una cosa simile:
Cerca nel titolo/contenuto/riassunto
Con questo snippet la logica diventa:
Cerca nel titolo/contenuto/riassunto
OR
mostra articoli collegati alla categoria/tag trovato
Il filtro usato è questo:
add_filter( 'posts_search', 'sergio_aggiungi_categorie_tag_alla_ricerca', 10, 2 );
La parte decisiva è il ritorno finale:
return " AND ( {$search_without_initial_and} OR {$wpdb->posts}.ID IN ({$ids_sql}) ) ";
In parole semplici: se l’articolo corrisponde alla ricerca testuale normale, viene mostrato. Se invece non corrisponde direttamente al testo, ma appartiene a una categoria o a un tag pertinente, viene mostrato lo stesso.
Questo migliora molto la qualità della ricerca interna.
Evitare l’indicizzazione delle pagine di ricerca
Nello snippet è presente anche questa riga:
add_filter( 'wp_robots', 'wp_robots_noindex_search' );
Serve per evitare che le pagine di ricerca vengano indicizzate dai motori di ricerca.
Questo è utile perché le URL di ricerca possono diventare infinite.
Per esempio:
/?s=wordpress
/?s=css
/?s=viagra
/?s=test
/?s=qualsiasi-cosa
Non ha senso far indicizzare tutte queste pagine.
Anzi, in molti casi è meglio evitarlo, perché potrebbero creare pagine di bassa qualità o URL generate da spam.
Con il noindex, gli utenti possono usare tranquillamente la ricerca interna, ma Google non viene invitato a indicizzare quelle pagine.
Perché questa soluzione è adatta a GeneratePress e GenerateBlocks
Questa soluzione funziona molto bene con GeneratePress e GenerateBlocks perché separa bene le responsabilità.
Lo snippet si occupa della parte funzionale:
- lente cliccabile;
- pop-up;
- form;
- invio ricerca;
- miglioramento query;
- sicurezza base;
- noindex.
GeneratePress e GenerateBlocks invece si occupano della parte visuale:
- layout della pagina risultati;
- griglia degli articoli;
- messaggio quando non ci sono risultati;
- stile delle card;
- spaziature;
- tipografia;
- eventuali CTA.
Questa divisione è molto pulita.
Non stai usando un page builder pesante per fare logica. E non stai usando PHP per costruire tutto il layout finale della pagina risultati.
Ogni strumento fa il suo lavoro.
Esempio pratico di utilizzo
Immaginiamo di avere un blog con articoli su:
- WordPress;
- CSS;
- PHP;
- GeneratePress;
- GenerateBlocks;
- UX;
- performance.
Nell’header inseriamo la lente:
[sergio_search_icon]
L’utente clicca sulla lente e cerca:
CSS
Il sito mostra:
- articoli che hanno “CSS” nel titolo;
- articoli che hanno “CSS” nel contenuto;
- articoli appartenenti alla categoria CSS;
- articoli con tag CSS.
Se invece l’utente cerca:
GeneratePress
il sito può mostrare anche gli articoli associati al tag GeneratePress.
Se non viene trovato nulla, viene caricata la pagina “nessun risultato” che hai costruito con GeneratePress e GenerateBlocks.
Magari lì puoi inserire un testo del tipo:
Non ho trovato risultati per questa ricerca, ma puoi provare con una parola più generica oppure visitare le categorie principali del blog.
E sotto puoi aggiungere link rapidi a:
- WordPress;
- CSS;
- PHP;
- Web Design;
- GeneratePress.
Così anche una ricerca senza risultato non diventa una pagina morta.
Attenzione: la pagina risultati non deve essere una pagina normale
Un dettaglio importante: la pagina dei risultati di ricerca non è una normale pagina WordPress tipo:
/risultati-ricerca/
La ricerca nativa lavora con la query:
/?s=termine
Quindi, quando costruisci il layout con GeneratePress e GenerateBlocks, devi assicurarti che quel layout venga applicato al contesto corretto, cioè alla pagina/archive di ricerca.
In altre parole, il pop-up invia la ricerca a WordPress; poi sarà il template o l’elemento creato con GeneratePress/GenerateBlocks a gestire la visualizzazione.
Questo è il punto da tenere sempre presente.
Vantaggi di questa soluzione
Questa soluzione ha diversi vantaggi.
Prima di tutto è leggera. Non aggiunge un plugin di ricerca complesso solo per aprire un campo input.
Poi è flessibile. Puoi inserire la lente dove vuoi tramite shortcode.
È anche abbastanza curata lato UX, perché il pop-up si apre vicino al bottone, si chiude cliccando fuori, si chiude con Escape e porta automaticamente il focus nel campo di ricerca.
In più migliora la ricerca nativa di WordPress, perché include categorie e tag nei risultati.
Infine, si integra bene con un sito costruito con GeneratePress e GenerateBlocks, perché lascia al tema e ai blocchi la gestione del layout.
Possibili personalizzazioni
Una volta inserito lo snippet, puoi personalizzare diversi aspetti.
Per esempio puoi cambiare il placeholder del campo:
placeholder="Cerca..."
con qualcosa di più amichevole:
placeholder="Cosa vuoi cercare?"
Puoi cambiare il testo del pulsante:
Cerca
con:
Trova
oppure:
Vai
Puoi anche modificare la larghezza del pop-up:
width: min(340px, calc(100vw - 28px));
Se vuoi un box leggermente più largo, puoi portarlo a:
width: min(420px, calc(100vw - 28px));
Oppure puoi cambiare il colore del pulsante:
background: #111827;
con il colore principale del tuo sito.
Per esempio:
background: #1E294A;
Conclusione
Creare una lente di ricerca con mini pop-up in WordPress è una soluzione elegante, leggera e molto pratica.
Non serve installare un plugin di ricerca solo per mostrare un campo input più bello. WordPress ha già una ricerca interna funzionante: basta creare un’interfaccia migliore e, se necessario, potenziare un po’ la query.
Con questo snippet otteniamo una lente cliccabile tramite shortcode, un pop-up responsive, una form collegata alla ricerca nativa di WordPress e una ricerca più intelligente, capace di considerare anche categorie e tag.
Il risultato finale è perfetto per un sito costruito con GeneratePress e GenerateBlocks: il codice gestisce la logica, mentre il layout dei risultati e della pagina senza risultati rimane completamente personalizzabile con i blocchi.
In questo modo la ricerca interna diventa più ordinata, più gradevole e più utile per chi visita il sito.



