# Elementor — Automação Programática e Pipelines Referência técnica para manipular o Elementor sem GUI: WP-CLI, MySQL, REST API, PHP Hooks, Kits e CSS. --- ## 1. WP-CLI + Elementor (CWP) ### Formato Obrigatório CWP ```bash PHP="/opt/alt/php-fpm83/usr/bin/php" WP="$PHP /usr/local/bin/wp --allow-root --path=/home/USER/public_html" ``` ### Comandos Essenciais ```bash # Regenerar CSS (SEMPRE após qualquer alteração programática) $WP elementor flush-css --regenerate # Substituição segura de URLs (evita corrupção JSON) # NUNCA usar wp search-replace directamente em _elementor_data $WP elementor replace-urls $URL_OLD $URL_NEW $WP search-replace $URL_OLD $URL_NEW --skip-columns=guid # Importar Kit (design system completo) $WP elementor kit import /tmp/kit.zip \ --include=site-settings,templates,content \ --overrideConditions=all # Sincronizar esquema BD após update do plugin $WP elementor update db # Modo manutenção $WP maintenance-mode activate $WP maintenance-mode deactivate ``` ### Pipeline de Deploy Completo ```bash #!/bin/bash # Pipeline de rebranding via WP-CLI (CWP) PHP="/opt/alt/php-fpm83/usr/bin/php" SITE_PATH="/home/USER/public_html" KIT_PATH="/tmp/rebranding-2026.zip" URL_OLD="https://staging.agencia.com" URL_NEW="https://www.producao.com" WP="$PHP /usr/local/bin/wp --allow-root --path=$SITE_PATH" $WP maintenance-mode activate $WP elementor kit import $KIT_PATH --include=site-settings,templates,content --overrideConditions=all $WP elementor replace-urls $URL_OLD $URL_NEW $WP search-replace $URL_OLD $URL_NEW --skip-columns=guid $WP elementor flush-css --regenerate $WP elementor update db $WP maintenance-mode deactivate ``` ### Avaliação do Método | Critério | Análise | |----------|---------| | Complexidade | Baixa — sintaxe documentada, comportamento previsível | | Segurança | Alta — invoca internos do WordPress, risco apenas em SSH | | Usar quando | Deploy, purga de cache, migração de URLs, sincronização BD | --- ## 2. Manipulação Directa via MySQL ### Estrutura _elementor_data O Elementor guarda layouts como JSON em `wp_postmeta`. Três meta keys obrigatórias: | Meta Key | Valor | |----------|-------| | `_elementor_edit_mode` | `builder` | | `_elementor_template_type` | `wp-page`, `kit`, `header`, `footer` | | `_elementor_data` | JSON array com toda a árvore de widgets | ### Estrutura JSON Interna ```json [{ "id": "3130e2cf", "elType": "container", "isInner": false, "settings": { ... }, "elements": [{ "id": "a1b2c3d4", "elType": "widget", "widgetType": "button", "settings": { "text": "Clique aqui", "link": { "url": "https://exemplo.com" } } }] }] ``` ### Query MySQL com JSON_REPLACE ```sql -- Substituição cirúrgica num widget específico -- SEMPRE fazer backup antes UPDATE wp_postmeta SET meta_value = JSON_REPLACE( meta_value, '$.elements.elements.settings.link.url', 'https://www.novo-destino.com/contacto' ) WHERE meta_key = '_elementor_data' AND post_id IN (1042, 1045, 1088); -- OBRIGATÓRIO após qualquer UPDATE directo: -- Executar 'wp elementor flush-css --regenerate' via WP-CLI ``` ### Regra Crítica: NUNCA wp search-replace ```bash # ERRADO — corrompe JSON silenciosamente (whitespace of death) wp search-replace 'http://antigo.com' 'https://novo.com' # CORRECTO — usa lógica nativa do Elementor wp elementor replace-urls 'http://antigo.com' 'https://novo.com' ``` ### Avaliação do Método | Critério | Análise | |----------|---------| | Complexidade | Alta — parsing JSON, funções MySQL JSON_* | | Segurança | Muito Baixa — sem validação, um char inválido corrompe a página | | Usar quando | Auditoria forense, extracção analítica em massa (10.000+ posts) | --- ## 3. REST API Custom Endpoint Para agentes externos (n8n, Make, Python) manipularem layouts via HTTP. ### Registar Endpoint (functions.php ou plugin MU) ```php 'POST', 'callback' => 'ai_agent_update_elementor_layout', 'permission_callback' => function() { return current_user_can('edit_pages'); } ]); }); function ai_agent_update_elementor_layout(WP_REST_Request $request) { $post_id = absint($request->get_param('post_id')); $json_data = $request->get_param('elementor_json'); // wp_slash é OBRIGATÓRIO — protege JSON de corrupção de escape update_post_meta($post_id, '_elementor_data', wp_slash(json_encode($json_data))); update_post_meta($post_id, '_elementor_edit_mode', 'builder'); // Invalidação de cache OBRIGATÓRIA delete_post_meta($post_id, '_elementor_css'); if (did_action('elementor/loaded')) { \Elementor\Plugin::$instance->files_manager->clear_cache(); } return rest_ensure_response([ 'status' => 'success', 'post_id' => $post_id ]); } ``` ### Autenticação ```bash # Via Application Passwords (WordPress 5.6+) curl -X POST https://site.pt/wp-json/agencia-ai/v1/atualizar-layout \ -H "Authorization: Basic $(echo -n 'user:app-password' | base64)" \ -H "Content-Type: application/json" \ -d '{"post_id": 2607, "elementor_json": [...]}' ``` ### Avaliação do Método | Critério | Análise | |----------|---------| | Complexidade | Média — endpoint PHP + formatar JSON _elementor_data válido | | Segurança | Alta — usa permissões WordPress + HTTPS | | Usar quando | Webhooks, n8n/Make, geração de páginas a partir de CRM | --- ## 4. PHP Hooks — Dynamic Tags Para conteúdo que se actualiza em runtime sem reescrever JSON. ### Registar Dynamic Tag ```php register(new IA_Agente_Metrica_Tag()); }); ``` ### Padrão: Agente IA actualiza Transient ```php // Agente IA executa isto remotamente (via eval-file ou endpoint) set_transient('ia_agente_ultima_metrica', '

Taxa de conversão: 4.2%

', DAY_IN_SECONDS); ``` ### Avaliação do Método | Critério | Análise | |----------|---------| | Complexidade | Alta — OOP PHP, Event Loop WordPress, DynamicTags | | Segurança | Muito Alta — lógica server-side, CI/CD, sem exposição JSON | | Usar quando | Conteúdo em tempo real (cotações, stock, métricas) — requer Elementor **Pro** | --- ## 5. Site Kits — Estrutura e Geração ### Estrutura ZIP de um Kit ``` kit.zip ├── manifest.json # Índice mestre — mapeamento de todos os ficheiros ├── site-settings.json # Cores globais, tipografia, configurações do tema ├── header-template.json # Template de cabeçalho ├── footer-template.json # Template de rodapé └── page-template.json # Templates de páginas ``` ### manifest.json (estrutura mínima) ```json { "templates": [ { "title": "Header Principal", "type": "header", "fileName": "header-template.json" } ], "site_settings": { "title": "Site Settings", "fileName": "site-settings.json" } } ``` ### Geração em Python ```python import json, zipfile, os kit_settings = { "version": "0.4", "title": "Site Settings", "settings": { "system_colors": [ {"_id": "primary", "title": "Primária", "color": "#1E40AF"}, {"_id": "secondary", "title": "Secundária", "color": "#10B981"} ], "system_typography": [ {"_id": "primary", "title": "Principal", "typography_font_family": "Inter"} ] } } manifest = { "templates": [], "site_settings": {"title": "Site Settings", "fileName": "site-settings.json"} } os.makedirs('/tmp/kit_build', exist_ok=True) with open('/tmp/kit_build/site-settings.json', 'w') as f: json.dump(kit_settings, f) with open('/tmp/kit_build/manifest.json', 'w') as f: json.dump(manifest, f) with zipfile.ZipFile('/tmp/agencia-kit.zip', 'w') as z: z.write('/tmp/kit_build/manifest.json', 'manifest.json') z.write('/tmp/kit_build/site-settings.json', 'site-settings.json') # Importar via WP-CLI (CWP) # /opt/alt/php-fpm83/usr/bin/php /usr/local/bin/wp elementor kit import /tmp/agencia-kit.zip \ # --include=site-settings,templates --overrideConditions=all \ # --allow-root --path=/home/USER/public_html ``` --- ## 6. CSS — Invalidação de Cache ### Localização dos Ficheiros CSS ``` wp-content/uploads/elementor/css/post-{ID}.css # CSS por página wp-content/uploads/elementor/css/global.css # CSS global ``` ### Invalidação Programática (PHP) ```php // Após qualquer alteração directa a _elementor_data ou post_meta if (did_action('elementor/loaded')) { \Elementor\Plugin::$instance->files_manager->clear_cache(); } // Alternativa: apagar meta específica delete_post_meta($post_id, '_elementor_css'); ``` ### Rebranding Global — Kit Activo ```php // Obter ID do kit activo $kit_id = get_option('elementor_active_kit'); // Ler configurações globais $settings = get_post_meta($kit_id, '_elementor_page_settings', true); // Alterar cor primária if (!empty($settings['system_colors'])) { foreach ($settings['system_colors'] as &$cor) { if ($cor['_id'] === 'primary') { $cor['color'] = '#FF0000'; } } } // Guardar (wp_slash protege o JSON) update_post_meta($kit_id, '_elementor_page_settings', $settings); // Invalidar cache CSS if (did_action('elementor/loaded')) { \Elementor\Plugin::$instance->files_manager->clear_cache(); } ``` --- ## 7. Regras Críticas e Riscos ### Nunca fazer | Erro | Consequência | Correcto | |------|-------------|----------| | `wp search-replace` em `_elementor_data` | Corrupção silenciosa do JSON, layout desaparece | `wp elementor replace-urls` | | UPDATE MySQL sem flush-css | CSS desactualizado, design dessincronizado | Sempre `wp elementor flush-css --regenerate` | | `update_post_meta` sem `wp_slash()` | Corrupção de escapes no JSON | `wp_slash(json_encode($data))` | | Múltiplos agentes a editar o mesmo post | Sobreposição de dados | Locks ou filas de processamento | ### IDs de Widgets São Aleatórios Os IDs de nós JSON (ex: `"id":"3130e2cf"`) são alfanuméricos aleatórios. Para manipular um widget específico via MySQL ou REST API: 1. Fazer parsing da árvore JSON completa primeiro 2. Encontrar o widget pelo `widgetType` ou conteúdo 3. Só então operar no ID correcto ### Limitações Elementor Free vs Pro | Funcionalidade | Free | Pro | |----------------|------|-----| | `wp elementor flush-css` | ✅ | ✅ | | `wp elementor kit import` | ✅ | ✅ | | Dynamic Tags | ❌ | ✅ | | Theme Builder (header/footer) | ❌ | ✅ | --- ## 8. MCP Elementor (Integração Futura) O projecto **Ultimate Elementor MCP** expõe ~60 ferramentas para manipulação via linguagem natural: - `create_container`, `create_heading`, `delete_element` - `get_page_structure` — lê árvore JSON (resolve problema dos IDs aleatórios) - `update_widget_settings` **Autenticação:** Application Passwords ou JWT (mesma arquitectura do REST API). **Quando usar:** Assistentes conversacionais, automações complexas onde formatar JSON raw em Python seria impraticável. **Referência:** [Ultimate Elementor MCP — LobeHub](https://lobehub.com/mcp/mbrown1837-ultimate-elementor-mcp) --- *Automação Elementor | Descomplicar® | Baseado em: Manipulação Programática do Elementor — Automação via IA | 18-02-2026*