$npx -y skills add Lonsdale201/wp-agent-skills --skill elementor-dynamic-tag-registerRegister a custom Elementor Dynamic Tag from a companion
| 1 | # Elementor: register a Dynamic Tag |
| 2 | |
| 3 | For developers shipping a companion plugin that adds Dynamic Tags — "show this product's shipping class", "this user's last order total", "this course's progress %". The dynamic-tags **infrastructure** (base classes, the registration manager, the hooks, the category/group system) ships in **free** Elementor under `Elementor\Core\DynamicTags\*`; this skill is the stable extension contract for registering your own tags against it. It does **not** cover building the tag's controls/fallback (see `elementor-dynamic-tag-fields`) or AJAX pickers (see `elementor-dynamic-tag-ajax-select`). |
| 4 | |
| 5 | ## The Pro-feature reality (read this first) |
| 6 | |
| 7 | The user's instinct that "dynamic tags are a Pro feature" is half-right, and the distinction matters: |
| 8 | |
| 9 | - The **API is in free Elementor** — `\Elementor\Core\DynamicTags\Tag`, `Data_Tag`, `Base_Tag`, the `Manager`, the `elementor/dynamic_tags/register` hook, and the category constants all live in the free plugin. Your tag classes compile and register without Pro. |
| 10 | - Free Elementor registers **zero tags of its own** — `Module::get_tag_classes_names()` returns `[]` ([modules/dynamic-tags/module.php:116-118](module.php)) and only one group, "Base Tags" ([module.php:130-136](module.php)). |
| 11 | - **Pro** ships ~34 tags plus 8 groups, every one gated behind a license check — `API::is_licence_has_feature( 'dynamic-tags', … )` ([elementor-pro/modules/dynamic-tags/module.php:97](module.php)). |
| 12 | - The **AJAX query control** (`QueryControlModule::QUERY_CONTROL_ID`) used to pick from large datasets is **Pro-only**. Without Pro you fall back to a manual field — see `elementor-dynamic-tag-ajax-select`. |
| 13 | |
| 14 | Practical rule: **build for "Elementor active, Pro likely present", feature-detect Pro-only pieces, and degrade gracefully.** The reference plugin does exactly this with a `has_query_control_support()` check before using the Pro autocomplete control. |
| 15 | |
| 16 | ## Misconception this skill corrects |
| 17 | |
| 18 | > "I'll register my tag with `add_action( 'elementor/dynamic_tags/register_tags', … )` and `$manager->register_tag( MyTag::class )` like the old tutorials show." |
| 19 | |
| 20 | Both still work — Elementor keeps deprecation shims — but both are **deprecated since 3.5.0**: |
| 21 | |
| 22 | ```php |
| 23 | // DEPRECATED (3.5.0) — fires a _doing_it_wrong notice, still functional |
| 24 | add_action( 'elementor/dynamic_tags/register_tags', function ( $manager ) { |
| 25 | $manager->register_tag( '\MyPlugin\Tags\MyTag' ); // string class name |
| 26 | } ); |
| 27 | |
| 28 | // MODERN — register() takes an INSTANCE, not a class string |
| 29 | add_action( 'elementor/dynamic_tags/register', function ( $manager ) { |
| 30 | $manager->register( new \MyPlugin\Tags\MyTag() ); |
| 31 | } ); |
| 32 | ``` |
| 33 | |
| 34 | Verified: the deprecated action is wrapped in `do_deprecated_action( 'elementor/dynamic_tags/register_tags', …, '3.5.0', 'elementor/dynamic_tags/register' )` ([manager.php:284-289](manager.php)); the modern action fires at [manager.php:302](manager.php). `register_tag()` is `@deprecated 3.5.0 Use register()` ([manager.php:315](manager.php)); `register()` takes a `Base_Tag` instance ([manager.php:337](manager.php)). |
| 35 | |
| 36 | (The bundled reference plugin was migrated to the modern API on 2026-06-17 — [TagManager.php:45,109](TagManager.php) now hooks `register` and calls `register( new $tag_class() )`. Older copies and most tutorials still show the legacy pair, which is why it's worth recognising.) |
| 37 | |
| 38 | ## When to use this skill |
| 39 | |
| 40 | Trigger when ANY of the following is true: |
| 41 | |
| 42 | - The diff hooks `elementor/dynamic_tags/register` or the legacy `elementor/dynamic_tags/register_tags`. |
| 43 | - A class `extends \Elementor\Core\DynamicTags\Tag` / `Data_Tag` / `Base_Tag` (or a Pro `Pro_Tag` / `Pro_Data_Tag`). |
| 44 | - The user asks "how do I add a |