Creare Widget Personalizzati per Elementor: Guida Sviluppatori
Elementor offre decine di widget predefiniti, ma in alcuni casi le esigenze specifiche di un progetto richiedono funzionalita che nessun widget standard puo fornire. In questi casi, la soluzione e creare un widget personalizzato. Elementor mette a disposizione una API solida e ben documentata che permette agli sviluppatori PHP di estendere il page builder con widget su misura, perfettamente integrati nel pannello di controllo visuale.
Questa guida e rivolta a sviluppatori con conoscenze di PHP, HTML e CSS. Se non sei uno sviluppatore ma hai bisogno di widget personalizzati per il tuo progetto, il nostro team di realizzazione siti web puo creare soluzioni su misura per le tue esigenze.
Architettura dei Widget di Elementor
Ogni widget di Elementor e una classe PHP che estende la classe base Widget_Base. La struttura segue un pattern chiaro e prevedibile:
- Metadati del widget: nome, titolo, icona, categoria
- Controlli: i campi di configurazione che appaiono nel pannello laterale (testo, colore, tipografia, immagine, ecc.)
- Rendering: la funzione che genera il codice HTML visibile nel frontend
- Template di anteprima: il JavaScript che genera la anteprima in tempo reale nel builder (opzionale)
File System
La struttura consigliata per un plugin che contiene widget personalizzati:
my-elementor-widgets/
├── my-elementor-widgets.php (file principale del plugin)
├── widgets/
│ ├── cta-box.php (widget CTA Box)
│ ├── team-member.php (widget Team Member)
│ └── pricing-table.php (widget Pricing Table)
├── assets/
│ ├── css/
│ │ └── widgets.css (stili dei widget)
│ └── js/
│ └── widgets.js (script dei widget)
└── readme.txt
Registrare il Plugin e i Widget
Il file principale del plugin deve registrare i widget con Elementor attraverso il hook appropriato:
<?php
/**
* Plugin Name: My Elementor Widgets
* Description: Widget personalizzati per Elementor
* Version: 1.0.0
* Requires PHP: 7.4
*/
if ( ! defined( 'ABSPATH' ) ) exit;
function register_custom_widgets( $widgets_manager ) {
require_once __DIR__ . '/widgets/cta-box.php';
$widgets_manager->register( new CTA_Box_Widget() );
}
add_action( 'elementor/widgets/register', 'register_custom_widgets' );

La Classe Widget_Base: Metodi Fondamentali
Ogni widget personalizzato deve implementare almeno questi metodi:
get_name()
Restituisce il nome tecnico del widget (slug unico, senza spazi, in minuscolo). Questo identificativo viene usato internamente da Elementor:
public function get_name() {
return 'cta_box';
}
get_title()
Restituisce il titolo leggibile del widget come appare nel pannello:
public function get_title() {
return 'CTA Box Personalizzato';
}
get_icon()
Restituisce la classe della icona visualizzata nel pannello widget. Puoi usare qualsiasi classe Eicons (il set di icone di Elementor) o Font Awesome:
public function get_icon() {
return 'eicon-call-to-action';
}
get_categories()
Definisce in quale categoria del pannello appare il widget. Puoi usare categorie esistenti o crearne di personalizzate:
public function get_categories() {
return [ 'general' ];
}
Categorie predefinite disponibili: basic, pro-elements, general, theme-elements, woocommerce-elements.
register_controls(): Creare i Campi di Configurazione
Il metodo register_controls() definisce tutti i campi che appaiono nel pannello laterale quando il widget viene selezionato. Elementor offre decine di tipi di controllo:
Controlli di Base
- TEXT: campo di testo singola riga
- TEXTAREA: area di testo multiriga
- WYSIWYG: editor visuale completo (TinyMCE)
- NUMBER: campo numerico con min/max/step
- URL: campo URL con opzioni per target e nofollow
- SWITCHER: toggle on/off
- SELECT: menu a discesa con opzioni predefinite
- SELECT2: menu a discesa con ricerca e selezione multipla
Controlli di Stile
- COLOR: selettore colore con supporto per i Global Colors
- SLIDER: cursore numerico con unita di misura (px, em, %, vw)
- DIMENSIONS: quattro campi collegati per padding/margin/border-radius
- TYPOGRAPHY: controllo completo della tipografia (font family, size, weight, transform, line-height, letter-spacing)
- TEXT_SHADOW: ombra del testo
- BOX_SHADOW: ombra del box
- BORDER: tipo, larghezza e colore del bordo
- BACKGROUND: sfondo classico o gradiente
Controlli Media
- MEDIA: selettore immagine dalla libreria media
- GALLERY: selettore galleria di immagini
- ICONS: selettore icona (Font Awesome, Eicons, SVG)
Esempio Completo di register_controls()
protected function register_controls() {
// SEZIONE CONTENUTO
$this->start_controls_section(
'content_section',
[
'label' => 'Contenuto',
'tab' => ElementorControls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'title',
[
'label' => 'Titolo',
'type' => ElementorControls_Manager::TEXT,
'default' => 'Titolo CTA',
'placeholder' => 'Inserisci il titolo',
]
);
$this->add_control(
'description',
[
'label' => 'Descrizione',
'type' => ElementorControls_Manager::TEXTAREA,
'default' => 'Descrizione della call to action.',
'rows' => 5,
]
);
$this->add_control(
'button_text',
[
'label' => 'Testo Pulsante',
'type' => ElementorControls_Manager::TEXT,
'default' => 'Scopri di piu',
]
);
$this->add_control(
'button_url',
[
'label' => 'Link Pulsante',
'type' => ElementorControls_Manager::URL,
'placeholder' => 'https://tuosito.it',
'default' => [ 'url' => '#' ],
]
);
$this->add_control(
'image',
[
'label' => 'Immagine',
'type' => ElementorControls_Manager::MEDIA,
'default' => [
'url' => ElementorUtils::get_placeholder_image_src(),
],
]
);
$this->end_controls_section();
// SEZIONE STILE
$this->start_controls_section(
'style_section',
[
'label' => 'Stile',
'tab' => ElementorControls_Manager::TAB_STYLE,
]
);
$this->add_control(
'title_color',
[
'label' => 'Colore Titolo',
'type' => ElementorControls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .cta-title' => 'color: {{VALUE}}',
],
]
);
$this->add_group_control(
ElementorGroup_Control_Typography::get_type(),
[
'name' => 'title_typography',
'label' => 'Tipografia Titolo',
'selector' => '{{WRAPPER}} .cta-title',
]
);
$this->end_controls_section();
}
render(): Generare il Codice HTML
Il metodo render() genera il codice HTML che viene visualizzato nel frontend del sito. Qui accedi ai valori impostati nei controlli tramite $this->get_settings_for_display():
protected function render() {
$settings = $this->get_settings_for_display();
$target = $settings['button_url']['is_external'] ? ' target="_blank"' : '';
$nofollow = $settings['button_url']['nofollow'] ? ' rel="nofollow"' : '';
echo '<div class="cta-box">';
if ( ! empty( $settings['image']['url'] ) ) {
echo '<img src="' . esc_url( $settings['image']['url'] ) . '" alt="" class="cta-image" />';
}
echo '<h3 class="cta-title">' . esc_html( $settings['title'] ) . '</h3>';
echo '<p class="cta-desc">' . esc_html( $settings['description'] ) . '</p>';
if ( ! empty( $settings['button_url']['url'] ) ) {
echo '<a href="' . esc_url( $settings['button_url']['url'] ) . '"' . $target . $nofollow . ' class="cta-btn">';
echo esc_html( $settings['button_text'] );
echo '</a>';
}
echo '</div>';
}

content_template(): Anteprima Live nel Builder
Il metodo content_template() e opzionale ma fortemente consigliato. Genera la anteprima in tempo reale nel builder usando la sintassi Backbone.js (template JavaScript). Senza questo metodo, Elementor deve fare una chiamata AJAX al server per ogni modifica, rallentando la esperienza di editing:
protected function content_template() {
?>
<div class="cta-box">
<# if ( settings.image.url ) { #>
<img src="{{ settings.image.url }}" alt="" class="cta-image" />
<# } #>
<h3 class="cta-title">{{{ settings.title }}}</h3>
<p class="cta-desc">{{{ settings.description }}}</p>
<# if ( settings.button_url.url ) { #>
<a href="{{ settings.button_url.url }}" class="cta-btn">
{{{ settings.button_text }}}
</a>
<# } #>
</div>
<?php
}
Nota la differenza di sintassi: {{ }} per i valori con escape e {{{ }}} per i valori senza escape (HTML grezzo).
Caricare CSS e JavaScript
Se il tuo widget richiede fogli di stile o script personalizzati, registrali nei metodi dedicati:
public function get_style_depends() {
return [ 'my-widget-styles' ];
}
public function get_script_depends() {
return [ 'my-widget-scripts' ];
}
Registra gli asset nel file principale del plugin:
function register_widget_assets() {
wp_register_style( 'my-widget-styles', plugins_url( 'assets/css/widgets.css', __FILE__ ) );
wp_register_script( 'my-widget-scripts', plugins_url( 'assets/js/widgets.js', __FILE__ ), [ 'jquery' ], '1.0.0', true );
}
add_action( 'wp_enqueue_scripts', 'register_widget_assets' );
Categorie Personalizzate
Per organizzare i tuoi widget in una categoria dedicata nel pannello:
function add_custom_widget_category( $elements_manager ) {
$elements_manager->add_category(
'my-custom-widgets',
[
'title' => 'I Miei Widget',
'icon' => 'fa fa-plug',
]
);
}
add_action( 'elementor/elements/categories_registered', 'add_custom_widget_category' );
Pacchettizzare come Plugin
Una volta sviluppati e testati i widget, pacchettizza il tutto come un plugin WordPress standard:
- Aggiungi le intestazioni corrette nel file principale del plugin
- Verifica che Elementor sia attivo prima di registrare i widget (controlla
did_action( 'elementor/loaded' )) - Gestisci la compatibilita con le versioni di Elementor (controlla
ELEMENTOR_VERSION) - Aggiungi un file
readme.txtse intendi distribuirlo - Crea un file ZIP per la distribuzione
Conclusione
Creare widget personalizzati per Elementor e un processo strutturato che richiede conoscenze di PHP e comprensione della architettura del page builder. Una volta padroneggiata la API, le possibilita sono praticamente illimitate: puoi creare widget per qualsiasi esigenza, da semplici box informativi a integrazioni complesse con API esterne.
Se hai bisogno di widget personalizzati per il tuo progetto ma non hai le competenze di sviluppo necessarie, contattaci per una consulenza tecnica.