Você chama wp_add_inline_script() dentro de um shortcode. Funciona perfeitamente em temas clássicos. Aí você troca pra um block theme — ou seu usuário troca — e de repente: nada. Sem erro PHP, sem warning, só uma falha silenciosa e um X is not defined no console do browser.
Isso é uma inconsistência conhecida, rastreada no WordPress Trac #54958. Aqui vai o que está realmente acontecendo e como corrigir direito.
O Problema
A diferença está em quando os shortcodes rodam em relação ao wp_head().
Em um tema clássico:
wp_enqueue_scriptsdispara dentro dowp_head()→ seu handle é registrado- Conteúdo renderiza → shortcode executa →
wp_add_inline_script('my-handle', ...)✅ handle já existe
Em um block theme (FSE):
get_the_block_template_html()renderiza blocks e shortcodes antes dowp_head()- Shortcode executa →
wp_add_inline_script('my-handle', ...)❌ handle ainda não existe wp_head()dispara →wp_enqueue_scripts→wp_register_script(...)— tarde demais
Esse é um comportamento intencional no core do WordPress. O comentário no template-canvas.php diz explicitamente:
“This needs to run before
<head>so that blocks can add scripts and styles inwp_head().”
Por que o wp_add_inline_script especificamente quebra
Essa é a parte sutil. Nem tudo quebra — só o wp_add_inline_script.
wp_enqueue_script('handle') sem registro prévio ainda funciona. O WordPress adiciona o handle a uma fila e tem um mecanismo pra re-enqueue automaticamente um script enfileirado prematuramente assim que ele é registrado — resolve tudo depois na hora de imprimir os scripts.
wp_add_inline_script('handle', ...) é diferente. Ele acessa $wp_scripts->registered['handle'] imediatamente no momento da chamada. Se o handle ainda não está registrado, retorna false — silenciosamente. Sem erro, sem warning.
Ou seja: enqueue tolera um handle ainda não registrado. Inline script não. Essa é a armadilha inteira.
A Solução: registrar no init
Mova o wp_register_script pro hook init. Ele roda antes dos blocks renderizarem, então o handle já está pronto quando o shortcode precisar dele.
// ❌ Antes — registro no wp_enqueue_scripts (tarde demais pro FSE)
add_action( 'wp_enqueue_scripts', function() {
wp_register_script( 'my-handle', plugin_dir_url(__FILE__) . 'script.js', [], '1.0', true );
wp_localize_script( 'my-handle', 'myData', [ 'ajax_url' => admin_url('admin-ajax.php') ] );
});
// ✅ Depois — registro no init (antes da renderização dos blocks)
add_action( 'init', function() {
wp_register_script( 'my-handle', plugin_dir_url(__FILE__) . 'script.js', [], '1.0', true );
});
add_action( 'wp_enqueue_scripts', function() {
// wp_localize_script funciona aqui — handle já está registrado
wp_localize_script( 'my-handle', 'myData', [ 'ajax_url' => admin_url('admin-ajax.php') ] );
});
// Shortcode — sem mudanças necessárias
function my_shortcode() {
wp_add_inline_script( 'my-handle', 'const config = ' . wp_json_encode($data) . ';', 'before' );
wp_enqueue_script( 'my-handle' );
return '<div>...</div>';
}
O shortcode fica intocado. Só move o registro pra mais cedo. Isso funciona tanto pra temas clássicos quanto block themes — registrar no init é explicitamente documentado como válido na referência de desenvolvimento do WordPress.
O que NÃO funciona como alternativa
enqueue_block_assets: dispara dentro do wp_enqueue_scripts — mesmo problema de timing.
Condicional com wp_is_block_theme(): frágil, duplica código, quebra se o usuário trocar de tema. Te força a manter dois caminhos de código pra algo que tem uma solução limpa única.
Ordem de execução dos hooks (referência)
plugins_loaded
└─ init ← registre scripts aqui
└─ wp_loaded
└─ template_redirect
└─ [FSE] get_the_block_template_html() ← shortcodes rodam aqui
└─ wp_head()
└─ wp_enqueue_scripts ← localize/enqueue aqui
└─ [Classic] the_content / shortcodes ← temas clássicos rodam aqui
└─ wp_footer
└─ wp_print_footer_scripts
Regra Prática
Se seu plugin usa wp_add_inline_script() dentro de um shortcode: registre o script no init, localize no wp_enqueue_scripts, enqueue dentro do shortcode. Zero lógica condicional, funciona em qualquer lugar.
Eu esbarrei nisso trabalhando num plugin que usa shortcodes pra renderizar conteúdo dinâmico. Levei mais tempo do que gostaria de admitir pra descobrir que a solução era uma mudança de uma linha na prioridade do hook — não algo dentro do shortcode em si.
Referências
- WordPress Trac #54958 — “Inconsistent behaviour for wp_add_inline_script between block-based and standard themes”
- wp_add_inline_script() — Developer Reference
- wp_register_script() — Developer Reference
- template-canvas.php — WordPress Core (GitHub)
- Block Editor Handbook — Enqueueing Assets
- Theme Handbook — Including Assets
Deixe um comentário