Saltar al contenido
DedicatedPHP Contactar

Campos personalizados en el checkout de WooCommerce: de la compra al backoffice

Aprende a añadir campos al checkout clásico o al Checkout Block, validar la entrada en el servidor y comprobar que el dato llega al pedido y al backoffice.

Campo personalizado del checkout de WooCommerce guardado en un pedido y consultado desde el backoffice

Un campo añadido al checkout no está resuelto solo porque aparezca en pantalla. Para que sea útil, debe responder a una necesidad concreta, validarse en el servidor, guardarse asociado al pedido y llegar a las personas o procesos que lo necesitan. Cada paso puede fallar por separado.

La implementación depende también del flujo de checkout activo. Los hooks del checkout clásico no añaden por sí mismos campos al Checkout Block. Antes de programar, identifica cuál usa la tienda y diseña el recorrido completo del dato.

Decidir si el dato pertenece al checkout

Decidir si el dato pertenece al checkout — guía visual de DedicatedPHP

Identifica qué tarea requiere el dato y cuándo debe estar disponible. Si es imprescindible para calcular el pedido, determinar su elegibilidad o preparar la entrega, puede ser necesario pedirlo antes de confirmar la compra. Si solo facilita una gestión posterior, valora recogerlo después para no añadir fricción innecesaria.

Documenta la finalidad, quién consume el campo, si es obligatorio y cuánto tiempo debe conservarse. Comprueba si WooCommerce ya dispone de un campo estándar para esa información: duplicar una dirección o un teléfono sin definir cuál prevalece crea discrepancias. Para datos sensibles o de alto impacto, limita la recogida y el acceso, y revisa las obligaciones de privacidad aplicables.

Identificar el flujo y añadir el campo

Comprueba en la página de finalizar compra si se usa el shortcode clásico [woocommerce_checkout] o el Checkout Block. Revisa también las plantillas y extensiones que modifican esa página. No basta con reconocer el diseño: una extensión puede alterar el flujo o el procesamiento. Implementa y prueba el mecanismo correspondiente, y no des por hecho que un campo creado para un flujo funcionará en el otro.

Checkout clásico: hooks de campos y pedido

El checkout clásico permite modificar los campos con woocommerce_checkout_fields, validar con woocommerce_after_checkout_validation y guardar durante la creación del pedido con woocommerce_checkout_create_order. Este ejemplo registra un campo opcional, rechaza entradas no escalares y limita el texto a 120 caracteres Unicode:

add_filter('woocommerce_checkout_fields', function ($fields) {
    $fields['order']['delivery_instructions'] = [
        'type'      => 'text',
        'label'     => 'Instrucciones 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', 'El valor debe ser texto.');
        return;
    }

    $value = trim(sanitize_text_field((string) $raw));
    if (preg_match_all('/./us', $value, $matches) === false) {
        $errors->add('delivery_instructions', 'El texto no tiene un formato válido.');
        return;
    }
    if (count($matches[0]) > 120) {
        $errors->add('delivery_instructions', 'El texto no puede superar 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);

El atributo maxlength proporciona una restricción en el navegador, no sustituye la validación del servidor. El ejemplo cuenta puntos de código Unicode con una expresión compatible con UTF-8; algunos caracteres, como ciertos emoji, ocupan más de una unidad UTF-16 en el navegador. Si deben admitirse, define y prueba expresamente la regla de longitud para que la experiencia del cliente y el servidor no discrepen.

El ejemplo guarda solo un valor válido y no vacío. Si el campo pasa a ser obligatorio, valida también su ausencia y devuelve un error antes de crear el pedido. Usa un nombre interno estable y no lo cambies sin planificar la migración de datos existentes.

Checkout Block: API de campos adicionales

Para el Checkout Block, utiliza la API de campos adicionales de WooCommerce en lugar de inyectar HTML en el formulario. Registra el campo desde un plugin o tema compatible, por ejemplo 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'    => 'Instrucciones de entrega',
        'location' => 'order',
        'type'     => 'text',
        'required' => false,
    ]);
});

La API integra el campo con el flujo de bloques y su almacenamiento asociado al pedido. Si necesitas reglas específicas, consulta las opciones de saneamiento y validación admitidas por la API en la instalación concreta y prueba el error de extremo a extremo. No guardes el mismo valor en paralelo con otro mecanismo sin decidir cuál es la fuente de verdad.

Antes de desplegar, comprueba que la función de registro existe y consulta la documentación correspondiente a la versión instalada. Si no está disponible, no simules compatibilidad con JavaScript: actualiza o elige una alternativa compatible con el checkout usado, y prueba en un entorno de staging.

Validar, normalizar y persistir en el servidor

La validación del navegador mejora la experiencia, pero no es un control de seguridad. Comprueba en el servidor la presencia cuando sea obligatoria, el tipo, la longitud, el formato y la pertenencia a opciones permitidas. Para listas cerradas, valida identificadores conocidos, no texto arbitrario enviado por el cliente. Si el dato es opcional, define si ausente y vacío significan lo mismo. Ante un valor inválido, muestra un error comprensible y no confirmes el pedido omitiendo silenciosamente un dato necesario.

En el flujo clásico, $order->update_meta_data() usa la API CRUD del pedido y evita escribir directamente en tablas o depender de una estructura de almacenamiento específica. En el Checkout Block, deja que la API de campos adicionales gestione la asociación del campo y consulta el valor mediante la API de pedido o el mecanismo documentado para esa integración; no presupongas una clave interna de metadatos.

Para verificar compatibilidad, revisa en los ajustes de WooCommerce si está activo el almacenamiento de pedidos de alto rendimiento (HPOS) o el almacenamiento basado en las tablas de publicaciones. En un entorno de pruebas con la misma configuración, crea un pedido por cada flujo, léelo como objeto WC_Order mediante wc_get_order($order_id) y comprueba el dato con la API CRUD, por ejemplo $order->get_meta('_delivery_instructions') para el campo clásico. Actualiza el pedido y vuelve a leerlo; no uses consultas SQL directas a tablas internas. Repite las comprobaciones tras cambiar el almacenamiento o actualizar extensiones que intervienen en el checkout.

Consultar el dato en el backoffice

La ruta de verificación operativa es crear un pedido de prueba, abrir WooCommerce > Pedidos, entrar en su edición y comparar el valor presentado con el enviado. Para el checkout clásico, si el metadato no aparece en la pantalla que utiliza el equipo, puede añadirse una presentación administrativa con el hook de datos de pedido siguiente:

add_action('woocommerce_admin_order_data_after_billing_address', function ($order) {
    $value = $order->get_meta('_delivery_instructions');
    if ($value !== '') {
        echo '<p><strong>Instrucciones de entrega:</strong> '
            . esc_html($value) . '</p>';
    }
});

Este hook y el metadato del ejemplo corresponden al checkout clásico; verifica su presentación en la pantalla administrativa habilitada en la tienda. En HPOS y en la pantalla de edición de pedidos basada en bloques, comprueba el resultado real: no asumas que una extensión del panel clásico cubre automáticamente la nueva interfaz. Usa siempre el objeto de pedido y la API CRUD para leer o editar datos.

Los campos registrados por la API del Checkout Block pueden integrarse en los detalles del pedido. Compruébalo en WooCommerce > Pedidos con un pedido de prueba. Si necesitas que otro código consulte el valor, identifica en la documentación de la API la ubicación y el mecanismo de lectura para la versión instalada; no adivines la clave de metadatos. Si no se muestra, añade una presentación administrativa compatible con esa pantalla y prueba tanto con el almacenamiento configurado como con las extensiones de administración instaladas.

Si se requiere edición, define roles autorizados y guarda los cambios mediante la API CRUD del pedido. No muestres el dato automáticamente en correos, documentos, exportaciones o pantallas públicas: incorpora cada destino solo si existe una necesidad operativa, limita el acceso y escapa siempre la salida.

Probar el ciclo completo y evitar regresiones

Una prueba que solo verifica que el campo se renderiza es insuficiente. Comprueba el recorrido desde el formulario hasta el uso posterior y cubre, como mínimo:

  • Pedido válido con dato informado: validar, guardar en el pedido correcto y consultar en el backoffice.
  • Campo opcional vacío y campo obligatorio ausente: verificar el comportamiento definido para cada caso.
  • Entrada manipulada, no escalar, demasiado larga o fuera de las opciones permitidas: confirmar rechazo en el servidor.
  • Texto con acentos y caracteres multibyte, incluido el límite exacto; comprueba también la interacción con maxlength.
  • Actualización del pedido: comprobar qué cambia, quién puede cambiarlo y cómo se propaga.
  • Checkout clásico y Checkout Block: probar el flujo activo y cualquier cambio de modalidad previsto.
  • Permisos y exposición: verificar que solo usuarios y procesos autorizados reciben el valor.

Incluye pruebas de regresión de totales, validaciones y creación del pedido. Si una automatización consume el campo, prueba también qué ocurre cuando falta o falla su envío. Una señal de diagnóstico clara es que el dato aparezca en el navegador, pero no en el pedido o en el proceso que debía utilizarlo.

Lista de comprobación antes del despliegue

Lista de comprobación antes del despliegue — guía visual de DedicatedPHP
  • La finalidad del dato y el momento de recogida están documentados.
  • El mecanismo corresponde al checkout activo: hooks del flujo clásico o API de campos adicionales para el Block.
  • El servidor valida tipo, formato y longitud; las entradas no escalares se rechazan y ausente, vacío e inválido tienen un tratamiento definido.
  • La instalación y el almacenamiento de pedidos se han identificado; lectura y actualización se prueban con la API CRUD.
  • Un pedido de prueba confirma la lectura en la pantalla de backoffice utilizada y el acceso está limitado.
  • Las pruebas cubren caracteres Unicode, actualizaciones, errores, integraciones y regresiones del checkout.
¿Quieres aplicar estas ideas a tu proyecto?Hablemos de tu plataforma PHP.
Ver servicio relacionado