Sunday, March 2, 2025

4 min read

How to Build a Custom Elementor Widget

Let's build something practical — a custom Elementor widget from scratch that integrates smoothly with WordPress and Elementor. We'll create a simple 'Sunrise & Sunset' widget that pulls real data from a public API and displays it cleanly inside the Elementor interface.

Why build a custom widget?

If you often find yourself repeating the same features across multiple Elementor projects, or you want to create reusable, client-specific blocks like testimonials, pricing tables, or data-driven widgets, building your own Elementor widget is the cleanest and most scalable approach.

We'll use a 'Sunrise & Sunset' widget as the example, which shows the sunrise and sunset times for a location entered by the user. It also demonstrates how to integrate external data from an API.

Folder Structure

Inside your wp-content/plugins directory, create the following folder and file structure:

bash
sunrise-sunset-addon/
      sunrise-sunset-addon.php
      widgets/
          sunrise-sunset-widget.php

Main Plugin File: sunrise-sunset-addon.php

This file registers the widget with Elementor. The important hook to use is elementor/widgets/register, which is the modern and stable approach.

php
1<?php
2  /**
3   * Plugin Name: Sunrise & Sunset Widget for Elementor
4   * Description: Adds a custom Elementor widget that displays sunrise and sunset times for a given location.
5   * Version: 1.0.0
6   * Author: Your Name
7   */
8  
9  if ( ! defined( 'ABSPATH' ) ) {
10      exit;
11  }
12  
13  add_action( 'plugins_loaded', function() {
14      if ( defined( 'ELEMENTOR_VERSION' ) && class_exists( '\Elementor\Widget_Base' ) ) {
15  
16          require_once __DIR__ . '/widgets/sunrise-sunset-widget.php';
17  
18          add_action( 'elementor/widgets/register', function( $widgets_manager ) {
19              $widgets_manager->register( new \Sunrise_Sunset_Widget() );
20          });
21      }
22  });

The Widget Class: sunrise-sunset-widget.php

Now we’ll define the widget itself. This class sets the widget name, icon, category, controls, and render output. It’s a clean example of how Elementor widgets are structured.

php
1<?php
2  if ( ! defined( 'ABSPATH' ) ) {
3      exit;
4  }
5  
6  class Sunrise_Sunset_Widget extends \Elementor\Widget_Base {
7  
8      public function get_name() {
9          return 'sunrise_sunset_widget';
10      }
11  
12      public function get_title() {
13          return __( 'Sunrise & Sunset', 'sunrise-sunset-addon' );
14      }
15  
16      public function get_icon() {
17          return 'eicon-clock';
18      }
19  
20      public function get_categories() {
21          return [ 'general' ];
22      }
23  
24      protected function register_controls() {
25          $this->start_controls_section(
26              'content_section',
27              [
28                  'label' => __( 'Settings', 'sunrise-sunset-addon' ),
29                  'tab'   => \Elementor\Controls_Manager::TAB_CONTENT,
30              ]
31          );
32  
33          $this->add_control(
34              'location',
35              [
36                  'label'       => __( 'Location (City)', 'sunrise-sunset-addon' ),
37                  'type'        => \Elementor\Controls_Manager::TEXT,
38                  'default'     => 'New York',
39                  'placeholder' => __( 'Enter a city name', 'sunrise-sunset-addon' ),
40              ]
41          );
42  
43          $this->end_controls_section();
44      }
45  
46      protected function render() {
47          $settings = $this->get_settings_for_display();
48          $location = sanitize_text_field( $settings['location'] );
49  
50          $times = $this->get_sun_times( $location );
51  
52          if ( ! $times ) {
53              echo '<p>Could not fetch data for this location.</p>';
54              return;
55          }
56  
57          echo '<h3>Sunrise & Sunset times for ' . esc_html( $location ) . '</h3>';
58          echo '<p>Sunrise: ' . esc_html( $times['sunrise'] ) . '</p>';
59          echo '<p>Sunset: ' . esc_html( $times['sunset'] ) . '</p>';
60      }
61  
62      private function get_sun_times( $location ) {
63          $api_url = 'https://api.sunrise-sunset.org/json?formatted=0&address=' . urlencode( $location );
64          $response = wp_remote_get( $api_url, [ 'timeout' => 10 ] );
65  
66          if ( is_wp_error( $response ) ) {
67              return false;
68          }
69  
70          $data = json_decode( wp_remote_retrieve_body( $response ), true );
71  
72          if ( empty( $data['results'] ) || $data['status'] !== 'OK' ) {
73              return false;
74          }
75  
76          return [
77              'sunrise' => date_i18n( get_option( 'time_format' ), strtotime( $data['results']['sunrise'] ) ),
78              'sunset'  => date_i18n( get_option( 'time_format' ), strtotime( $data['results']['sunset'] ) ),
79          ];
80      }
81  }

This class includes sanitization, escaping, and a simple API call. It’s lean but safe and ready for real projects.

php
1$cache_key = 'sun_times_' . md5( $location );
2  $cached = get_transient( $cache_key );
3  if ( $cached ) return $cached;
4  
5  // API call happens here
6  
7  set_transient( $cache_key, $result, 12 * HOUR_IN_SECONDS );

Caching results avoids calling the external API on every page load and improves performance.

Activate and Test

  1. Zip the sunrise-sunset-addon folder and upload it to WordPress via “Plugins > Add New”.
  2. Activate the plugin, open any page with Elementor, and look for “Sunrise & Sunset” under General widgets.
  3. Add it to your layout, set a location, and see real sunrise and sunset times pulled directly from the API.

Elementor developer documentation:

In-depth guide from WebDesignSun: “Elementor Custom Widget Tutorial”:

Unlimited Elements article: “How to Create a Custom Elementor Widget”:

And that's it — you now have a reusable Elementor widget structure that you can customize, expand, and ship in your projects. From here, you can add style controls, typography settings, or connect to more advanced APIs. Same pattern, more power.

About the Author
Jonas Lindemann

I’m an experienced SEO professional with over a decade of helping over 100 businesses rank higher online, especially local businesses, e-commerce stores and SaaS. As the co-founder of LPagery, I specialize in practical, proven strategies for regular SEO and Local SEO success.