Classic WooCommerce Single Product
Use this when building or reviewing single product pages in a classic WooCommerce theme: product gallery, summary order, add-to-cart forms, variable products, tabs, upsells, related products, reviews, and structured data.
When to Use This Skill
- Editing
woocommerce/single-product.php.
- Editing
woocommerce/content-single-product.php.
- Moving title, price, rating, excerpt, add-to-cart, meta, or sharing.
- Customizing product gallery layout.
- Customizing variable product forms or add-to-cart UI.
- Changing tabs, upsells, related products, or reviews.
Single Product Skeleton
Keep the top-level single-product.php simple.
get_header( 'shop' );
do_action( 'woocommerce_before_main_content' );
while ( have_posts() ) {
the_post();
wc_get_template_part( 'content', 'single-product' );
}
do_action( 'woocommerce_after_main_content' );
do_action( 'woocommerce_sidebar' );
get_footer( 'shop' );
Rules:
- Preserve
get_header( 'shop' ) and get_footer( 'shop' ) unless the theme has a deliberate header/footer strategy.
- Preserve wrapper hooks.
- Do not manually query products inside
single-product.php.
- Do not remove
woocommerce_sidebar without replacing sidebar behavior intentionally.
Content Single Product Contract
content-single-product.php handles notices, password protection, product classes, gallery, summary, tabs, upsells, related products, and after-product hooks.
Must preserve:
do_action( 'woocommerce_before_single_product' ) for notices.
post_password_required() guard.
<div id="product-<?php the_ID(); ?>" <?php wc_product_class( '', $product ); ?>>.
woocommerce_before_single_product_summary.
woocommerce_single_product_summary.
woocommerce_after_single_product_summary.
woocommerce_after_single_product.
Rules:
- Do not remove
WC_Structured_Data::generate_product_data() by deleting the summary hook.
- Preserve
wc_product_class() for schema/state/CSS classes.
- Use hooks to reorder summary items instead of overriding the template.
Summary Hook Map
Default woocommerce_single_product_summary callbacks:
- title at 5.
- rating at 10.
- price at 10.
- excerpt at 20.
- add-to-cart at 30.
- meta at 40.
- sharing at 50.
- structured data at 60.
Example: move price below excerpt.
add_action( 'after_setup_theme', 'mytheme_single_summary_order' );
function mytheme_single_summary_order() {
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 25 );
}
Rules:
- Use exact callbacks/priorities from
wc-template-hooks.php.
- Do not echo raw
_price, _stock, or _sku meta.
- Use
WC_Product methods and Woo template functions.
Product Gallery
Default gallery output:
woocommerce_before_single_product_summary -> sale flash at 10.
woocommerce_before_single_product_summary -> woocommerce_show_product_images at 20.
woocommerce_product_thumbnails -> thumbnails at 20.
Rules:
- Prefer CSS and gallery support flags before overriding
single-product/product-image.php.
- Keep
wc_get_gallery_image_html() behavior when overriding gallery markup.
- Preserve placeholder behavior for products without images.
- Test variable products, because variation image switching depends on gallery structure.
- Do not remove focusable/lightbox controls without replacement.
Add-to-Cart Forms
Woo routes add-to-cart by product type:
woocommerce_simple_add_to_cart.
woocommerce_grouped_add_to_cart.
woocommerce_variable_add_to_cart.
woocommerce_external_add_to_cart.
Rules:
- Do not replace all product types with one custom form.
- Preserve quantity inputs, hidden variation/product fields, form action, method, and enctype.
- Keep nonce/validation behavior from Woo forms.
- For product-type-specific layout, hook around the relevant add-to-cart action or override the smallest add-to-cart template.
Variable Products
The Woo 10.x single-product/add-to-cart/variable.php template includes:
- JSON-encoded variations in
data-product_variations.
wc_dropdown_variation_attribute_options().
- labels for each attribute select.
- reset link with
aria-label.
.reset_variations_alert.screen-reader-text live region.
woocommerce_single_variation hooks.
Rules:
- Avoid overriding
variable.php unless absolutely necessary.
- Preserve
data-product_id and data-product_variations.
- Preserve labels and reset/live-region accessibility.
- Do not load all variation objects manually in the theme.
- Test in-stock, out-of-stock, backorder, and unavailable variation states.
Tabs, Upsells, Related Products
Default hooks:
woocommerce_after_single_product_summary -> tabs at 10.
- upsells at 15.
- related products at 20.
Examples:
add_filter( 'woocommerce_output_related_products_args', 'mytheme_related_products_args' );
function mytheme_related_products_args( $args ) {
$args['posts_per_page'] = 3;
$args['columns'] = 3;
return $args;
}
Rules:
- Use
woocommerce_product_tabs to rename, remove, or reorder tabs.
- Use
woocommerce_output_related_products_args for related product count/columns.
- Keep reviews accessible if reviews are enabled.
- Do not hide product attributes that customers need for purchase decisions.
Reviews and Comments
Product reviews use the comments system when reviews are enabled.
Rules:
- Do not globally disable comments template behavior for products unless the store does not use reviews.
- Preserve rating display and review text hooks in custom review templates.
- Use accessible labels and validation on review forms.
Review Checklist
single-product.php keeps Woo wrapper and sidebar hooks.
content-single-product.php keeps notices and password protection.
- Product wrapper uses
wc_product_class().
- Summary changes use hooks when possible.
- Structured data hook remains reachable.
- Gallery overrides preserve variation image behavior.
- Add-to-cart forms remain product-type-specific.
- Variable product form keeps labels, data attributes, reset link, and live region.
- Tabs/related/upsells use filters/hooks before template copies.
- Product data comes from
WC_Product methods, not raw postmeta.
Common Mistakes
- Removing
woocommerce_before_single_product and losing notices.
- Rebuilding the variable product form from scratch.
- Moving add-to-cart outside the product form contract.
- Deleting structured-data callbacks while reordering summary output.
- Breaking variation image switching with gallery markup changes.
- Hardcoding a simple product purchase flow for all product types.
References
1---2name: classic-woocommerce-single-product3description: Build or audit WooCommerce single product templates in a classic PHP theme. Covers `single-product.php`, `content-single-product.php`, `woocommerce_before_single_product`, product gallery hooks, `woocommerce_single_product_summary`, add-to-cart templates for simple/variable/grouped/external products, variation form accessibility, tabs, upsells, related products, structured data hook preservation, `WC_Product` CRUD methods, image gallery support, reviews/comments, and avoiding fragile overrides of `product-image.php` and `variable.php`.4---56# Classic WooCommerce Single Product78Use this when building or reviewing single product pages in a classic WooCommerce theme: product gallery, summary order, add-to-cart forms, variable products, tabs, upsells, related products, reviews, and structured data.910## When to Use This Skill1112- Editing `woocommerce/single-product.php`.13- Editing `woocommerce/content-single-product.php`.14- Moving title, price, rating, excerpt, add-to-cart, meta, or sharing.15- Customizing product gallery layout.16- Customizing variable product forms or add-to-cart UI.17- Changing tabs, upsells, related products, or reviews.1819## Single Product Skeleton2021Keep the top-level `single-product.php` simple.2223```php24get_header( 'shop' );2526do_action( 'woocommerce_before_main_content' );2728while ( have_posts() ) {29 the_post();30 wc_get_template_part( 'content', 'single-product' );31}3233do_action( 'woocommerce_after_main_content' );34do_action( 'woocommerce_sidebar' );3536get_footer( 'shop' );37```3839Rules:4041- Preserve `get_header( 'shop' )` and `get_footer( 'shop' )` unless the theme has a deliberate header/footer strategy.42- Preserve wrapper hooks.43- Do not manually query products inside `single-product.php`.44- Do not remove `woocommerce_sidebar` without replacing sidebar behavior intentionally.4546## Content Single Product Contract4748`content-single-product.php` handles notices, password protection, product classes, gallery, summary, tabs, upsells, related products, and after-product hooks.4950Must preserve:5152- `do_action( 'woocommerce_before_single_product' )` for notices.53- `post_password_required()` guard.54- `<div id="product-<?php the_ID(); ?>" <?php wc_product_class( '', $product ); ?>>`.55- `woocommerce_before_single_product_summary`.56- `woocommerce_single_product_summary`.57- `woocommerce_after_single_product_summary`.58- `woocommerce_after_single_product`.5960Rules:6162- Do not remove `WC_Structured_Data::generate_product_data()` by deleting the summary hook.63- Preserve `wc_product_class()` for schema/state/CSS classes.64- Use hooks to reorder summary items instead of overriding the template.6566## Summary Hook Map6768Default `woocommerce_single_product_summary` callbacks:6970- title at 5.71- rating at 10.72- price at 10.73- excerpt at 20.74- add-to-cart at 30.75- meta at 40.76- sharing at 50.77- structured data at 60.7879Example: move price below excerpt.8081```php82add_action( 'after_setup_theme', 'mytheme_single_summary_order' );8384function mytheme_single_summary_order() {85 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );86 add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 25 );87}88```8990Rules:9192- Use exact callbacks/priorities from `wc-template-hooks.php`.93- Do not echo raw `_price`, `_stock`, or `_sku` meta.94- Use `WC_Product` methods and Woo template functions.9596## Product Gallery9798Default gallery output:99100- `woocommerce_before_single_product_summary` -> sale flash at 10.101- `woocommerce_before_single_product_summary` -> `woocommerce_show_product_images` at 20.102- `woocommerce_product_thumbnails` -> thumbnails at 20.103104Rules:105106- Prefer CSS and gallery support flags before overriding `single-product/product-image.php`.107- Keep `wc_get_gallery_image_html()` behavior when overriding gallery markup.108- Preserve placeholder behavior for products without images.109- Test variable products, because variation image switching depends on gallery structure.110- Do not remove focusable/lightbox controls without replacement.111112## Add-to-Cart Forms113114Woo routes add-to-cart by product type:115116- `woocommerce_simple_add_to_cart`.117- `woocommerce_grouped_add_to_cart`.118- `woocommerce_variable_add_to_cart`.119- `woocommerce_external_add_to_cart`.120121Rules:122123- Do not replace all product types with one custom form.124- Preserve quantity inputs, hidden variation/product fields, form action, method, and enctype.125- Keep nonce/validation behavior from Woo forms.126- For product-type-specific layout, hook around the relevant add-to-cart action or override the smallest add-to-cart template.127128## Variable Products129130The Woo 10.x `single-product/add-to-cart/variable.php` template includes:131132- JSON-encoded variations in `data-product_variations`.133- `wc_dropdown_variation_attribute_options()`.134- labels for each attribute select.135- reset link with `aria-label`.136- `.reset_variations_alert.screen-reader-text` live region.137- `woocommerce_single_variation` hooks.138139Rules:140141- Avoid overriding `variable.php` unless absolutely necessary.142- Preserve `data-product_id` and `data-product_variations`.143- Preserve labels and reset/live-region accessibility.144- Do not load all variation objects manually in the theme.145- Test in-stock, out-of-stock, backorder, and unavailable variation states.146147## Tabs, Upsells, Related Products148149Default hooks:150151- `woocommerce_after_single_product_summary` -> tabs at 10.152- upsells at 15.153- related products at 20.154155Examples:156157```php158add_filter( 'woocommerce_output_related_products_args', 'mytheme_related_products_args' );159160function mytheme_related_products_args( $args ) {161 $args['posts_per_page'] = 3;162 $args['columns'] = 3;163164 return $args;165}166```167168Rules:169170- Use `woocommerce_product_tabs` to rename, remove, or reorder tabs.171- Use `woocommerce_output_related_products_args` for related product count/columns.172- Keep reviews accessible if reviews are enabled.173- Do not hide product attributes that customers need for purchase decisions.174175## Reviews and Comments176177Product reviews use the comments system when reviews are enabled.178179Rules:180181- Do not globally disable comments template behavior for products unless the store does not use reviews.182- Preserve rating display and review text hooks in custom review templates.183- Use accessible labels and validation on review forms.184185## Review Checklist186187- `single-product.php` keeps Woo wrapper and sidebar hooks.188- `content-single-product.php` keeps notices and password protection.189- Product wrapper uses `wc_product_class()`.190- Summary changes use hooks when possible.191- Structured data hook remains reachable.192- Gallery overrides preserve variation image behavior.193- Add-to-cart forms remain product-type-specific.194- Variable product form keeps labels, data attributes, reset link, and live region.195- Tabs/related/upsells use filters/hooks before template copies.196- Product data comes from `WC_Product` methods, not raw postmeta.197198## Common Mistakes199200- Removing `woocommerce_before_single_product` and losing notices.201- Rebuilding the variable product form from scratch.202- Moving add-to-cart outside the product form contract.203- Deleting structured-data callbacks while reordering summary output.204- Breaking variation image switching with gallery markup changes.205- Hardcoding a simple product purchase flow for all product types.206207## References208209- Official documentation: <https://developer.woocommerce.com/docs/theming/theme-development/template-structure/>210- Official documentation: <https://developer.woocommerce.com/docs/theming/theme-development/image-sizes/>211- Official documentation: <https://developer.woocommerce.com/docs/theming/theme-development/theme-design-ux-guidelines/>212- Verified source paths:213 - `wp-content/plugins/woocommerce/templates/single-product.php`214 - `wp-content/plugins/woocommerce/templates/content-single-product.php`215 - `wp-content/plugins/woocommerce/templates/single-product/product-image.php`216 - `wp-content/plugins/woocommerce/templates/single-product/add-to-cart/variable.php`217 - `wp-content/plugins/woocommerce/includes/wc-template-hooks.php`218 - `wp-content/plugins/woocommerce/includes/wc-template-functions.php`219 - `wp-content/plugins/woocommerce/includes/wc-product-functions.php`