Blocos Customizados no Gutenberg com ACF: Tutorial Completo
Blocos customizados no Gutenberg com ACF Pro permitem criar componentes visuais reutilizáveis onde o editor controla o conteúdo via campos registrados, e o desenvolvedor controla a marcação via render.php. É a combinação mais prática…
Blocos customizados no Gutenberg com ACF Pro permitem criar componentes visuais reutilizáveis onde o editor controla o conteúdo via campos registrados, e o desenvolvedor controla a marcação via render.php. É a combinação mais prática para agências que precisam de blocos flexíveis sem escrever JavaScript puro.
Depois de configurar mais de 300 sites em WordPress na Weboption, testamos praticamente todas as abordagens para blocos customizados: React puro, block.json nativo, Page Builders e ACF Blocks. Para a maioria dos projetos de agência, o ACF Pro ainda vence pela velocidade de entrega e pela autonomia que dá ao cliente no editor.
O que são ACF Blocks e por que usar em 2025
ACF Blocks são blocos Gutenberg cujos campos são definidos via Advanced Custom Fields Pro, e a renderização acontece num arquivo PHP. Não há necessidade de configurar um bundler, escrever JSX ou entender o ciclo de vida do React para criar um bloco funcional.
O ACF Pro custa a partir de R$ 600/ano para uso em sites ilimitados no plano Professional. Para uma agência que entrega 10 ou mais projetos por ano, o custo por projeto cai abaixo de R$ 60, o que é irrelevante diante do tempo economizado. A versão 6.x do plugin (atual no momento deste artigo) trouxe suporte completo ao block.json e ao modo de preview inline, o que eliminou os últimos motivos para evitar o ACF Blocks em produção.
Um dado importante: segundo a própria Advanced Custom Fields, mais de 2 milhões de sites usam o plugin ativamente. Parte significativa desse volume usa ACF Blocks exatamente pelo padrão que vamos descrever aqui.
Estrutura de arquivos e registro via acf-json
O registro correto de um bloco ACF começa no block.json e termina no acf-json. Misturar as duas abordagens sem entender o fluxo é o erro mais comum que vemos em projetos que chegam para manutenção aqui na Weboption.
A estrutura mínima de um bloco fica assim dentro do tema ou plugin:
blocks/
meu-bloco/
block.json
render.php
editor.css (opcional)
style.css (opcional)
acf-json/
group_meu_bloco.json
O block.json registra o bloco no WordPress e no ACF ao mesmo tempo. A chave acf dentro dele aponta para o grupo de campos:
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "weboption/meu-bloco",
"title": "Meu Bloco",
"category": "weboption",
"icon": "layout",
"description": "Bloco customizado com ACF.",
"supports": {
"anchor": true,
"align": ["wide", "full"]
},
"acf": {
"mode": "preview",
"renderTemplate": "render.php"
},
"editorStyle": "file:./editor.css",
"style": "file:./style.css"
}
O registro no PHP ocorre chamando acf_register_block_type() via hook acf/init, mas com o block.json na versão 6+ você pode usar register_block_type() diretamente e o ACF detecta a chave acf automaticamente. Isso é melhor porque aproveita o cache nativo do WordPress.
add_action('init', function() {
register_block_type( get_template_directory(). '/blocks/meu-bloco' );
});

O padrão render.php: PHP direto, sem gambiarra
O render.php é onde a marcação HTML do bloco vive. O ACF injeta automaticamente as variáveis $block, $content e $is_preview. Você acessa os campos com get_field() normalmente.
Um exemplo real de render.php para um bloco de depoimento:
<?php
$titulo = get_field('titulo');
$texto = get_field('texto');
$autor = get_field('autor');
$imagem = get_field('imagem');
$classes = ['bloco-depoimento'];
if (! empty( $block['className'] ) ) {
$classes[] = $block['className'];
}
if (! empty( $block['align'] ) ) {
$classes[] = 'align'. $block['align'];
}?>
<div class="<?php echo esc_attr( implode( ' ', $classes ) );?>">
<?php if ( $imagem ):?>
<img src="<?php echo esc_url( $imagem['url'] );?>" alt="<?php echo esc_attr( $imagem['alt'] );?>">
<?php endif;?>
<blockquote>
<p><?php echo wp_kses_post( $texto );?></p>
<cite><?php echo esc_html( $autor );?></cite>
</blockquote>
</div>
Três regras que seguimos em todo projeto: sempre escapar saídas com esc_attr, esc_url ou wp_kses_post; nunca colocar lógica de negócio complexa no render.php (mova para funções de tema); e tratar o caso em que o campo está vazio antes de renderizar.
Criando o grupo de campos no acf-json
O grupo de campos que alimenta o bloco precisa ter a regra de localização apontando para o bloco. No editor do ACF, em “Localização”, escolha “Bloco” e selecione seu bloco registrado.
O arquivo gerado no acf-json/ terá uma estrutura similar a esta (simplificada):
{
"key": "group_meu_bloco",
"title": "Campos: Meu Bloco",
"fields": [
{
"key": "field_titulo",
"label": "Título",
"name": "titulo",
"type": "text"
},
{
"key": "field_texto",
"label": "Texto",
"name": "texto",
"type": "textarea"
}
],
"location": [
[
{
"param": "block",
"operator": "==",
"value": "weboption/meu-bloco"
}
]
]
}
Salvar os grupos no acf-json é obrigatório em qualquer projeto sério. Isso garante que os campos ficam versionados no Git junto com o código, e a sincronização entre ambientes (local, staging, produção) é automática. Já resolvemos dezenas de incidentes de campos sumidos em produção simplesmente porque o cliente ou outro dev tinha editado o grupo direto no banco sem o acf-json ativo.
Modos de preview e experiência no editor
O ACF Blocks oferece três modos configuráveis no block.json: edit, preview e auto.
O modo edit mostra sempre o formulário de campos. O preview mostra o HTML renderizado pelo render.php no editor, e ao clicar o bloco entra em modo de edição. O auto alterna entre os dois automaticamente conforme o bloco está selecionado ou não.
Nossa recomendação depois de anos de uso: use preview para blocos visuais complexos (hero, cards, depoimentos) e edit para blocos simples onde o preview não agrega. O cliente entende melhor o que está editando quando vê o resultado em tempo real no editor.
A variável $is_preview disponível no render.php serve para adaptar o conteúdo quando necessário. Um uso comum é exibir um placeholder quando o bloco está vazio no preview:
<?php if ( $is_preview && empty( $titulo ) ):?>
<div class="bloco-placeholder">Adicione um título no painel lateral.</div>
<?php endif;?>
O erro que vemos com mais frequência
O erro mais comum em projetos que chegam para nós é o uso de save() com HTML estático em blocos ACF. Isso quebra o bloco quando o conteúdo muda, porque o WordPress valida o HTML salvo contra o retorno atual de save().
Blocos ACF com render.php devem sempre ter save retornando null no lado JavaScript (ou simplesmente não registrar um save quando usando o fluxo PHP). O ACF cuida disso automaticamente quando você usa o padrão correto de block.json com renderTemplate.
Outro problema frequente: registrar o grupo de campos com a chave de localização errada. Se o valor em “Bloco” não bate exatamente com o name no block.json (incluindo o namespace, como weboption/meu-bloco), os campos simplesmente não aparecem no editor. Sem mensagem de erro, sem aviso. Só o painel lateral vazio.
O terceiro erro clássico é não escapar saídas no render.php. Todo campo que vem do banco e vai para o HTML precisa de escape. Não é opcional, é segurança básica.
Perguntas frequentes
Preciso do ACF Pro para criar blocos customizados no Gutenberg?
Sim. Os ACF Blocks são um recurso exclusivo do ACF Pro. A versão gratuita do ACF não inclui suporte a blocos Gutenberg. O plano Professional custa a partir de R$ 600/ano e cobre sites ilimitados, o que é viável para qualquer agência.
Qual a diferença entre ACF Blocks e blocos nativos do WordPress?
Blocos nativos são escritos em JavaScript/React e têm controle total sobre a edição inline no Gutenberg. ACF Blocks delegam os campos para o ACF e a renderização para PHP, sem necessidade de JavaScript. Blocos nativos são mais flexíveis e performáticos a longo prazo; ACF Blocks são muito mais rápidos de criar e manter para equipes PHP.
O que é o acf-json e por que devo usá-lo?
O acf-json é uma pasta no tema ou plugin onde o ACF salva automaticamente os grupos de campos em formato JSON. Isso versiona os campos no Git e sincroniza configurações entre ambientes sem depender do banco de dados. É obrigatório em qualquer projeto profissional com ACF.
Posso usar ACF Blocks com temas de bloco (FSE)?
Sim. ACF Blocks funcionam tanto com temas clássicos quanto com temas de bloco (Full Site Editing). No FSE, os blocos aparecem normalmente na biblioteca do editor e podem ser usados em templates de bloco. A compatibilidade com FSE melhorou bastante a partir do ACF 6.0.
Como testar o render.php sem publicar a página?
Use o modo preview no block.json. O render.php é executado diretamente no editor Gutenberg, então você vê o resultado visual em tempo real enquanto preenche os campos no painel lateral, sem precisar publicar ou pré-visualizar a página em nova aba.
Guia completo: Gutenberg e Full Site Editing no WordPress: Guia Completo: leia o artigo principal para uma visão abrangente do tema.