Skip to content

Todo para WordPress, el desarrollo web — y mucho más

🔧 Cómo preparar un tema de WordPress para WooCommerce: guía completa para desarrolladores

🔧 Cómo preparar un tema de WordPress para WooCommerce: guía completa para desarrolladores

Construir su propio tema y quiere integrar una tienda? Técnicamente WooCommerce funciona con cualquier tema, ya que es solo un plugin. Pero «funciona» no significa «se ve bien»: la cuadrícula de productos se rompe, las barras laterales se desplazan y los estilos predeterminados chocan con los suyos.

El problema va más allá de unas pocas reglas CSS. A partir de WooCommerce 3.3, un tema sin soporte declarado recibe un renderizado simplificado mediante shortcodes y una advertencia en el panel de administración. Usted pierde el control total sobre la maquetación.

A continuación encontrará fragmentos listos para usar que cubren desde la declaración de soporte hasta un carrito dinámico en el menú. Cada uno ha sido probado en la versión actual de WooCommerce y está organizado por secciones, desde los fundamentos hasta los ajustes finos.

💡 Resumen rápido:

  • Primero, el tema debe declarar explícitamente el soporte para WooCommerce; sin esto, las sobrescrituras de plantillas y algunas funciones no se activarán
  • Coloque el código en un archivo separado (por ejemplo inc/woocommerce.php) que se cargue solo cuando el plugin esté activo
  • Configurar la cuadrícula de la tienda requiere dos filtros: uno cambia las columnas, el otro añade una clase al body
  • La galería de productos, el zoom, la caja de luz y el deslizador se habilitan mediante llamadas separadas a add_theme_support
  • El carrito en el menú debe actualizarse vía AJAX; utilice el filtro add_to_cart_fragments

1. Fundamentos: declarar el soporte y verificar si el plugin está activo

Ante todo, el tema debe decirle explícitamente a WooCommerce: «Le doy soporte». Sin esto, el plugin no activará las sobrescrituras de plantillas y mostrará una advertencia en el panel de administración. A partir de WooCommerce 3.3, un tema sin soporte declarado recibe un renderizado simplificado mediante shortcodes. Esto funciona, pero limita su control sobre la maquetación.

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce' );
3} );

Es importante usar el gancho after_setup_theme en lugar de init, como recomienda la documentación de WooCommerce. Desde la versión 3.3+, puede pasar la configuración de la cuadrícula directamente:

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce', array(
3 'thumbnail_image_width' => 150,
4 'single_image_width' => 300,
5 'product_grid' => array(
6 'default_rows' => 3,
7 'min_rows' => 2,
8 'max_rows' => 8,
9 'default_columns' => 4,
10 'min_columns' => 2,
11 'max_columns' => 5,
12 ),
13 ) );
14} );

Estos parámetros establecen valores predeterminados para el personalizador (WooCommerce → Imágenes de producto / Catálogo de productos) y evitan que los usuarios tengan que configurar la cuadrícula manualmente.

Verificar si el plugin está activo

Cuando distribuye un tema, no puede simplemente volcar fragmentos de WooCommerce al final de functions.php porque provocarán un error fatal si el plugin no está activo. El código debe cargarse solo cuando WooCommerce esté en ejecución:

1define( 'MYTHEME_WOOCOMMERCE_ACTIVE', class_exists( 'WooCommerce' ) );
2
3if ( MYTHEME_WOOCOMMERCE_ACTIVE ) {
4 require_once get_template_directory() . '/inc/woocommerce.php';
5}

La constante se evalúa una vez, y luego en cualquier parte de su tema puede envolver las llamadas en if ( MYTHEME_WOOCOMMERCE_ACTIVE ). Esto es más limpio que llamar a class_exists o is_plugin_active cada vez.

2. Gestionar los estilos de WooCommerce

WooCommerce incluye tres archivos CSS: woocommerce-general, woocommerce-layout y woocommerce-smallscreen. Lo ideal es no eliminarlos, sino sobrescribirlos en su tema. De ese modo, las extensiones de terceros para WooCommerce que dependen de estas clases no se rompen. Pero si está escribiendo todo desde cero y quiere un control total, aquí le mostramos cómo eliminarlos.

Eliminar todos los estilos a la vez:

1add_filter( 'woocommerce_enqueue_styles', '__return_empty_array' );

O eliminar selectivamente:

1function mytheme_remove_woo_styles( $styles ) {
2 unset( $styles['woocommerce-general'] );
3 unset( $styles['woocommerce-layout'] );
4 unset( $styles['woocommerce-smallscreen'] );
5 return $styles;
6}
7add_filter( 'woocommerce_enqueue_styles', 'mytheme_remove_woo_styles' );

En la práctica, la segunda opción es más común: usted elimina woocommerce-layout (la cuadrícula basada en porcentajes) pero conserva woocommerce-general (botones, avisos, formularios) y los sobrescribe selectivamente con su propio CSS usando una especificidad mayor.

3. Configurar las páginas de la tienda

Cuántos productos mostrar

El filtro loop_shop_per_page controla el número de productos en la página de la tienda y en los archivos (categorías, etiquetas):

1function mytheme_woo_posts_per_page( $cols ) {
2 return 12;
3}
4add_filter( 'loop_shop_per_page', 'mytheme_woo_posts_per_page' );

Número de columnas en la cuadrícula

Aquí se necesitan dos filtros. Usar solo loop_shop_columns no basta: a diferencia de los shortcodes de WooCommerce (que tienen un contenedor con una clase columns-N), las páginas de la tienda no tienen esa clase. Así que la añadimos al body:

1function mytheme_woo_shop_columns( $columns ) {
2 return 4;
3}
4add_filter( 'loop_shop_columns', 'mytheme_woo_shop_columns' );
5
6function mytheme_woo_shop_columns_body_class( $classes ) {
7 if ( is_shop() || is_product_category() || is_product_tag() ) {
8 $classes[] = 'columns-4';
9 }
10 return $classes;
11}
12add_filter( 'body_class', 'mytheme_woo_shop_columns_body_class' );

Ahora en CSS puede escribir selectores como .columns-4 ul.products li.product, y se aplicarán específicamente a la cuadrícula de la tienda.

Título de la tienda

WooCommerce muestra «Shop» como título en la página de la tienda por defecto. Si su tema ya gestiona los títulos de archivo, este duplicado estorba:

1add_filter( 'woocommerce_show_page_title', '__return_false' );

Si utiliza the_archive_title(), puede reemplazar el título con el nombre de la página de tienda (definido en el panel de administración):

1function mytheme_woo_archive_title( $title ) {
2 if ( is_shop() && $shop_id = wc_get_page_id( 'shop' ) ) {
3 $title = get_the_title( $shop_id );
4 }
5 return $title;
6}
7add_filter( 'get_the_archive_title', 'mytheme_woo_archive_title' );

4. Galería de producto: zoom, lightbox y slider

A partir de WooCommerce 3.0 se introdujo una nueva galería de producto basada en FlexSlider, PhotoSwipe y jQuery Zoom. En las versiones 3.0 a 3.2 está desactivada por defecto y requiere activación explícita. Desde la 3.3, la galería se activa para temas que no son de WooCommerce y se desactiva para temas que declaran soporte; usted habilita los componentes que necesita:

1add_theme_support( 'wc-product-gallery-slider' );
2add_theme_support( 'wc-product-gallery-zoom' );
3add_theme_support( 'wc-product-gallery-lightbox' );

Puede activar solo algunas funciones: por ejemplo, slider y zoom sí, pero reemplazar el lightbox con su propia solución Fancybox. Cada directiva carga sus propios scripts, así que no active lo que no necesite.

Número de columnas para las miniaturas de la galería (debajo de la imagen principal del producto):

1function mytheme_woo_product_thumbnails_columns() {
2 return 4;
3}
4add_action( 'woocommerce_product_thumbnails_columns', 'mytheme_woo_product_thumbnails_columns' );

5. Productos relacionados y ventas cruzadas/up-sells

En la página de producto, WooCommerce muestra los bloques de «Productos relacionados» y «También podría gustarle» (up-sells). Su cantidad y cuadrícula se configuran por separado.

Cuántos productos relacionados mostrar:

1function mytheme_woo_related_posts_per_page( $args ) {
2 $args['posts_per_page'] = 4;
3 return $args;
4}
5add_filter( 'woocommerce_output_related_products_args', 'mytheme_woo_related_posts_per_page' );

Columnas para los bloques de up-sells y relacionados (la misma historia que con la cuadrícula de la tienda): cambiamos tanto las columnas como la clase en el body:

1function mytheme_woo_single_loops_columns( $columns ) {
2 return 4;
3}
4add_filter( 'woocommerce_up_sells_columns', 'mytheme_woo_single_loops_columns' );
5
6function mytheme_woo_related_columns( $args ) {
7 $args['columns'] = 4;
8 return $args;
9}
10add_filter( 'woocommerce_output_related_products_args', 'mytheme_woo_related_columns', 10 );
11
12function mytheme_woo_single_loops_columns_body_class( $classes ) {
13 if ( is_singular( 'product' ) ) {
14 $classes[] = 'columns-4';
15 }
16 return $classes;
17}
18add_filter( 'body_class', 'mytheme_woo_single_loops_columns_body_class' );

Tenga en cuenta que woocommerce_output_related_products_args tiene dos filtros con prioridades diferentes: mytheme_woo_related_posts_per_page (prioridad 10) cambia posts_per_page, y mytheme_woo_related_columns (prioridad 10) cambia columns. No entran en conflicto porque trabajan con claves distintas dentro del mismo array $args.

6. Paginación e insignia de oferta

Puede reemplazar las flechas de la paginación con los iconos de su tema:

1function mytheme_woo_pagination_args( $args ) {
2 $args['prev_text'] = '<i class="fa fa-angle-left"></i>';
3 $args['next_text'] = '<i class="fa fa-angle-right"></i>';
4 return $args;
5}
6add_filter( 'woocommerce_pagination_args', 'mytheme_woo_pagination_args' );

Reemplace las clases de Font Awesome por sus propias clases de iconos o SVGs directos.

El texto de la insignia de oferta (Sale!) es fácil de sobrescribir. Esto es útil para sitios en otros idiomas o simplemente para eliminar el signo de exclamación:

1function mytheme_woo_sale_flash() {
2 return '<span class="onsale">' . esc_html__( 'Sale', 'woocommerce' ) . '</span>';
3}
4add_filter( 'woocommerce_sale_flash', 'mytheme_woo_sale_flash' );

Para otros idiomas, reemplace 'Sale' por su traducción. La traducción se tomará automáticamente si usted tiene los archivos MO de WooCommerce para ese idioma.

7. Carrito dinámico en el menú

Este es probablemente el elemento más solicitado en cualquier tema de tienda: un icono de carrito en la navegación con el total actual. La implementación consta de tres partes: añadir el elemento al menú, generar el HTML del carrito y la actualización por AJAX.

1// Adding the link to the menu
2function mytheme_add_menu_cart_item( $items, $args ) {
3 if ( $args->theme_location === 'primary' ) {
4 $css_class = 'menu-item menu-item-type-cart menu-item-type-woocommerce-cart';
5 if ( is_cart() ) {
6 $css_class .= ' current-menu-item';
7 }
8 $items .= '<li class="' . esc_attr( $css_class ) . '">';
9 $items .= mytheme_menu_cart_item();
10 $items .= '</li>';
11 }
12 return $items;
13}
14add_filter( 'wp_nav_menu_items', 'mytheme_add_menu_cart_item', 10, 2 );
15
16// Cart HTML
17function mytheme_menu_cart_item() {
18 $cart_count = WC()->cart->cart_contents_count;
19 $css_class = 'wpex-menu-cart-total wpex-cart-total-' . intval( $cart_count );
20 $url = $cart_count ? WC()->cart->get_cart_url() : wc_get_page_permalink( 'shop' );
21 $html = WC()->cart->get_cart_total();
22 $html = str_replace( 'amount', '', $html );
23
24 return '<a href="' . esc_url( $url ) . '" class="' . esc_attr( $css_class ) . '">'
25 . '<span class="cart-icon"></span>'
26 . wp_kses_post( $html )
27 . '</a>';
28}
29
30// AJAX fragment update
31function mytheme_menu_cart_link_fragments( $fragments ) {
32 $fragments['.wpex-menu-cart-total'] = mytheme_menu_cart_item();
33 return $fragments;
34}
35add_filter( 'add_to_cart_fragments', 'mytheme_menu_cart_link_fragments' );

Punto crítico: **no envuelva estas funciones en **is_admin(). Las peticiones AJAX del carrito llegan a través de admin-ajax.php, y si la función no está disponible en el contexto de administración, la actualización del precio en el menú simplemente no funcionará. Reemplace theme_location con el identificador de su menú (primary en el ejemplo).

8. Enfoque alternativo: la plantilla woocommerce.php

Los hooks descritos arriba son el método más flexible y seguro frente a actualizaciones. Pero si usted necesita reformar radicalmente todo el envoltorio de la tienda y la página de producto, existe un camino mediante una plantilla separada.

Cree un archivo woocommerce.php en la raíz de su tema (una copia de page.php) y reemplace el bucle principal con una llamada a woocommerce_content():

1<?php
2get_header(); ?>
3
4<div id="primary" class="content-area">
5 <main id="main" class="site-main">
6 <?php woocommerce_content(); ?>
7 </main>
8</div>
9
10<?php get_footer();
11

Este método es más simple, pero tiene un costo: una sola plantilla para todas las páginas de WooCommerce (la tienda, las categorías y el detalle del producto). El ajuste fino (diferentes cuadrículas, diferentes barras laterales en distintas páginas) se vuelve más difícil. Elija este enfoque solo si su tema actual realmente no se lleva bien con WooCommerce a nivel de marcado y usted está preparado para aceptar las limitaciones.

⁉️🤔 Preguntas frecuentes

¿Es obligatorio eliminar los estilos predeterminados de WooCommerce?

No es obligatorio. Un enfoque más seguro es conservarlos y sobrescribir los selectores en su tema con mayor especificidad. Esto preserva la compatibilidad con extensiones que dependen de las clases estándar de WooCommerce. La eliminación completa (__return_empty_array) solo se justifica si está construyendo un tema para tienda desde cero y sabe con certeza que ningún plugin de terceros añadirá elementos estilizados para WooCommerce. En la mayoría de los casos, basta con desactivar selectivamente woocommerce-layout (la cuadrícula porcentual entra en conflicto con flexbox y grids en temas modernos) manteniendo woocommerce-general y woocommerce-smallscreen y sobrescribiéndolos cuidadosamente mediante la cascada CSS. Esto le da una cuadrícula limpia sin perder compatibilidad.

¿Por qué no funciona el cambio de columnas en la tienda?

Porque el filtro loop_shop_columns por sí solo no es suficiente. WooCommerce usa clases .columns-N en el contenedor para que la cuadrícula funcione, y estas se añaden automáticamente solo a los shortcodes ([products columns="4"]). En las páginas de tienda y archivos, este contenedor no existe, por lo que necesita añadir la clase al body mediante body_class. Los dos filtros de la sección 3 resuelven este problema por completo.

El filtro loop_shop_columns cambia la variable PHP que WooCommerce pasa a la plantilla, pero la cuadrícula CSS depende de la clase del contenedor. Sin la clase columns-4 en body, sus estilos ul.products li.product no tienen un selector de contexto y o no se aplican o afectan a todas las listas de productos del sitio.

¿Necesito reconstruir el tema después de una actualización de WooCommerce?

Si está usando hooks (todos los fragmentos de este artículo), no. Los hooks cambian muy raramente. Si está sobrescribiendo plantillas (archivos de woocommerce/templates/), sí, necesita comparar sus copias con las versiones actuales después de cada actualización mayor. Esta es exactamente la razón por la que la documentación oficial recomienda los hooks como el método de personalización preferido.

Los hooks son un contrato. WooCommerce garantiza su estabilidad entre versiones. Las plantillas son una implementación que puede cambiar en cualquier momento: se añaden nuevas acciones, el marcado cambia, las clases se renombran. En los cinco años que estos hooks han existido (loop_shop_columns y woocommerce_output_related_products_args), su firma nunca ha cambiado, mientras que el archivo content-product.php se ha actualizado docenas de veces durante el mismo período.

¿Puedo usar is_admin() para proteger las funciones del carrito?

No, y esta es una trampa común. Las peticiones AJAX de WooCommerce (añadir al carrito, actualizar cantidad) se procesan a través de admin-ajax.php; en este contexto, is_admin() devuelve true. Si envuelve las funciones del carrito en if ( ! is_admin() ), las actualizaciones de fragmentos AJAX (add_to_cart_fragments) dejarán de funcionar y el total en el icono del carrito no cambiará sin recargar la página.

Envolver en ! is_admin() solo debe usarse para cosas que no deben ejecutarse en el administrador (salida HTML del front-end), pero las funciones manejadoras de AJAX deben estar siempre disponibles. Para el código de la sección 7, no use is_admin() en absoluto. El propio WooCommerce llama a los callbacks necesarios a través de su manejador AJAX, y la restricción romperá la lógica.

¿Cómo añado soporte de WooCommerce a un tema de bloques (FSE)?

Para temas de bloques, la declaración de soporte no ha cambiado: el mismo add_theme_support('woocommerce'). Pero en lugar de hooks y sobrescritura de plantillas PHP, trabaja en el Editor del Sitio: WooCommerce proporciona bloques (Productos, Búsqueda de productos, Carrito, Finalizar compra) que inserta en las plantillas mediante Appearance → Editor. Los ajustes finos se realizan a través de theme.json y variables CSS.

Los temas de bloques cambian fundamentalmente el enfoque: no escribe hooks PHP para la maquetación, sino que ensambla visualmente las páginas a partir de bloques de WooCommerce listos para usar. Pero la base (add_theme_support en functions.php) sigue siendo la misma. Para ajustes finos que no se pueden hacer con bloques (por ejemplo, texto personalizado en el botón «Añadir al carrito»), los buenos filtros de siempre de este artículo también funcionan en temas FSE.

Qué estrategia elegir para su proyecto

Si está mejorando un tema existente, comience con los pasos 1 y 2: declare el soporte y configure la cuadrícula. En la mayoría de los casos, esto es suficiente para que la tienda tenga un aspecto decente. Luego añada solo las correcciones que resuelvan problemas específicos: una galería rota, una paginación antiestética, la falta del carrito en el menú.

Si está escribiendo un tema desde cero para venta o distribución, recorra la lista completa. Cada elemento añade algo que los usuarios esperan de un tema para tienda «listo para usar»: una cuadrícula personalizable, zoom en los productos, un icono de carrito en vivo. Coloque el código en inc/woocommerce.php y cárguelo basándose en la constante. De esta manera, el tema funciona igual de bien tanto como blog como tienda.

El punto de partida es siempre el mismo:

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce' );
3} );

Ocho líneas. Todo lo demás son detalles que distinguen un tema «compatible» de uno «creado específicamente para ello».