Commit 65ffae934d0 for woocommerce
commit 65ffae934d02cc4806aa6fecd728f8998d117780
Author: Rafael Minuesa <rafael.minuesa@gmail.com>
Date: Fri Apr 3 00:16:25 2026 +0200
Fix structured data adding valueAddedTaxIncluded when taxes are disabled (#63304)
* Fix structured data adding valueAddedTaxIncluded when taxes are disabled (#63266)
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix PHPCS alignment warnings in structured data order markup
The if block for wc_tax_enabled() breaks the assignment alignment
group, requiring the subsequent assignments to be re-aligned.
Refs woocommerce/woocommerce#63266
* Update PHPStan baseline for conditional valueAddedTaxIncluded
The valueAddedTaxIncluded key is now conditionally added to the
priceSpecification array, making it optional in the type signature.
Refs woocommerce/woocommerce#63266
* Fix PHPStan baseline key order for conditional valueAddedTaxIncluded
Since valueAddedTaxIncluded is now added after the array is built,
it appears after validThrough in PHPStan's type signature.
Refs woocommerce/woocommerce#63266
* Re-trigger CI (transient 429 in Blocks e2e)
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
diff --git a/plugins/woocommerce/changelog/fix-63266-structured-data-tax b/plugins/woocommerce/changelog/fix-63266-structured-data-tax
new file mode 100644
index 00000000000..c4f82c806df
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-63266-structured-data-tax
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Only add valueAddedTaxIncluded to structured data when taxes are enabled (#63266)
diff --git a/plugins/woocommerce/includes/class-wc-structured-data.php b/plugins/woocommerce/includes/class-wc-structured-data.php
index b5f79e4d1e4..316504715b0 100644
--- a/plugins/woocommerce/includes/class-wc-structured-data.php
+++ b/plugins/woocommerce/includes/class-wc-structured-data.php
@@ -240,17 +240,18 @@ class WC_Structured_Data {
$variation_prices = $product->get_variation_prices( true );
if ( $lowest === $highest ) {
+ $unit_price_spec = array(
+ '@type' => 'UnitPriceSpecification',
+ 'price' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
+ 'priceCurrency' => $currency,
+ 'validThrough' => $price_valid_until,
+ );
+ if ( wc_tax_enabled() ) {
+ $unit_price_spec['valueAddedTaxIncluded'] = 'incl' === get_option( 'woocommerce_tax_display_shop' );
+ }
$markup_offer = array(
'@type' => 'Offer',
- 'priceSpecification' => array(
- array(
- '@type' => 'UnitPriceSpecification',
- 'price' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
- 'priceCurrency' => $currency,
- 'valueAddedTaxIncluded' => 'incl' === get_option( 'woocommerce_tax_display_shop' ),
- 'validThrough' => $price_valid_until,
- ),
- ),
+ 'priceSpecification' => array( $unit_price_spec ),
);
} else {
$markup_offer = array(
@@ -274,16 +275,17 @@ class WC_Structured_Data {
? gmdate( 'Y-m-d', $date_on_sale_to->getTimestamp() )
: null;
- $markup_offer['priceSpecification'] = array(
- array(
- '@type' => 'UnitPriceSpecification',
- 'priceType' => 'https://schema.org/SalePrice',
- 'price' => wc_format_decimal( $lowest_child_sale_price, wc_get_price_decimals() ),
- 'priceCurrency' => $currency,
- 'valueAddedTaxIncluded' => 'incl' === get_option( 'woocommerce_tax_display_shop' ),
- 'validThrough' => $sale_price_valid_until ?? $price_valid_until,
- ),
+ $sale_unit_price_spec = array(
+ '@type' => 'UnitPriceSpecification',
+ 'priceType' => 'https://schema.org/SalePrice',
+ 'price' => wc_format_decimal( $lowest_child_sale_price, wc_get_price_decimals() ),
+ 'priceCurrency' => $currency,
+ 'validThrough' => $sale_price_valid_until ?? $price_valid_until,
);
+ if ( wc_tax_enabled() ) {
+ $sale_unit_price_spec['valueAddedTaxIncluded'] = 'incl' === get_option( 'woocommerce_tax_display_shop' );
+ }
+ $markup_offer['priceSpecification'] = array( $sale_unit_price_spec );
}
}
} elseif ( $product->is_type( ProductType::GROUPED ) ) {
@@ -313,12 +315,14 @@ class WC_Structured_Data {
}
$unit_price_specification = array(
- '@type' => 'UnitPriceSpecification',
- 'price' => wc_format_decimal( $min_price, wc_get_price_decimals() ),
- 'priceCurrency' => $currency,
- 'valueAddedTaxIncluded' => 'incl' === $tax_display_mode,
- 'validThrough' => $price_valid_until,
+ '@type' => 'UnitPriceSpecification',
+ 'price' => wc_format_decimal( $min_price, wc_get_price_decimals() ),
+ 'priceCurrency' => $currency,
+ 'validThrough' => $price_valid_until,
);
+ if ( wc_tax_enabled() ) {
+ $unit_price_specification['valueAddedTaxIncluded'] = 'incl' === $tax_display_mode;
+ }
if ( $product->is_on_sale() && $min_price !== $min_sale_price ) {
// `priceType` should only be specified in prices which are not the current offer.
// https://developers.google.com/search/docs/appearance/structured-data/merchant-listing#sale-pricing-example
@@ -338,16 +342,16 @@ class WC_Structured_Data {
// We add the sale price to the top of the array so it's the first offer.
// See https://github.com/woocommerce/woocommerce/issues/55043.
- array_unshift(
- $markup_offer['priceSpecification'],
- array(
- '@type' => 'UnitPriceSpecification',
- 'price' => wc_format_decimal( $min_sale_price, wc_get_price_decimals() ),
- 'priceCurrency' => $currency,
- 'valueAddedTaxIncluded' => 'incl' === $tax_display_mode,
- 'validThrough' => $sale_price_valid_until ?? $price_valid_until,
- )
+ $grouped_sale_spec = array(
+ '@type' => 'UnitPriceSpecification',
+ 'price' => wc_format_decimal( $min_sale_price, wc_get_price_decimals() ),
+ 'priceCurrency' => $currency,
+ 'validThrough' => $sale_price_valid_until ?? $price_valid_until,
);
+ if ( wc_tax_enabled() ) {
+ $grouped_sale_spec['valueAddedTaxIncluded'] = 'incl' === $tax_display_mode;
+ }
+ array_unshift( $markup_offer['priceSpecification'], $grouped_sale_spec );
}
} else {
$tax_display_mode = get_option( 'woocommerce_tax_display_shop' );
@@ -355,12 +359,14 @@ class WC_Structured_Data {
? wc_get_price_including_tax( $product, array( 'price' => $product->get_regular_price() ) )
: wc_get_price_excluding_tax( $product, array( 'price' => $product->get_regular_price() ) );
$unit_price_specification = array(
- '@type' => 'UnitPriceSpecification',
- 'price' => wc_format_decimal( $regular_price, wc_get_price_decimals() ),
- 'priceCurrency' => $currency,
- 'valueAddedTaxIncluded' => 'incl' === $tax_display_mode,
- 'validThrough' => $price_valid_until,
+ '@type' => 'UnitPriceSpecification',
+ 'price' => wc_format_decimal( $regular_price, wc_get_price_decimals() ),
+ 'priceCurrency' => $currency,
+ 'validThrough' => $price_valid_until,
);
+ if ( wc_tax_enabled() ) {
+ $unit_price_specification['valueAddedTaxIncluded'] = 'incl' === $tax_display_mode;
+ }
if ( $product->is_on_sale() ) {
// `priceType` should only be specified in prices which are not the current offer.
// https://developers.google.com/search/docs/appearance/structured-data/merchant-listing#sale-pricing-example
@@ -383,16 +389,16 @@ class WC_Structured_Data {
// We add the sale price to the top of the array so it's the first offer.
// See https://github.com/woocommerce/woocommerce/issues/55043.
- array_unshift(
- $markup_offer['priceSpecification'],
- array(
- '@type' => 'UnitPriceSpecification',
- 'price' => wc_format_decimal( $sale_price, wc_get_price_decimals() ),
- 'priceCurrency' => $currency,
- 'valueAddedTaxIncluded' => 'incl' === $tax_display_mode,
- 'validThrough' => $sale_price_valid_until ?? $price_valid_until,
- )
+ $simple_sale_spec = array(
+ '@type' => 'UnitPriceSpecification',
+ 'price' => wc_format_decimal( $sale_price, wc_get_price_decimals() ),
+ 'priceCurrency' => $currency,
+ 'validThrough' => $sale_price_valid_until ?? $price_valid_until,
);
+ if ( wc_tax_enabled() ) {
+ $simple_sale_spec['valueAddedTaxIncluded'] = 'incl' === $tax_display_mode;
+ }
+ array_unshift( $markup_offer['priceSpecification'], $simple_sale_spec );
}
}
@@ -655,11 +661,13 @@ class WC_Structured_Data {
$markup['price'] = $order->get_total();
$markup['priceCurrency'] = $order->get_currency();
$markup['priceSpecification'] = array(
- 'price' => $order->get_total(),
- 'priceCurrency' => $order->get_currency(),
- 'valueAddedTaxIncluded' => 'true',
+ 'price' => $order->get_total(),
+ 'priceCurrency' => $order->get_currency(),
);
- $markup['billingAddress'] = array(
+ if ( wc_tax_enabled() ) {
+ $markup['priceSpecification']['valueAddedTaxIncluded'] = wc_prices_include_tax();
+ }
+ $markup['billingAddress'] = array(
'@type' => 'PostalAddress',
'name' => $order->get_formatted_billing_full_name(),
'streetAddress' => $order->get_billing_address_1(),
@@ -670,16 +678,16 @@ class WC_Structured_Data {
'email' => $order->get_billing_email(),
'telephone' => $order->get_billing_phone(),
);
- $markup['customer'] = array(
+ $markup['customer'] = array(
'@type' => 'Person',
'name' => $order->get_formatted_billing_full_name(),
);
- $markup['merchant'] = array(
+ $markup['merchant'] = array(
'@type' => 'Organization',
'name' => $shop_name,
'url' => $shop_url,
);
- $markup['potentialAction'] = array(
+ $markup['potentialAction'] = array(
'@type' => 'ViewAction',
'name' => 'View Order',
'url' => $order_url,
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 0b4aafe57bd..5510c4505be 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -15787,7 +15787,7 @@ parameters:
path: includes/class-wc-structured-data.php
-
- message: '#^Offset ''price'' on array\{priceValidUntil\: string, availability\: ''https\://schema\.org…'', url\: mixed, seller\: array\{''@type''\: ''Organization'', name\: mixed, url\: mixed\}, ''@type''\: ''AggregateOffer'', lowPrice\: mixed, highPrice\: mixed, offerCount\: int\<0, max\>, \.\.\.\}\|array\{priceValidUntil\: string, availability\: ''https\://schema\.org…'', url\: mixed, seller\: array\{''@type''\: ''Organization'', name\: mixed, url\: mixed\}, ''@type''\: ''Offer'', priceSpecification\: array\{0\: array\{''@type''\: ''UnitPriceSpecificat…'', price\: mixed, priceCurrency\: mixed, valueAddedTaxIncluded\: bool, validThrough\: string, priceType\?\: ''https\://schema\.org…''\}, 1\?\: array\{''@type''\: ''UnitPriceSpecificat…'', price\: mixed, priceCurrency\: mixed, valueAddedTaxIncluded\: bool, validThrough\: string, priceType\?\: ''https\://schema\.org…''\}\}\} in empty\(\) does not exist\.$#'
+ message: '#^Offset ''price'' on array\{priceValidUntil\: string, availability\: ''https\://schema\.org…'', url\: mixed, seller\: array\{''@type''\: ''Organization'', name\: mixed, url\: mixed\}, ''@type''\: ''AggregateOffer'', lowPrice\: mixed, highPrice\: mixed, offerCount\: int\<0, max\>, \.\.\.\}\|array\{priceValidUntil\: string, availability\: ''https\://schema\.org…'', url\: mixed, seller\: array\{''@type''\: ''Organization'', name\: mixed, url\: mixed\}, ''@type''\: ''Offer'', priceSpecification\: array\{0\: array\{''@type''\: ''UnitPriceSpecificat…'', price\: mixed, priceCurrency\: mixed, validThrough\: string, valueAddedTaxIncluded\?\: bool, priceType\?\: ''https\://schema\.org…''\}, 1\?\: array\{''@type''\: ''UnitPriceSpecificat…'', price\: mixed, priceCurrency\: mixed, validThrough\: string, valueAddedTaxIncluded\?\: bool, priceType\?\: ''https\://schema\.org…''\}\}\} in empty\(\) does not exist\.$#'
identifier: empty.offset
count: 1
path: includes/class-wc-structured-data.php