Jump to Navigation Jump to Main Content Jump to Footer
Home » Docs » Features » Woocommerce support

Woocommerce support

Chisel provides first‑class WooCommerce integration via custom Twig templates, helper utilities, and selective hook overrides.

Overview

  • Theme supportwoocommerce, product gallery zoom/lightbox/slider enabled. Source: core/WP/Woocommerce.php::add_woocommerce_support()
  • Custom templates:
    • Archive: views/woocommerce/archive-product.twig
    • Single: views/woocommerce/single-product.twig
    • Loop item: views/woocommerce/content-product.twig
    • Category item: views/woocommerce/content-product-cat.twig
    • Linked products (upsells/related): views/woocommerce/linked-products.twig
    • Entry point: woocommerce.php
  • Twig hooks preserved: Templates call Woo hooks (e.g., woocommerce_before_main_contentwoocommerce_single_product_summary) via do_action(...), but the theme removes some default outputs to replace layout/markup.
  • Sidebar: Dedicated “WooCommerce” sidebar registered via filter. Source: core/WP/Woocommerce.php::register_sidebars()

Hook customizations

  • Removed default actions (theme reimplements layout/markup):
    • Wrapper and breadcrumb around main content. Removed: woocommerce_output_content_wrapperwoocommerce_output_content_wrapper_endwoocommerce_breadcrumb
    • Loop product/category link wrappers and default thumbnails. Removed: woocommerce_template_loop_product_link_open/closewoocommerce_subcategory_thumbnailwoocommerce_template_loop_product_thumbnail
    • Archive pagination (theme may use its Load More). Removed: woocommerce_pagination
    • Single product upsells/related default placement (theme renders via Twig). Removed: woocommerce_upsell_displaywoocommerce_output_related_products. Source: core/WP/Woocommerce.php::remove_actions()
  • Sort bar container: Injected before/after shop loop to wrap count/order controls. Source: core/WP/Woocommerce.php::before_shop_loop_div_open() / before_shop_loop_div_close(). Triggered by Woo hook: woocommerce_before_shop_loop
  • Customizer: Removes “both” display choice for shop/category archives. Source: core/WP/Woocommerce.php::modify_customizer()

Assets

  • Removes Woo’s woocommerce-layout stylesheet to avoid conflicts. Filter: woocommerce_enqueue_styles in core/WP/Woocommerce.php::enqueue_styles()
  • Registers theme style handle woocommerce via chisel_frontend_styles. Source: core/WP/Woocommerce.php::register_custom_styles()

Custom Timber classes

Chisel provides extended Timber classes specifically for WooCommerce products and product categories, offering enhanced thumbnail handling with automatic placeholder fallback support.

ChiselProduct

Located in core/Timber/ChiselProduct.php, this class extends Timber\Post and provides WooCommerce-specific functionality for products.

Properties:

  • $thumbnail_html (string|null) – Cached product thumbnail HTML
  • $thumbnail_id (int|null) – Cached thumbnail attachment ID

Methods:

get_thumbnail( string $size = 'woocommerce_thumbnail', array $attrs = array() ): string

Returns the product thumbnail as responsive image HTML. Applies the single_product_archive_thumbnail_size filter to allow customization of the thumbnail size. If no thumbnail is set, automatically falls back to the WooCommerce placeholder image configured in WooCommerce → Settings → Products → Placeholder image.

Parameters:

  • $size – Thumbnail size (default: 'woocommerce_thumbnail')
  • $attrs – Image attributes array passed to ImageHelpers::get_responsive_image()

Returns: Responsive <img> HTML, or empty string if no thumbnail or placeholder exists

get_thumbnail_id(): int

Returns the product thumbnail attachment ID. Falls back to the WooCommerce placeholder image option (woocommerce_placeholder_image) if no product thumbnail is set.

Returns: Thumbnail attachment ID (int)

Usage in templates:

{% for product in products %}
    <div class="c-product">
        {{ product.get_thumbnail('woocommerce_thumbnail') }}
        <h3>{{ product.title }}</h3>
        <span class="c-product__price">{{ product.price }}</span>
    </div>
{% endfor %}
Twig

ChiselProductCategory

Located in core/Timber/ChiselProductCategory.php, this class extends Timber\Term for WooCommerce product category taxonomy.

Properties:

  • $thumbnail_html (string|null) – Cached category thumbnail HTML
  • $thumbnail_id (int|null) – Cached thumbnail attachment ID

Methods:

get_thumbnail( string $size = 'woocommerce_thumbnail', array $attrs = array() ): string

Returns the category thumbnail as responsive image HTML. Applies the subcategory_archive_thumbnail_size filter. Falls back to WooCommerce placeholder image if no category thumbnail is set.

Parameters:

  • $size – Thumbnail size (default: 'woocommerce_thumbnail')
  • $attrs – Image attributes array

Returns: Responsive <img> HTML, or empty string

get_thumbnail_id(): int

Returns the category thumbnail attachment ID from term meta (thumbnail_id). Falls back to the WooCommerce placeholder image option if no category thumbnail is set.

Returns: Thumbnail attachment ID (int)

Usage in templates:

{% for category in categories %}
    <div class="c-category">
        {{ category.get_thumbnail('woocommerce_thumbnail') }}
        <h3>{{ category.name }}</h3>
    </div>
{% endfor %}
Twig

Helpers

WoocommerceHelpers (core/Helpers/WoocommerceHelpers.php)

is_woocommerce_active()

is_woocommerce_active(): bool

Checks if the WooCommerce plugin is active. Use this to guard WooCommerce-specific code paths.

Returns: true if WooCommerce class exists, false otherwise

Usage:

<?php
use Chisel\Helpers\WoocommerceHelpers;

if ( WoocommerceHelpers::is_woocommerce_active() ) {
    // WooCommerce-specific code
}
PHP

timber_set_product()

timber_set_product( object $post ): void

Sets the global $product object for WooCommerce products. This is essential for product loops where WooCommerce templates and functions expect the global $product to be correctly set. The method checks if the post type is 'product' and uses wc_get_product() to set the global product object.

Parameters:

  • $post – Timber Post object

Usage:

<?php
use Chisel\Helpers\WoocommerceHelpers;

foreach ( $posts as $post ) {
    if ( $post->post_type === 'product' ) {
        WoocommerceHelpers::timber_set_product( $post );
    }
}
PHP

Exposed to Twig as: timber_set_product(post)

This method is automatically used internally by Chisel when rendering product templates, ensuring that $product is always available in the correct context.

get_products_grid_classnames()

get_products_grid_classnames( bool $products, bool $has_sidebar ): string

Generates responsive grid CSS classnames for WooCommerce product layouts based on the number of columns configured in WooCommerce settings. Returns ITCSS object-layer grid classes (o-grid) with responsive modifiers.

Parameters:

  • $products – Whether there are products to render
  • $has_sidebar – Whether the layout includes a sidebar

Returns: String of CSS classnames for the grid container

Behavior:

  • Reads the WooCommerce loop columns setting via wc_get_loop_prop('columns')
  • Limits maximum columns to 4 for optimal layout
  • Generates responsive grid classes:
    • Base: o-grid o-grid--cols-1 (mobile/default)
    • Small breakpoint: o-grid--cols-{n}-small where n is columns or columns-1
    • Medium breakpoint: Adjusts based on sidebar presence (uses small column count if sidebar exists, otherwise uses full column count)

Example output:

  • Without sidebar, 3 columns: o-grid o-grid--cols-1 o-grid--cols-2-small o-grid--cols-3-medium
  • With sidebar, 3 columns: o-grid o-grid--cols-1 o-grid--cols-2-small o-grid--cols-2-medium

Usage in Twig:

<div class="{{ fn('Chisel\\Helpers\\WoocommerceHelpers::get_products_grid_classnames', products|length > 0, has_sidebar) }}">
    {% for product in products %}
        <div class="o-grid__item">
            {% include 'components/product-card.twig' with { product: product } %}
        </div>
    {% endfor %}
</div>
Twig

Example usage in PHP (archive context):

woocommerce.php computes and passes:

  • items (posts or terms), categoriesshow_products
  • loop_columns_class via WoocommerceHelpers::get_products_grid_classnames($products, $has_sidebar)
  • load_more config for AJAX pagination: { per_page, post_type: 'product' }

Templates: data flow and extension

Archive

views/woocommerce/archive-product.twig

  • Uses Woo hooks (woocommerce_before_main_contentwoocommerce_before_shop_loop, etc.)
  • Renders either content-product.twig or content-product-cat.twig based on show_products
  • Appends Load More control when products present:
    • Includes components/pagination.twig with { type: 'load-more' }
    • Front‑end JS module src/scripts/modules/load-more.js uses REST endpoint load-more
  • Grid classes injected via loop_columns_class

Single

views/woocommerce/single-product.twig

  • Uses standard Woo hooks for gallery/summary/tabs
  • Theme renders custom linked products sections via linked-products.twig using:
    • Context vars from woocommerce.phpupsells_productsrelated_products
  • post_classes(post.class) and wrapper_class used for consistent BEM classes

Entry logic

woocommerce.php

Single product:

  • Sets postproduct
  • Controls upsells/related via filters:
    • chisel_woocommerce_upsell_display (bool)
    • chisel_woocommerce_output_related_products (bool)
  • Computes grid_classnames and renders single-product.twig

Archive:

  • Honors Woo “display type” (products vs subcategories)
  • Builds items (posts or terms), categoriesshow_products
  • Computes loop_columns_class, and load_more per page via wc_get_loop_prop('columns') * wc_get_default_product_rows_per_page()
  • Renders archive-product.twig

Theme filters for Woo behavior

Toggle upsells/related on single (in woocommerce.php):

  • chisel_woocommerce_upsell_display → default true
  • chisel_woocommerce_output_related_products → default true

Example:

<?php
add_filter( 'chisel_woocommerce_output_related_products', '__return_false' );
add_filter( 'chisel_woocommerce_upsell_display', '__return_false' );
PHP

AJAX “Load more” for products

Archive integrates with the theme’s REST AJAX pattern:

  • Client: src/scripts/modules/load-more.js calls Utils.ajaxRequest('load-more', { post_type: 'product', ... })
  • Server: core/WP/Ajax/LoadMoreEndpoints.php::load_more() prepends Woo template views/woocommerce/content-product.twig for post_type === 'product'

Sidebars

  • Add a “WooCommerce” sidebar via filter chisel_sidebars (merged in inc/Plugin/Woocommerce.php).Twig includes sidebar-woocommerce.twig or sidebar-woocommerce-product.twig when sidebar is present in the context.

How to extend

  • Override markup: Copy any views/woocommerce/*.twig file into a child theme with the same path/name to customize.
  • Grid/tile layout: Adjust columns via Woo settings; helper caps at 4 columns. For custom breakpoints, adapt WoocommerceHelpers::get_products_grid_classnames().
  • Disable/enable pieces via filters listed above.
  • Register extra CSS/JS for shop pages via asset filters.

Do you like Chisel?

Give it a star on GitHub!