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
| Hook | Arguments | Purpose |
|---|---|---|
linked_product_qty_to_add_to_cart | $qty, $choice, $quantityMode, $cartItemKey, $cartItemData | How many units of the linked product to add |
mkl_pc_quantity_is_integer | true | Whether linked quantities are rounded to whole numbers |
mkl_pc/remove_linked_items | true, $cartItemKey | Whether removing the parent line also removes linked lines |
mkl_pc/set_linked_product_choice_name | $name, $linkedProduct, $choice | Choice name taken from the linked product |
mkl_pc/set_linked_product_choice_description | $description, $linkedProduct, $choice | Choice description taken from the linked product |
mkl_pc/set_linked_product_choice_advanced_description | $description, $linkedProduct, $choice | Advanced description taken from the linked product |
mkl_pc/set_linked_product_price | $price, $linkedProduct, $qty | Price taken from the linked product |
mkl_pc_out_of_stock_choice_label | $label, $choice, $product | Label naming a choice that cannot be fulfilled |
MKL/PC/Out-of-stock-label | $label | The "Out of stock" badge on a choice |
MKL/PC/On-back-order-label | $label | The "On backorder" badge on a choice |
mkl_pc/store_api_product_data | $data, $product | Extra product fields exposed through the Store API |
mkl_pc/store_api_product_data_schema | $schema | Schema for those fields |
PHP actions
| Hook | Arguments | Purpose |
|---|---|---|
mkl_pc/added_linked_product_to_the_cart | $cartItemKey, $productId | Linked products were added alongside a configured product |
JavaScript
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
PC.fe.linked_product.default_min_qty | filter | 1, model | Fallback quantity when a choice has none set |
PC.fe.linked_product_qty.updated | action | view | The 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.
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 );
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.
add_filter( 'mkl_pc_quantity_is_integer', function () { return false;} );
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.
add_filter( 'mkl_pc/remove_linked_items', function ( $remove, $cart_item_key ) { return $remove;}, 10, 2 );
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.
add_filter( 'mkl_pc/set_linked_product_choice_name', function ( $name, $product, $choice ) { return $name . ' (' . $product->get_sku() . ')';}, 10, 3 );
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.
add_filter( 'mkl_pc/set_linked_product_price', function ( $price, $product, $qty ) { return $qty >= 10 ? $price * 0.9 : $price;}, 10, 3 );
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.
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-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".
add_filter( 'MKL/PC/Out-of-stock-label', function () { return __( 'Sold out', 'my-plugin' );} );
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.
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;} );
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.
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 );
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.
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_qty.updated
Fires after the customer changes a choice's quantity input and the model has been updated. The argument is the choice view.
wp.hooks.addAction( 'PC.fe.linked_product_qty.updated', 'my-plugin/stock', function ( view ) { console.log( view.model.get( 'linked_product_qty' ) );} );
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.
Related hooks from other plugins
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.