WooCommerce Hooks e Filtros: Customização Sem Modificar o Core
WooCommerce hooks e filtros são o mecanismo correto para personalizar qualquer comportamento da loja sem tocar no core do plugin. Depois de configurar mais de 300 lojas WooCommerce aqui na Weboption, aprendemos que a…

WooCommerce hooks e filtros são o mecanismo correto para personalizar qualquer comportamento da loja sem tocar no core do plugin. Depois de configurar mais de 300 lojas WooCommerce aqui na Weboption, aprendemos que a diferença entre uma loja que sobrevive às atualizações e uma que quebra toda vez está quase sempre na disciplina de usar hooks em vez de editar arquivos do plugin diretamente.
Este guia cobre os hooks mais úteis do WooCommerce na prática, com código real que você pode aplicar hoje.
O que são hooks no WooCommerce e por que eles importam
Hooks são pontos de extensão que o WooCommerce expõe para que você adicione ou modifique comportamentos sem alterar o código fonte. Existem dois tipos: add_action para executar código em um momento específico, e add_filter para modificar um valor antes de ele ser usado.
A documentação oficial do WooCommerce lista mais de 1.800 hooks disponíveis na versão 8.x. Na prática, uns 30 deles resolvem 90% dos casos de customização que vemos em projetos reais. O restante fica ali para situações muito específicas.
Todo código de hook vai no arquivo functions.php do seu child theme, nunca diretamente no tema pai ou em arquivos do WooCommerce. Isso garante que suas modificações sobrevivam a qualquer atualização do plugin ou do tema.
Customizando campos do checkout com woocommerce_checkout_fields
O filtro woocommerce_checkout_fields é provavelmente o mais solicitado em projetos de lojas virtuais. Ele permite adicionar, remover, reordenar e modificar qualquer campo do checkout sem criar um plugin separado.
Para remover o campo de empresa do billing, por exemplo:
add_filter( 'woocommerce_checkout_fields', function( $fields ) {
unset( $fields['billing']['billing_company'] );
return $fields;
} );Para adicionar um campo personalizado de CPF:
add_filter( 'woocommerce_checkout_fields', function( $fields ) {
$fields['billing']['billing_cpf'] = array(
'label' => 'CPF',
'placeholder' => '000.000.000-00',
'required' => true,
'class' => array( 'form-row-wide' ),
'priority' => 25,
);
return $fields;
} );O campo priority controla a ordem de exibição. Valores menores aparecem primeiro. Por padrão, o WooCommerce usa incrementos de 10, então usar 25 coloca o campo entre o 20 e o 30.
Um erro que vemos com frequência: adicionar o campo no checkout mas esquecer de salvar o valor no pedido. O campo aparece, o cliente preenche, mas o dado some. Para salvar corretamente, você precisa de mais dois hooks:
add_action( 'woocommerce_checkout_update_order_meta', function( $order_id ) {
if (! empty( $_POST['billing_cpf'] ) ) {
update_post_meta( $order_id, '_billing_cpf', sanitize_text_field( $_POST['billing_cpf'] ) );
}
} );
add_action( 'woocommerce_admin_order_data_after_billing_address', function( $order ) {
$cpf = get_post_meta( $order->get_id(), '_billing_cpf', true );
if ( $cpf ) {
echo 'CPF: '. esc_html( $cpf ). '
';
}
} );
Modificando preços no carrinho com woocommerce_cart_item_price
O filtro woocommerce_cart_item_price controla como o preço de cada item é exibido no carrinho. Isso é diferente de alterar o preço real do produto. Para alterar o preço real, você usa woocommerce_product_get_price ou woocommerce_cart_item_subtotal.
Um caso real que implementamos para um cliente atacadista: mostrar o preço por unidade e o preço por caixa lado a lado no carrinho:
add_filter( 'woocommerce_cart_item_price', function( $price_html, $cart_item, $cart_item_key ) {
$product = $cart_item['data'];
$unidade_caixa = get_post_meta( $product->get_id(), '_unidades_por_caixa', true );
if ( $unidade_caixa && $unidade_caixa > 1 ) {
$preco_caixa = $product->get_price() * $unidade_caixa;
$price_html.= ' (R$ '. number_format( $preco_caixa, 2, ',', '.' ). '/cx)';
}
return $price_html;
}, 10, 3 );Note que o filtro recebe três argumentos: o HTML do preço, os dados do item no carrinho e a chave do item. Quando seu callback usa mais de um argumento, você precisa declarar o número correto no quarto parâmetro do add_filter, que aqui é o 3. Esquecer isso é uma fonte clássica de bugs silenciosos.
Reagindo a mudanças de status com woocommerce_order_status_changed
A action woocommerce_order_status_changed dispara toda vez que um pedido muda de status. É aqui que você conecta integrações externas: ERPs, sistemas de logística, notificações por WhatsApp, relatórios internos.
A assinatura do hook é: $order_id, $old_status, $new_status, $order.
add_action( 'woocommerce_order_status_changed', function( $order_id, $old_status, $new_status, $order ) {
if ( $new_status === 'processing' ) {
// Notificar ERP
wp_remote_post( 'https://seu-erp.com.br/api/pedidos', array(
'body' => json_encode( array(
'pedido_id' => $order_id,
'total' => $order->get_total(),
'cliente' => $order->get_billing_email(),
) ),
'headers' => array( 'Content-Type' => 'application/json' ),
) );
}
}, 10, 4 );Para integrações críticas, recomendamos usar wp_schedule_single_event em vez de fazer a chamada HTTP diretamente no hook. Isso evita que um timeout da API externa deixe o cliente esperando na tela de confirmação do pedido. Vimos isso acontecer em lojas com integração ao sistema TOTVS: a chamada travava por 30 segundos e o cliente achava que o pagamento havia falhado.
Adicionando meta dados personalizados a pedidos
Salvar informações extras no pedido é algo que praticamente todo projeto WooCommerce exige. Seja o número de NF, o código de rastreamento, o vendedor responsável ou qualquer dado específico do negócio.
O padrão correto usa a API de objetos do WooCommerce a partir da versão 3.0, não update_post_meta diretamente:
// Salvar meta dado
$order = wc_get_order( $order_id );
$order->update_meta_data( '_codigo_rastreamento', 'BR123456789BR' );
$order->save();
// Recuperar meta dado
$order = wc_get_order( $order_id );
$codigo = $order->get_meta( '_codigo_rastreamento' );
A partir do WooCommerce 8.0, pedidos podem ser armazenados em tabelas próprias (HPOS, High-Performance Order Storage) em vez de wp_posts. Usar update_post_meta diretamente quebra lojas com HPOS ativado. Já encontramos isso em pelo menos 15 migrações de clientes que vieram com código legado.
Para exibir o meta dado no painel administrativo do pedido:
add_action( 'woocommerce_admin_order_data_after_order_details', function( $order ) {
$codigo = $order->get_meta( '_codigo_rastreamento' );
if ( $codigo ) {
echo '';
echo '';
echo ''. esc_html( $codigo ). '';
echo '
';
}
} );Padrões no functions.php do child theme
Organizar hooks no functions.php do child theme parece simples, mas projetos que crescem sem estrutura viram um arquivo de 2.000 linhas impossível de manter. O padrão que adotamos na Weboption depois de anos refatorando código de terceiros é separar por contexto em arquivos incluídos:
// functions.php do child theme
require_once get_stylesheet_directory(). '/inc/wc-checkout.php';
require_once get_stylesheet_directory(). '/inc/wc-cart.php';
require_once get_stylesheet_directory(). '/inc/wc-orders.php';
require_once get_stylesheet_directory(). '/inc/wc-emails.php';
Cada arquivo cuida de uma área. O functions.php fica com menos de 50 linhas e continua fácil de ler.
Outro padrão importante: sempre verificar se o WooCommerce está ativo antes de usar funções do plugin:
add_action( 'plugins_loaded', function() {
if (! class_exists( 'WooCommerce' ) ) {
return;
}
// Seus hooks aqui
} );Isso previne erros fatais quando o WooCommerce é desativado temporariamente para manutenção.
O erro mais comum que vemos em projetos WooCommerce
O erro número um, sem dúvida, é editar arquivos dentro da pasta /wp-content/plugins/woocommerce/. Parece rápido. Resolve o problema na hora. E destrói tudo na próxima atualização do plugin.
Já recuperamos projetos onde o desenvolvedor anterior modificou diretamente woocommerce/templates/checkout/form-checkout.php. Quando o cliente atualizou o WooCommerce de 7.x para 8.x, o checkout parou de funcionar completamente. A loja ficou fora do ar por quase 4 horas num sábado.
A alternativa correta para templates é copiar o arquivo para /wp-content/themes/seu-child-theme/woocommerce/checkout/form-checkout.php. O WooCommerce carrega o template do tema se ele existir, e esse arquivo não é sobrescrito em atualizações do plugin. Para modificações de comportamento, use sempre hooks.
Uma pesquisa da WP Engine com 1.000 desenvolvedores WordPress em 2023 mostrou que 67% dos problemas de compatibilidade após atualizações de plugins vinham de modificações diretas em arquivos do plugin. O número é alto, mas faz sentido para quem acompanha projetos no dia a dia.
Perguntas frequentes
Qual a diferença entre add_action e add_filter no WooCommerce?
add_action executa uma função em um momento específico do ciclo de vida da página ou do pedido, sem necessariamente retornar um valor. add_filter intercepta um valor, permite que você o modifique e exige que você retorne o valor alterado. No WooCommerce, use actions para disparar eventos (enviar e-mail, salvar dados) e filters para alterar o que é exibido ou calculado.
Onde devo colocar meus hooks WooCommerce?
Sempre no functions.php do child theme ou em arquivos PHP incluídos por ele. Nunca edite arquivos dentro da pasta do plugin WooCommerce. Se o volume de customizações for grande, considere criar um plugin filho (mu-plugin) para manter o código separado do tema.
Como descobrir quais hooks estão disponíveis para um comportamento específico?
A documentação oficial em woocommerce.com/document/hooks/ lista os principais hooks com exemplos. Para encontrar hooks em contextos específicos, instale o plugin Query Monitor e ative a exibição de hooks: ele mostra todos os hooks disparados em cada requisição. O código fonte do WooCommerce no GitHub também é referência confiável.
Meu hook não está funcionando. O que verificar primeiro?
Verifique o nome do hook (um caractere errado e ele nunca dispara), a prioridade (se outro código roda depois e sobrescreve sua modificação), e o número de argumentos aceitos no callback versus o que você declarou no add_filter. Para filters, confirme que você está retornando o valor modificado, não apenas modificando uma variável local.
Hooks WooCommerce funcionam com o HPOS (High-Performance Order Storage)?
Sim, desde que você use a API de objetos do WooCommerce (wc_get_order, $order->get_meta(), $order->update_meta_data()) em vez de funções diretas de post meta como get_post_meta e update_post_meta. O HPOS armazena pedidos em tabelas próprias e ignora chamadas diretas à tabela wp_postmeta.
Guia completo: WooCommerce Avançado: Guia Para Lojas de Alta Performance: leia o artigo principal para uma visão abrangente do tema.