PHP Development

Creating your own custom Elementor widgets

For those who don’t know, Elementor is an amazing page builder for WordPress. Super fast with some really nifty features. Check it out here.

Today I’ll run through how you can add your own custom elements into the sidebar. We’ll do a basic one that outputs some text along with some recent post titles.

This is what the new element will look like:


And this is what will happen when dragging this element onto the page:



I’ll wrap this up into a handy plugin at the end, nice copy-paste example for you to use.

Elementor does not have a developer API as such, so we’ll just be interacting with the Elementor function calls directly.


Step 1: Choose an Elementor icon

Elementor widgets look like this:


So we need to choose an icon for the new one we’re going to make. The easiest way is to pick one of the existing Elementor icons (you can use font-awesome, it’s just a little messy, I’ll cover that in another post).

Head over to and click Select Font then upload the wp-content/plugins/elementor/assets/lib/eicons/fonts/eicons.ttf file. You’ll see all the available icons:


I click on the icon I wish to use and take note of the “name” to the left. The one I’m using here is called “post-list”:




Step 2: Create a WordPress plugin to hold our Elementor widget

Here’s the code. Nothing special. It just hooks into elementor/widgets/widgets_registered and then includes our Elementor file. We do it this way so the theme can override this custom Elementor widget if it wants to (I do things this way so I can share a base plugin between all my themes and make individual theme tweaks if necessary).



 * Plugin Name: Elementor Custom Elements
 * Description: Custom element added to Elementor
 * Plugin URI:
 * Version: 0.0.1
 * Author: dtbaker
 * Author URI:
 * Text Domain: elementor-custom-element

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

// This file is pretty much a boilerplate WordPress plugin.
// It does very little except including wp-widget.php

class ElementorCustomElement {

   private static $instance = null;

   public static function get_instance() {
      if ( ! self::$instance )
         self::$instance = new self;
      return self::$instance;

   public function init(){
      add_action( 'elementor/widgets/widgets_registered', array( $this, 'widgets_registered' ) );

   public function widgets_registered() {

      // We check if the Elementor plugin has been installed / activated.
      if(defined('ELEMENTOR_PATH') && class_exists('Elementor\Widget_Base')){

         // We look for any theme overrides for this custom Elementor element.
         // If no theme overrides are found we use the default one in this plugin.

         $widget_file = 'plugins/elementor/my-widget.php';
         $template_file = locate_template($widget_file);
         if ( !$template_file || !is_readable( $template_file ) ) {
            $template_file = plugin_dir_path(__FILE__).'my-widget.php';
         if ( $template_file && is_readable( $template_file ) ) {
            require_once $template_file;




Step 3: Create the custom Elementor widget

Now we create the custom Elementor widget. We put this into a my-widget.php file in the plugin folder. This file can also be placed / modified in the theme folder ‘wp-content/themes/my-theme/plugins/elementor/my-widget.php’

The magic here happens with the $this->add_control() calls. I won’t list all the available controls here. The quickest way is to find an existing widget that you like ( wp-content/plugins/elementor/includes/widgets/*.php ) and just copy/paste the relevant controls in.

In our widget here we’re only having a text input box and a drop down list:

namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

class Widget_My_Custom_Elementor_Thing extends Widget_Base {

   public function get_id() {
      return 'my-blog-posts';

   public function get_title() {
      return __( 'My Custom Widget', 'elementor-custom-element' );

   public function get_icon() {
      // Icon name from the Elementor font file, as per
      return 'post-list';

   protected function _register_controls() {

            'label' => __( 'Blog Posts', 'elementor-custom-element' ),
            'type' => Controls_Manager::SECTION,

            'label' => __( 'Text', 'elementor-custom-element' ),
            'type' => Controls_Manager::TEXT,
            'default' => '',
            'title' => __( 'Enter some text', 'elementor-custom-element' ),
            'section' => 'section_blog_posts',

            'label' => __( 'Number of Posts', 'elementor-custom-element' ),
            'type' => Controls_Manager::SELECT,
            'default' => 5,
            'section' => 'section_blog_posts',
            'options' => [
               1 => __( 'One', 'elementor-custom-element' ),
               2 => __( 'Two', 'elementor-custom-element' ),
               5 => __( 'Five', 'elementor-custom-element' ),
               10 => __( 'Ten', 'elementor-custom-element' ),


   protected function render( $instance = [] ) {

      // get our input from the widget settings.

      $custom_text = ! empty( $instance['some_text'] ) ? $instance['some_text'] : ' (no text was entered ) ';
      $post_count = ! empty( $instance['posts_per_page'] ) ? (int)$instance['posts_per_page'] : 5;


      <h3>My Example Elementor Widget</h3>
      <p>My text was: <?php echo esc_html( $custom_text );?> </p>
      <h3>Some Recent Posts Here:</h3>
         $args = array( 'numberposts' => $post_count );
         $recent_posts = wp_get_recent_posts( $args );
         foreach( $recent_posts as $recent ){
            echo '<li><a href="' . esc_url( get_permalink( $recent["ID"] ) ). '">' .   esc_html( $recent["post_title"] ).'</a> </li> ';



   protected function content_template() {}

   public function render_plain_content( $instance = [] ) {}


Plugin::instance()->widgets_manager->register_widget( 'Elementor\Widget_My_Custom_Elementor_Thing' );


Step 4: Profit!

Feel free to try Elementor (and a couple of my basic Elementor addons) in the live Elementor demo available here:


Code is on Github

The above code is over on Github, check it out here:


What’s next?

You can also add new controls to existing elements. For example: this is how you add a new select control to an existing Elementor widget.


These blog posts are soooo helpful. I haven’t found anyone else writing about Elementor development. Thanks man.

I have a question for you…

All of the widgets that come packaged with elementor make use of the global font settings.

But none of the widgets I create seem to inherit those styles. Is there a trick to getting my custom elementor widgets to inherit the global elementor font styles?


Hi there! Thanks for sharing!
But since one of the latest updates the code should be slightly different.
In the widget class you should have a function like this:
public function get_name() {
return ‘my-widget-name’;
Plugin::instance()->widgets_manager->register_widget( ‘ElementorWidget_My_Custom_Elementor_Thing’ );
has been replaced by
Plugin::instance()->widgets_manager->register_widget_type( new Widget_My_Custom_Elementor_Thing() );




Yep there’s been quite a few breaking changes recently. The latest version includes new hooks/filters that should prevent this from breaking in future updates. I’ll fix up this example so it works with the latest and greatest version shortly.



Leave a Reply

Your email address will not be published. Required fields are marked *