Um campo adicionado ao checkout não está resolvido só por aparecer no ecrã. Para ser útil, tem de responder a uma necessidade concreta, ser validado no servidor, ser guardado associado ao pedido e chegar às pessoas ou aos processos que dele precisam. Cada etapa pode falhar de forma independente.
A implementação também depende do fluxo de checkout ativo. Os hooks do checkout clássico não adicionam, por si só, campos ao Checkout Block. Antes de programar, identifica qual é usado pela loja e planeia o percurso completo dos dados.
Decidir se o dado pertence ao checkout

Identifica que tarefa requer o dado e quando este tem de estar disponível. Se for indispensável para calcular o pedido, determinar a sua elegibilidade ou preparar a entrega, pode ser necessário pedi-lo antes de confirmar a compra. Se apenas facilitar uma gestão posterior, considera recolhê-lo mais tarde para não criar atrito desnecessário.
Documenta a finalidade, quem utiliza o campo, se é obrigatório e durante quanto tempo deve ser conservado. Verifica se o WooCommerce já tem um campo padrão para essa informação: duplicar um endereço ou um número de telefone sem definir qual prevalece cria discrepâncias. Para dados sensíveis ou de grande impacto, limita a recolha e o acesso e verifica as obrigações de privacidade aplicáveis.
Identificar o fluxo e adicionar o campo
Verifica na página de finalização da compra se é usado o shortcode clássico [woocommerce_checkout] ou o Checkout Block. Analisa também os templates e as extensões que modificam essa página. Não basta reconhecer o design: uma extensão pode alterar o fluxo ou o processamento. Implementa e testa o mecanismo correspondente e não pressuponhas que um campo criado para um fluxo funcionará no outro.
Checkout clássico: hooks de campos e pedidos
O checkout clássico permite modificar os campos com woocommerce_checkout_fields, validar com woocommerce_after_checkout_validation e guardar durante a criação do pedido com woocommerce_checkout_create_order. Este exemplo regista um campo opcional, rejeita entradas que não sejam escalares e limita o texto a 120 caracteres Unicode:
add_filter('woocommerce_checkout_fields', function ($fields) {
$fields['order']['delivery_instructions'] = [
'type' => 'text',
'label' => 'Instruções de entrega',
'required' => false,
'priority' => 25,
'maxlength' => 120,
'class' => ['form-row-wide'],
];
return $fields;
});
add_action('woocommerce_after_checkout_validation', function ($data, $errors) {
$raw = $data['delivery_instructions'] ?? '';
if (! is_scalar($raw)) {
$errors->add('delivery_instructions', 'O valor tem de ser texto.');
return;
}
$value = trim(sanitize_text_field((string) $raw));
if (preg_match_all('/./us', $value, $matches) === false) {
$errors->add('delivery_instructions', 'O texto não tem um formato válido.');
return;
}
if (count($matches[0]) > 120) {
$errors->add('delivery_instructions', 'O texto não pode exceder 120 caracteres.');
}
}, 10, 2);
add_action('woocommerce_checkout_create_order', function ($order, $data) {
$raw = $data['delivery_instructions'] ?? '';
if (! is_scalar($raw)) {
return;
}
$value = trim(sanitize_text_field((string) $raw));
if ($value !== '') {
$order->update_meta_data('_delivery_instructions', $value);
}
}, 10, 2);O atributo maxlength impõe uma restrição no navegador; não substitui a validação no servidor. O exemplo conta pontos de código Unicode com uma expressão compatível com UTF-8; alguns caracteres, como determinados emojis, ocupam mais de uma unidade UTF-16 no navegador. Se tiverem de ser aceites, define e testa expressamente a regra de comprimento para que a experiência do cliente e o servidor não divirjam.
O exemplo guarda apenas um valor válido e não vazio. Se o campo passar a ser obrigatório, valida também a sua ausência e devolve um erro antes de criar o pedido. Usa um nome interno estável e não o alteres sem planear a migração dos dados existentes.
Checkout Block: API de campos adicionais
Para o Checkout Block, usa a API de campos adicionais do WooCommerce em vez de injetar HTML no formulário. Regista o campo a partir de um plugin ou tema compatível, por exemplo, durante woocommerce_init:
add_action('woocommerce_init', function () {
if (! function_exists('woocommerce_register_additional_checkout_field')) {
return;
}
woocommerce_register_additional_checkout_field([
'id' => 'mi-plugin/delivery-instructions',
'label' => 'Instruções de entrega',
'location' => 'order',
'type' => 'text',
'required' => false,
]);
});A API integra o campo no fluxo de blocos e no respetivo armazenamento associado ao pedido. Se precisares de regras específicas, consulta as opções de sanitização e validação suportadas pela API na instalação concreta e testa o erro de ponta a ponta. Não guardes o mesmo valor em paralelo com outro mecanismo sem decidir qual é a fonte de verdade.
Antes de colocar em produção, verifica se a função de registo existe e consulta a documentação correspondente à versão instalada. Se não estiver disponível, não simules compatibilidade com JavaScript: atualiza ou escolhe uma alternativa compatível com o checkout utilizado e testa num ambiente de staging.
Validar, normalizar e persistir no servidor
A validação no navegador melhora a experiência, mas não é um controlo de segurança. Verifica no servidor a presença quando o campo for obrigatório, o tipo, o comprimento, o formato e a correspondência com as opções permitidas. Para listas fechadas, valida identificadores conhecidos, não texto arbitrário enviado pelo cliente. Se o dado for opcional, define se a ausência e o valor vazio significam o mesmo. Perante um valor inválido, apresenta um erro compreensível e não confirmes o pedido omitindo silenciosamente um dado necessário.
No fluxo clássico, $order->update_meta_data() usa a API CRUD do pedido e evita escrever diretamente nas tabelas ou depender de uma estrutura de armazenamento específica. No Checkout Block, deixa que a API de campos adicionais trate da associação do campo e consulta o valor através da API de pedidos ou do mecanismo documentado para essa integração; não pressuponhas uma chave interna de metadados.
Para verificar a compatibilidade, consulta as definições do WooCommerce e confirma se está ativo o armazenamento de pedidos de alto desempenho (HPOS) ou o armazenamento baseado nas tabelas de publicações. Num ambiente de testes com a mesma configuração, cria um pedido para cada fluxo, lê-o como objeto WC_Order através de wc_get_order($order_id) e verifica o dado com a API CRUD, por exemplo, $order->get_meta('_delivery_instructions') para o campo clássico. Atualiza o pedido e volta a lê-lo; não uses consultas SQL diretas às tabelas internas. Repete as verificações depois de alterar o armazenamento ou atualizar extensões que intervêm no checkout.
Consultar o dado no backoffice
O percurso de verificação operacional consiste em criar um pedido de teste, abrir WooCommerce > Pedidos, entrar na respetiva edição e comparar o valor apresentado com o enviado. Para o checkout clássico, se o metadado não aparecer no ecrã utilizado pela equipa, pode ser apresentada informação administrativa com o seguinte hook de dados do pedido:
add_action('woocommerce_admin_order_data_after_billing_address', function ($order) {
$value = $order->get_meta('_delivery_instructions');
if ($value !== '') {
echo '<p><strong>Instruções de entrega:</strong> '
. esc_html($value) . '</p>';
}
});Este hook e o metadado do exemplo correspondem ao checkout clássico; verifica a sua apresentação no ecrã administrativo ativo na loja. Com HPOS e no ecrã de edição de pedidos baseado em blocos, verifica o resultado real: não pressuponhas que uma extensão do painel clássico abrange automaticamente a nova interface. Usa sempre o objeto do pedido e a API CRUD para ler ou editar dados.
Os campos registados pela API do Checkout Block podem ser integrados nos detalhes do pedido. Confirma-o em WooCommerce > Pedidos com um pedido de teste. Se precisares que outro código consulte o valor, identifica na documentação da API a localização e o mecanismo de leitura para a versão instalada; não adivinhes a chave de metadados. Se não for apresentado, adiciona uma apresentação administrativa compatível com esse ecrã e testa tanto com o armazenamento configurado como com as extensões de administração instaladas.
Se for necessária edição, define os perfis autorizados e guarda as alterações através da API CRUD do pedido. Não apresentes o dado automaticamente em emails, documentos, exportações ou ecrãs públicos: inclui cada destino apenas se existir uma necessidade operacional, limita o acesso e escapa sempre a saída.
Testar o ciclo completo e evitar regressões
Um teste que apenas verifica se o campo é apresentado é insuficiente. Verifica o percurso desde o formulário até à utilização posterior e cobre, no mínimo:
- Pedido válido com dado preenchido: validar, guardar no pedido correto e consultar no backoffice.
- Campo opcional vazio e campo obrigatório ausente: verificar o comportamento definido para cada caso.
- Entrada manipulada, não escalar, demasiado longa ou fora das opções permitidas: confirmar a rejeição no servidor.
- Texto com acentos e caracteres multibyte, incluindo o limite exato; verifica também a interação com
maxlength. - Atualização do pedido: verificar o que muda, quem pode alterá-lo e como a alteração se propaga.
- Checkout clássico e Checkout Block: testar o fluxo ativo e qualquer alteração de modalidade prevista.
- Permissões e exposição: verificar que só os utilizadores e processos autorizados recebem o valor.
Inclui testes de regressão dos totais, das validações e da criação do pedido. Se uma automatização consumir o campo, testa também o que acontece quando o seu envio falha ou não ocorre. Um sinal de diagnóstico claro é o dado aparecer no navegador, mas não no pedido nem no processo que o deveria utilizar.
Lista de verificação antes da colocação em produção

- A finalidade do dado e o momento da recolha estão documentados.
- O mecanismo corresponde ao checkout ativo: hooks do fluxo clássico ou API de campos adicionais para o Block.
- O servidor valida o tipo, o formato e o comprimento; entradas não escalares são rejeitadas e a ausência, o valor vazio e o valor inválido têm um tratamento definido.
- A instalação e o armazenamento de pedidos foram identificados; a leitura e a atualização são testadas com a API CRUD.
- Um pedido de teste confirma a leitura no ecrã de backoffice utilizado e o acesso está limitado.
- Os testes abrangem caracteres Unicode, atualizações, erros, integrações e regressões do checkout.



