$npx -y skills add Lonsdale201/wp-agent-skills --skill elementor-experiments-and-markupDesign Elementor addons / widgets / dynamic tags to survive
| 1 | # Elementor: experiments and markup-changing features |
| 2 | |
| 3 | For developers shipping a companion plugin / theme that adds **widgets, dynamic tags, or frontend CSS/JS** on top of Elementor. Elementor ships "experiments" (feature flags) under `core/experiments/manager.php`. Most are cosmetic, but two **Performance** experiments **change the rendered HTML** and are **default-ON on new installs**, so a modern addon must handle them or it silently breaks on a large share of sites. |
| 4 | |
| 5 | ## Read this first — you cannot assume the state |
| 6 | |
| 7 | Experiment state is per-site and three-valued (Default / Active / Inactive), and the effective default differs between fresh and upgraded installs. **Never hardcode an assumption; detect at runtime:** |
| 8 | |
| 9 | ```php |
| 10 | if ( \Elementor\Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' ) ) { |
| 11 | // adapt markup |
| 12 | } |
| 13 | ``` |
| 14 | |
| 15 | Verified: `Experiments\Manager::is_feature_active( $name, $check_dependencies = false )` at [core/experiments/manager.php:257](manager.php); actual state resolves to the user's explicit `state` unless it's `Default`, then the feature's `default` ([manager.php](manager.php) `get_feature_actual_state`). |
| 16 | |
| 17 | The two markup-changing experiments (both `release_status => STABLE`, tag "Performance", `new_site.default_active => true`) — verified [manager.php:312-381](manager.php): |
| 18 | |
| 19 | | Experiment | `name` | Default on NEW install (≥ ver) | What it changes | |
| 20 | |---|---|---|---| |
| 21 | | **Inline Font Icons** | `e_font_icon_svg` | ON (≥ 3.17.0) | Icons render as inline `<svg>`; Font Awesome + eicons CSS/fonts NOT loaded on frontend | |
| 22 | | **Optimized Markup** | `e_optimized_markup` | ON (≥ 3.30.0) | Removes inner wrapper HTML (`.elementor-widget-container`) from widgets to shrink the DOM | |
| 23 | |
| 24 | > `new_site.default_active => true` means a site first installed at/after that version defaults the experiment ON. Sites upgraded from older versions may keep it OFF (`e_optimized_markup` / `container` have `default => STATE_INACTIVE`). So the SAME addon meets both states in the wild — which is exactly why you detect at runtime. |
| 25 | |
| 26 | ## Misconception this skill corrects |
| 27 | |
| 28 | > "My widget's icons render fine in the Elementor editor, so my icon markup is correct." |
| 29 | |
| 30 | The editor/preview is misleading. `Icons_Manager` only switches to inline SVG **when not in edit/preview mode** — verified [includes/managers/icons.php:186](icons.php) (`is_font_icon_inline_svg() && ! is_edit_mode() && ! is_preview_mode()`). So with Inline Font Icons ON, the editor still loads the icon **fonts** and hardcoded `<i class="fas fa-star">` looks correct there — but on the **frontend** the Font Awesome CSS is absent and your hardcoded icon renders as an empty/broken glyph. Always test on the published frontend, and always emit icons through `Icons_Manager::render_icon()`. |
| 31 | |
| 32 | ## When to use this skill |
| 33 | |
| 34 | - Building or reviewing a **custom widget** (its `render()` markup, wrapper structure, or icon output). |
| 35 | - Shipping **frontend CSS/JS** that targets Elementor's DOM (`.elementor-widget-container`, widget inner structure). |
| 36 | - Any addon that renders icons chosen via the `ICONS` control. |
| 37 | - Diagnosing "works on my site, breaks on the client's" icon/layout bugs — usually an experiment default difference. |
| 38 | - The diff references `is_feature_active`, `has_widget_inner_wrapper`, `Icons_Manager`, `e_optimized_markup`, or `e_font_icon_svg`. |
| 39 | |
| 40 | ## Optimized Markup (`e_optimized_markup`) |
| 41 | |
| 42 | The wrapper contract lives on the element base. `Element_Base::has_widget_inner_wrapper()` returns **`true` by default** — verified [includes/base/element-base.php:1588](element-base.php). `Widget_Base::render()` prints the `<div class="ele |