elementor-themes

1. Theme Builder Locations

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "elementor-themes" with this command: npx skills add peixotorms/odinlayer-skills/peixotorms-odinlayer-skills-elementor-themes

  1. Theme Builder Locations

Registering Locations

Register all core locations at once:

function theme_prefix_register_elementor_locations( $elementor_theme_manager ) { $elementor_theme_manager->register_all_core_location(); } add_action( 'elementor/theme/register_locations', 'theme_prefix_register_elementor_locations' );

Register specific locations or custom locations:

$elementor_theme_manager->register_location( 'header' ); $elementor_theme_manager->register_location( 'footer' ); $elementor_theme_manager->register_location( 'main-sidebar', [ 'label' => esc_html__( 'Main Sidebar', 'theme-name' ), 'multiple' => true, // allow multiple templates (default: false) 'edit_in_content' => false, // edit in content area (default: true) ] );

Location Types

Location Replaces

header

header.php

footer

footer.php

single

singular.php, single.php, page.php, attachment.php, 404.php

archive

archive.php, taxonomy.php, author.php, date.php, search.php

Displaying Locations with Fallback

<?php if ( ! function_exists( 'elementor_theme_do_location' ) || ! elementor_theme_do_location( 'archive' ) ) { get_template_part( 'template-parts/archive' ); } ?>

elementor_theme_do_location() returns true if a template was displayed, false otherwise.

Migration: Functions Method

Use elementor_theme_do_location() with fallback in header.php, footer.php, single.php, archive.php:

<!-- header.php --> <!doctype html> <html <?php language_attributes(); ?>> <head> <meta charset="<?php bloginfo( 'charset' ); ?>"> <?php wp_head(); ?> </head> <body <?php body_class(); ?>> <?php if ( ! function_exists( 'elementor_theme_do_location' ) || ! elementor_theme_do_location( 'header' ) ) { get_template_part( 'template-parts/header' ); } ?>

Migration: Hooks Method

Register locations with hook and remove_hooks parameters to auto-replace theme output:

$elementor_theme_manager->register_location( 'header', [ 'hook' => 'theme_prefix_header', 'remove_hooks' => [ 'theme_prefix_print_elementor_header' ], ] );

  1. Theme Conditions

Class Structure

Extend \ElementorPro\Modules\ThemeBuilder\Conditions\Condition_Base .

Required methods:

Method Returns Purpose

get_type()

string Condition group: general , singular , archive

get_name()

string Unique condition identifier

get_label()

string Display label

check( $args )

bool Evaluate if condition matches

get_all_label()

string Label for "All" option (parent conditions only)

register_sub_conditions()

void Register child conditions

Registration

function register_new_theme_conditions( $conditions_manager ) { require_once( DIR . '/theme-conditions/my-condition.php' ); $conditions_manager->get_condition( 'general' )->register_sub_condition( new \My_Condition() ); } add_action( 'elementor/theme/register_conditions', 'register_new_theme_conditions' );

Condition Groups

ID Label Description

general

General Entire site conditions

archive

Archives Archive page conditions

singular

Singular Single page/post conditions

Simple Example: 404 / Front Page

class Front_Page_Condition extends \ElementorPro\Modules\ThemeBuilder\Conditions\Condition_Base { public static function get_type(): string { return 'general'; } public function get_name(): string { return 'front_page'; } public function get_label(): string { return esc_html__( 'Front Page', 'textdomain' ); } public function check( $args ): bool { return is_front_page(); } }

class Not_Found_Condition extends \ElementorPro\Modules\ThemeBuilder\Conditions\Condition_Base { public static function get_type(): string { return 'general'; } public function get_name(): string { return 'not_found_404'; } public function get_label(): string { return esc_html__( '404 Page', 'textdomain' ); } public function check( $args ): bool { return is_404(); } }

Advanced Example: Parent with Sub-Conditions

class Logged_In_User_Condition extends \ElementorPro\Modules\ThemeBuilder\Conditions\Condition_Base { public static function get_type(): string { return 'general'; } public function get_name(): string { return 'logged_in_user'; } public function get_label(): string { return esc_html__( 'Logged-in User', 'textdomain' ); } public function get_all_label(): string { return esc_html__( 'Any user role', 'textdomain' ); }

public function register_sub_conditions(): void {
    global $wp_roles;
    if ( ! isset( $wp_roles ) ) { $wp_roles = new \WP_Roles(); }
    foreach ( $wp_roles->get_names() as $role ) {
        $this->register_sub_condition( new \User_Role_Condition( $role ) );
    }
}

public function check( $args ): bool { return is_user_logged_in(); }

}

class User_Role_Condition extends \ElementorPro\Modules\ThemeBuilder\Conditions\Condition_Base { private $user_role; public function __construct( $user_role ) { parent::_construct(); $this->user_role = $user_role; } public static function get_type(): string { return 'logged_in_user'; } public function get_name(): string { return strtolower( $this->user_role . 'role' ); } public function get_label(): string { return sprintf( esc_html( '%s role', 'textdomain' ), $this->user_role ); } public function check( $args ): bool { $current_user = wp_get_current_user(); return in_array( $this->user_role, (array) $current_user->roles ); } }

  1. Dynamic Tags

Class Structure

Extend \Elementor\Core\DynamicTags\Tag .

Required methods:

Method Returns Purpose

get_name()

string Unique tag identifier

get_title()

string Display title

get_group()

array Groups this tag belongs to

get_categories()

array Data type categories

render()

void Output the dynamic value (echo)

register_controls()

void Optional: add tag settings

Dynamic Tag Categories

Constant Value Use For

Module::NUMBER_CATEGORY

number

Numeric values

Module::TEXT_CATEGORY

text

Text strings

Module::URL_CATEGORY

url

URLs

Module::COLOR_CATEGORY

color

Color values

Module::IMAGE_CATEGORY

image

Image data

Module::MEDIA_CATEGORY

media

Media files

Module::GALLERY_CATEGORY

gallery

Image galleries

Module::POST_META_CATEGORY

post_meta

Post meta fields

Full constant path: \Elementor\Modules\DynamicTags\Module::CATEGORY_NAME .

Registration

function register_dynamic_tags( $dynamic_tags_manager ) { require_once( DIR . '/dynamic-tags/my-tag.php' ); $dynamic_tags_manager->register( new \My_Dynamic_Tag() ); } add_action( 'elementor/dynamic_tags/register', 'register_dynamic_tags' );

Register Custom Group

function register_custom_dynamic_tag_group( $dynamic_tags_manager ) { $dynamic_tags_manager->register_group( 'my-group', [ 'title' => esc_html__( 'My Group', 'textdomain' ), ] ); } add_action( 'elementor/dynamic_tags/register', 'register_custom_dynamic_tag_group' );

Controls in Dynamic Tags

Use $this->add_control() in register_controls() and $this->get_settings( 'key' ) in render() .

Code Examples

See resources/dynamic-tags.md for complete examples: Simple tag (Random Number), Advanced tag with controls (ACF Average), Complex tag with SELECT control (Server Variables), and unregistering tags.

  1. Finder

Class Structure

Extend \Elementor\Core\Common\Modules\Finder\Base_Category .

Method Returns Purpose

get_id()

string Unique category identifier

get_title()

string Display title

get_category_items( array $options = [] )

array Items in this category

is_dynamic()

bool If true, items loaded via AJAX on search

Item Properties

Property Type Required Description

title

string Yes Displayed to user

icon

string No Icon before title

url

string Yes Link URL

keywords

array No Search keywords

Registration

function register_finder_category( $finder_categories_manager ) { require_once( DIR . '/finder/my-category.php' ); $finder_categories_manager->register( new \My_Finder_Category() ); } add_action( 'elementor/finder/register', 'register_finder_category' );

Default Categories

ID Description

create

Create posts, pages, templates

edit

Edit posts, pages, templates

general

General Elementor links

settings

Elementor settings pages

tools

Elementor tools

site

Site links

Add Items to Existing Category

function add_finder_items( array $categories ) { $categories['create']['items']['theme-template'] = [ 'title' => esc_html__( 'Add New Theme Template', 'textdomain' ), 'icon' => 'plus-circle-o', 'url' => admin_url( 'edit.php?post_type=elementor_library#add_new' ), 'keywords' => [ 'template', 'theme', 'new', 'create' ], ]; return $categories; } add_filter( 'elementor/finder/categories', 'add_finder_items' );

Remove Categories / Items

// Remove entire category function remove_finder_category( array $categories ) { unset( $categories['edit'] ); return $categories; } add_filter( 'elementor/finder/categories', 'remove_finder_category' );

// Remove specific item function remove_finder_item( array $categories ) { unset( $categories['create']['items']['post'] ); return $categories; } add_filter( 'elementor/finder/categories', 'remove_finder_item' );

Simple Example: Social Media Links

See resources/context-menu-finder.md for a complete Finder category implementation.

  1. Context Menu (JavaScript)

Context Menu Types

  • Element - right-click on Section, Column, or Widget

  • Empty Column - right-click on empty column area

  • Add New - right-click on add new section/template area

Available Groups by Element Type

Group Section Column Widget

general

Yes Yes Yes

addNew

No Yes No

clipboard

Yes Yes Yes

save

Yes No Yes

tools

Yes Yes Yes

delete

Yes Yes Yes

PHP: Enqueue Editor Script

function my_context_menu_scripts() { wp_enqueue_script( 'my-context-menus', plugins_url( 'assets/js/context-menus.js', FILE ), [], '1.0.0', false ); } add_action( 'elementor/editor/after_enqueue_scripts', 'my_context_menu_scripts' );

JS: Add New Group with Actions

window.addEventListener( 'elementor/init', () => { elementor.hooks.addFilter( 'elements/context-menu/groups', ( customGroups, elementType ) => { const newGroup = { name: 'my-custom-group', actions: [ { name: 'my-action-1', icon: 'eicon-alert', title: 'My Action', isEnabled: () => true, callback: () => console.log( 'Action triggered' ), }, ], }; if ( 'widget' === elementType ) { customGroups.push( newGroup ); } return customGroups; } ); } );

JS: Modify Groups and Actions

// Add action to existing group customGroups.forEach( ( group ) => { if ( 'general' === group.name ) { group.actions.push( newAction ); } } );

// Remove group const idx = customGroups.findIndex( ( g ) => 'my-group' === g.name ); if ( idx > -1 ) { customGroups.splice( idx, 1 ); }

// Remove action from group group.actions.splice( group.actions.findIndex( ( a ) => 'my-action' === a.name ), 1 );

// Update action property group.actions.forEach( ( a ) => { if ( 'my-action' === a.name ) { a.icon = 'eicon-code'; } } );

  1. Hello Elementor Theme

All Theme Hooks

Hook (Filter) Default Purpose

hello_elementor_post_type_support

true

Register post type support

hello_elementor_add_theme_support

true

Register theme features (title-tag, thumbnails, etc.)

hello_elementor_register_menus

true

Register navigation menus

hello_elementor_add_woocommerce_support

true

Register WooCommerce support

hello_elementor_register_elementor_locations

true

Register Elementor theme locations

hello_elementor_enqueue_style

true

Load style.min.css

hello_elementor_enqueue_theme_style

true

Load theme.min.css

hello_elementor_content_width

800

Content width in pixels

hello_elementor_page_title

true

Show page title

hello_elementor_viewport_content

width=device-width, initial-scale=1

Viewport meta tag

hello_elementor_enable_skip_link

true

Enable accessibility skip link

hello_elementor_skip_link_url

#content

Skip link target URL

Disable a Feature

add_filter( 'hello_elementor_register_menus', '__return_false' ); add_filter( 'hello_elementor_enqueue_theme_style', '__return_false' ); add_filter( 'hello_elementor_page_title', '__return_false' );

Custom Content Width

function custom_content_width() { return 1024; } add_filter( 'hello_elementor_content_width', 'custom_content_width' );

Other Customizations

// Custom viewport add_filter( 'hello_elementor_viewport_content', fn() => 'width=100vw, height=100vh, user-scalable=no' );

// Custom skip link by page type add_filter( 'hello_elementor_skip_link_url', function() { if ( is_404() ) { return '#404-content'; } return is_page() ? '#page-content' : '#main-content'; } );

// Override navigation menus add_filter( 'hello_elementor_register_menus', 'return_false' ); register_nav_menus( [ 'my-header-menu' => esc_html( 'Header Menu', 'textdomain' ) ] );

// Remove description meta tag add_action( 'after_setup_theme', function() { remove_action( 'wp_head', 'hello_elementor_add_description_meta_tag' ); } );

  1. Hosting Cache Integration

Purge Everything

Action hook with no parameters. Clears all page cache.

do_action( 'elementor/hosting/page_cache/purge_everything' );

Allow Page Cache Filter

function custom_page_cache( $allow ) { if ( ! $allow ) { return $allow; } return is_my_special_page(); } add_filter( 'elementor/hosting/page_cache/allow_page_cache', 'custom_page_cache', 20 );

Changed URLs Filter

Hook: elementor/hosting/page_cache/{$content_type}_changed_urls

$content_type values: post , comment , woocommerce_product , etc.

Parameters: $urls (array), $content_id (int).

function clear_cache_on_product_update( $urls, $product_id ) { if ( ! is_array( $urls ) || empty( $urls ) ) { $urls = []; } $urls[] = site_url( '/my-path' ); return $urls; } add_filter( 'elementor/hosting/page_cache/woocommerce_product_changed_urls', 'clear_cache_on_product_update', 10, 2 );

  1. Common Mistakes

Mistake Consequence Fix

Not checking function_exists( 'elementor_theme_do_location' )

Fatal error if Elementor not active Always wrap in function_exists check with fallback

Using get_type() value that does not match parent condition name Sub-condition not displayed get_type() must return the parent condition's get_name() value

Returning wrong category constant in dynamic tags Tag not shown for matching controls Use \Elementor\Modules\DynamicTags\Module::*_CATEGORY constants

Missing echo in dynamic tag render()

Empty output render() must echo , not return

Not escaping dynamic tag output XSS vulnerability Use wp_kses_post() , esc_html() , or esc_url()

Forgetting elementor/init listener in context menu JS Filter runs before Elementor ready Wrap in window.addEventListener( 'elementor/init', ... )

Using elementor/editor/after_enqueue_scripts for frontend JS Script only loads in editor Use wp_enqueue_scripts for frontend, editor hook for editor-only

Not validating $allow parameter in cache filter Overrides other filters Check if ( ! $allow ) { return $allow; } first

Registering location without Elementor Pro active Theme Builder requires Pro Check if Elementor Pro is active before registering conditions

Calling register_all_core_location() and individual locations Duplicate registrations Use one or the other, not both

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

elementor-hooks

No summary provided by upstream source.

Repository SourceNeeds Review
General

elementor-controls

No summary provided by upstream source.

Repository SourceNeeds Review
General

elementor-forms

No summary provided by upstream source.

Repository SourceNeeds Review
General

flyonui

No summary provided by upstream source.

Repository SourceNeeds Review