Guide

Linked Product Stock Management hooks

This add-on ties a choice to a real WooCommerce product, so selecting the choice consumes that product's stock and — optionally — adds it to the cart as its own line item. Its hooks cover the quantities added, the text and price pulled from the linked product, the labels shown when something is out of stock, and the Store API fields it registers for block themes.

See the hook reference index for how to register PHP and JavaScript callbacks.

PHP filters

HookArgumentsPurpose
linked_product_qty_to_add_to_cart$qty, $choice, $quantityMode, $cartItemKey, $cartItemDataHow many units of the linked product to add
mkl_pc_quantity_is_integertrueWhether linked quantities are rounded to whole numbers
mkl_pc/remove_linked_itemstrue, $cartItemKeyWhether removing the parent line also removes linked lines
mkl_pc/set_linked_product_choice_name$name, $linkedProduct, $choiceChoice name taken from the linked product
mkl_pc/set_linked_product_choice_description$description, $linkedProduct, $choiceChoice description taken from the linked product
mkl_pc/set_linked_product_choice_advanced_description$description, $linkedProduct, $choiceAdvanced description taken from the linked product
mkl_pc/set_linked_product_price$price, $linkedProduct, $qtyPrice taken from the linked product
mkl_pc_out_of_stock_choice_label$label, $choice, $productLabel naming a choice that cannot be fulfilled
MKL/PC/Out-of-stock-label$labelThe "Out of stock" badge on a choice
MKL/PC/On-back-order-label$labelThe "On backorder" badge on a choice
mkl_pc/store_api_product_data$data, $productExtra product fields exposed through the Store API
mkl_pc/store_api_product_data_schema$schemaSchema for those fields

PHP actions

HookArgumentsPurpose
mkl_pc/added_linked_product_to_the_cart$cartItemKey, $productIdLinked products were added alongside a configured product

JavaScript

HookTypeArgumentsPurpose
PC.fe.linked_product.default_min_qtyfilter1, modelFallback quantity when a choice has none set
PC.fe.linked_product_qty.updatedactionviewThe customer changed a choice's quantity

linked_product_qty_to_add_to_cart

The most useful hook here. Each choice carries a linked product quantity; this filter runs just before that number is multiplied by the configured product's own quantity, and decides how many units land in the cart.

php functions.php
add_filter( 'linked_product_qty_to_add_to_cart', function ( $qty, $choice, $quantity_mode, $cart_item_key, $cart_item_data ) {	// A pack of six is sold as one unit, but consumes six.	if ( 'pack' === $choice->get_choice( 'my_unit_type' ) ) {		return $qty * 6;	}	return $qty;}, 10, 5 );
linked_product_qty_to_add_to_cart.

Note the 10, 5 — five arguments. The result is multiplied by the parent quantity afterwards, so return a per-unit figure, not a total.

mkl_pc_quantity_is_integer

By default the computed quantity is cast to an integer with intval(). Return false for products sold by length, weight or area, where 2.5 is a legitimate quantity.

php functions.php
add_filter( 'mkl_pc_quantity_is_integer', function () {	return false;} );
mkl_pc_quantity_is_integer.

This filter takes no context, so it applies to every linked product on the site. Make sure WooCommerce itself is configured to allow decimal quantities before turning it off.

mkl_pc/remove_linked_items

When a configured product is removed from the cart, its linked line items go with it. Return false to leave them behind — useful when a linked item is a service or a deposit the customer should keep.

php functions.php
add_filter( 'mkl_pc/remove_linked_items', function ( $remove, $cart_item_key ) {	return $remove;}, 10, 2 );
mkl_pc/remove_linked_items.

mkl_pc/set_linked_product_choice_name, …_description, …_advanced_description

When a choice is configured to take its text from the linked product, these three filters supply each piece. All receive the resolved value, the WC_Product, and the choice.

php functions.php
add_filter( 'mkl_pc/set_linked_product_choice_name', function ( $name, $product, $choice ) {	return $name . ' (' . $product->get_sku() . ')';}, 10, 3 );
mkl_pc/set_linked_product_choice_name, …_description, …_advanced_description.

Returning false or null leaves the choice's own text untouched — that is the documented way to opt out for a particular product rather than blanking the name.

mkl_pc/set_linked_product_price

The price read from the linked product before it becomes the choice's linked_product_price. The third argument is the quantity, so tiered pricing is expressible here.

php functions.php
add_filter( 'mkl_pc/set_linked_product_price', function ( $price, $product, $qty ) {	return $qty >= 10 ? $price * 0.9 : $price;}, 10, 3 );
mkl_pc/set_linked_product_price.

mkl_pc_out_of_stock_choice_label

Builds the label naming a choice that cannot be fulfilled at the requested quantity. The default is Product name > Layer name > Choice name, which is precise but verbose.

php functions.php
add_filter( 'mkl_pc_out_of_stock_choice_label', function ( $label, $choice, $product ) {	return $choice->get_choice( 'name' );}, 10, 3 );
mkl_pc_out_of_stock_choice_label.

MKL/PC/Out-of-stock-label and MKL/PC/On-back-order-label

The short badges printed on a choice in the configurator. Both default to the WooCommerce strings "Out of stock" and "On backorder".

php functions.php
add_filter( 'MKL/PC/Out-of-stock-label', function () {	return __( 'Sold out', 'my-plugin' );} );
MKL/PC/Out-of-stock-label and MKL/PC/On-back-order-label.

These are rendered into an Underscore template, so return plain text or simple markup — not template syntax.

mkl_pc/store_api_product_data and mkl_pc/store_api_product_data_schema

The add-on extends the WooCommerce Store API so block-based carts and checkouts can see stock and price data for linked products. The first filter adds fields, the second declares them.

php functions.php
add_filter( 'mkl_pc/store_api_product_data', function ( $data, $product ) {	$data['my_lead_time'] = get_post_meta( $product->get_id(), '_lead_time', true );	return $data;}, 10, 2 );add_filter( 'mkl_pc/store_api_product_data_schema', function ( $schema ) {	$schema['my_lead_time'] = array(		'description' => __( 'Lead time in days', 'my-plugin' ),		'type'        => 'string',		'readonly'    => true,	);	return $schema;} );
mkl_pc/store_api_product_data and mkl_pc/store_api_product_data_schema.

Add to both, or the field is stripped by the API's schema validation. Note that post_status is only included for users who can manage_woocommerce.

mkl_pc/added_linked_product_to_the_cart

Fires once, after every linked product for a configured line item has been added.

php functions.php
add_action( 'mkl_pc/added_linked_product_to_the_cart', function ( $cart_item_key, $product_id ) {	// The linked keys are on the parent item.	$item = WC()->cart->get_cart_item( $cart_item_key );	$linked = $item['mkl_pc_linked_items'];}, 10, 2 );
mkl_pc/added_linked_product_to_the_cart.

PC.fe.linked_product.default_min_qty

The quantity used when a choice's own linked_product_qty is missing, zero or not a number. Defaults to 1.

javascript custom.js
wp.hooks.addFilter(	'PC.fe.linked_product.default_min_qty',	'my-plugin/stock',	function ( qty, model ) {		return model.get( 'my_min_order' ) || qty;	});
PC.fe.linked_product.default_min_qty.

PC.fe.linked_product_qty.updated

Fires after the customer changes a choice's quantity input and the model has been updated. The argument is the choice view.

javascript custom.js
wp.hooks.addAction( 'PC.fe.linked_product_qty.updated', 'my-plugin/stock', function ( view ) {	console.log( view.model.get( 'linked_product_qty' ) );} );
PC.fe.linked_product_qty.updated.

WooCommerce hooks it fires

The add-on sends its own low-stock and no-stock notifications for linked products, and does so through WooCommerce's own email filters so existing customisations keep working: woocommerce_email_recipient_low_stock, woocommerce_email_subject_low_stock, woocommerce_email_content_low_stock and the matching …_no_stock trio, plus woocommerce_email_headers and woocommerce_email_attachments.

Each is passed the WC_Product as its second argument, exactly as WooCommerce does. It also calls WPML's wpml_original_element_id when resolving translated products.

extra_price_overrides_product_price is shared with the Extra Price add-on and decides whether a choice's extra price replaces the linked product's price rather than adding to it. PC.choices.canSelectChoice and mkl_wc_general_metaboxe_classes come from the core plugin.