These hooks cover everything between the product page and the configurator opening: the Configure button, whether the configurator's scripts load at all, the configuration object handed to the browser, and the add-to-cart form inside the configurator.
See the hook reference index for how to register callbacks.
The Configure button
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
mkl_pc_configure_button | filter | $html | The button markup |
mkl_pc_configure_button_a11y_description | filter | $html, $product | The screen-reader heading before it |
get_configurator_element_attributes | filter | $attributes, $product | Data attributes on the trigger element |
mkl_configurator_button_data_attributes | filter | $attributes, $productId, $atts | Same, for the [mkl_configurator_button] shortcode |
mkl_configurator_data_attributes | filter | $attributes, $productId, $atts | Same, for the inline [mkl_configurator] shortcode |
configurator_convert_base_price | filter | false, $product | Whether the base price is currency-converted client-side |
Loading and assets
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
load_configurator_on_page | filter | $load | Whether to load the configurator on this page |
mkl_pc_scripts_product_page_before | action | (none) | Before the configurator's scripts are enqueued |
mkl_pc_scripts_product_page_after | action | (none) | After they are |
mkl_pc_3d_viewer_enqueued | action | $productId | The 3D viewer was enqueued for a 3D product, on its page or in a shortcode |
mkl_pc/js/product_configurator/dependencies | filter | $deps | Dependencies of the main script |
mkl_pc/js/configurator/dependencies | filter | $deps | Dependencies of the configurator view script |
mkl_pc/css/product_configurator.css | filter | $stylesheet | URL of the theme stylesheet |
mkl_pc_3d_preload_urls | filter | $urls, $productId | Model URLs preloaded for 3D products |
Configuration handed to the browser
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
mkl_pc_js_config | filter | $config | The config section of PC_config |
mkl_pc_frontend_js_config | filter | $args | The whole of PC_config, last |
mkl_pc_bg_image | filter | $url | Default viewer background image |
mkl_pc_show_form | filter | $show, $postId | Whether the configurator renders a cart form |
mkl_pc/reset_configurator_on_ajax_add_to_cart | filter | $reset, $postId | Reset after an AJAX add to cart |
mkl_pc_do_not_override_images | filter | false | Skip re-resolving image URLs to the configured sizes |
mkl_pc_get_saved_configuration_content | filter | $configuration | A configuration being restored into the configurator |
mkl_pc/current_user_can_view_order_config | filter | $canView | Who may reload a configuration from an order |
Price and cart form
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
mkl_pc/get_product_price | filter | $price, $product | The base price the configurator prices from |
mkl_pc/display_add_to_cart_button | filter | true, $product | Whether the form renders at all |
mkl_pc/add_to_cart_button/default_label | filter | $label | The label before third-party plugins adjust it |
mkl_pc/add_to_cart_button/label | filter | $label | The final label |
mkl_pc/edit_item_in_cart_button/label | filter | $label | Label when editing an existing cart item |
mkl_pc/get_cart_icon | filter | $svg | The cart icon markup |
mkl_pc_frontend_configurator_cart_form | action | (none) | Inside the cart form |
mkl_pc_frontend_configurator_after_add_to_cart | action | (none) | After the add-to-cart button |
mkl_pc/sku_mode | filter | $mode, $product | How SKUs are displayed |
mkl_pc/sku_label | filter | $html, $product | The SKU label markup |
mkl_pc_configuration_price_shortcode_output | filter | $output, $price, $atts, $configId | Output of the configuration price shortcode |
load_configurator_on_page
The gate for every asset the configurator loads. By default it returns true when the product is
configurable, or the post contains one of the configurator shortcodes, or the post has the
mkl_load_configurator_on_page meta.
Return true to force the scripts onto a page where the shortcode is not detected — a page
builder's template, a popup, a block your theme renders late:
add_filter( 'load_configurator_on_page', function ( $load ) { return $load || is_page( 'design-studio' );} );
This is the hook behind
Forcing the configurator scripts to load.
Returning true everywhere loads a substantial amount of JavaScript on every page — target it.
mkl_pc_configure_button
The whole Configure button. You get the assembled markup, including the data attributes the configurator needs to open.
add_filter( 'mkl_pc_configure_button', function ( $html ) { return str_replace( 'configure-product ', 'configure-product my-class ', $html );} );
Preserve the configure-product class and the data-… attributes, or the button stops
opening the configurator. If you only need extra attributes, use
get_configurator_element_attributes instead — it is far safer:
add_filter( 'get_configurator_element_attributes', function ( $attributes, $product ) { $attributes['my_campaign'] = 'spring'; return $attributes;}, 10, 2 );
Attribute names are printed as data-{name} and escaped for you. The same array already carries
product_id, price, regular_price, is_on_sale and a settings sub-array.
See also Overriding the Configure button.
mkl_pc_js_config and mkl_pc_frontend_js_config
Two layers of the same object. mkl_pc_js_config filters the config section — the behaviour
flags read all over the frontend. mkl_pc_frontend_js_config filters the complete PC_config
object, including lang and config, and runs last.
// Force steps off for one product, whatever the setting says.add_filter( 'mkl_pc_js_config', function ( $config ) { if ( 12345 === get_the_ID() ) { $config['use_steps'] = false; } return $config;} );// Add your own data for your own scripts to read.add_filter( 'mkl_pc_frontend_js_config', function ( $args ) { $args['my_plugin'] = array( 'endpoint' => rest_url( 'my/v1/quote' ) ); return $args;} );
mkl_pc_frontend_js_config must return an array — anything else is replaced with an empty
one, which breaks the configurator entirely.
mkl_pc/get_product_price
The base price the configurator starts from before any extra prices are added. It runs after the plugin's currency-conversion compatibility layers, so what you return is final.
add_filter( 'mkl_pc/get_product_price', function ( $price, $product ) { return my_customer_specific_price( $price, $product );}, 10, 2 );
This changes the price the customer sees while configuring. The price actually charged comes from WooCommerce, so pair this with a cart hook or the two will disagree.
mkl_pc/display_add_to_cart_button
Return false and the configurator renders no cart form at all — the pattern for a catalogue-mode
or quote-only configurator.
add_filter( 'mkl_pc/display_add_to_cart_button', function ( $display, $product ) { return $product->get_price() ? $display : false;}, 10, 2 );
mkl_pc/add_to_cart_button/label and …/default_label
default_label filters "Add to cart" before the plugin's quote-plugin compatibility runs;
label filters the result. Use label unless you specifically need to run first.
add_filter( 'mkl_pc/add_to_cart_button/label', function ( $label ) { return __( 'Order this configuration', 'my-plugin' );} );
mkl_pc_frontend_configurator_cart_form and …_after_add_to_cart
Both print into the configurator's footer form, which is Underscore template markup — see Template hooks are different.
add_action( 'mkl_pc_frontend_configurator_cart_form', function () { ?> <label class="gift-wrap"> <input type="checkbox" name="gift_wrap" value="1"> <?php esc_html_e( 'Gift wrap', 'my-plugin' ); ?> </label><?php } );
Fields added here are inside the real form, so they post with the add-to-cart request.
mkl_pc/current_user_can_view_order_config
Guards reloading a configuration out of an order item — the "edit this configuration" flow from My Account. The default allows shop managers and the order's own customer.
add_filter( 'mkl_pc/current_user_can_view_order_config', function ( $can_view ) { return $can_view;} );
The default is already correct for almost every store. Widening it exposes one customer's configuration to another.
mkl_pc_get_saved_configuration_content
The configuration about to be loaded into the configurator, whether it came from a cart item, an order, or a saved design. Return an empty array to load nothing.
add_filter( 'mkl_pc_get_saved_configuration_content', function ( $configuration ) { return $configuration;} );
mkl_pc/js/product_configurator/dependencies and mkl_pc/js/configurator/dependencies
Add script handles the configurator must wait for. The second defaults to
jquery, backbone, wp-util, wp-hooks.
add_filter( 'mkl_pc/js/configurator/dependencies', function ( $deps ) { $deps[] = 'my-plugin-configurator-extensions'; return $deps;} );
This is only needed when your script must run before the configurator boots. For ordinary hook
callbacks, depending on wp-hooks alone is enough and works on every page.
mkl_pc/css/product_configurator.css
The URL of the active theme's stylesheet, before it is registered as mlk_pc/css. Point it at
your own file to replace the configurator's styling wholesale — though a child theme or extra
stylesheet is usually a better idea.
mkl_pc_scripts_product_page_before and _after
Bracket the configurator's own enqueues, which is what makes them useful for ordering: register
on _before if the configurator must depend on you, on _after if you must load later.
add_action( 'mkl_pc_scripts_product_page_after', function () { wp_enqueue_script( 'my-plugin-after', '…', array( 'mkl_pc/js/product_configurator' ), '1.0', true );} );
mkl_pc_3d_viewer_enqueued
Fires when the 3D viewer script is enqueued for a 3D product: on the product's own page, and for
each 3D product a [mkl_configurator] or [mkl_configurator_button] shortcode shows on any other
page. It fires once per product and request, with the parent product ID.
This is the place to enqueue scripts that extend the 3D viewer. Use the ID it gives you rather than
the global $post: on a shortcode page, the global post is the page, not the product. On the product
page it fires just before mkl_pc_scripts_product_page_after; for a shortcode it fires while the
content renders, so enqueue in the footer.
add_action( 'mkl_pc_3d_viewer_enqueued', function ( $product_id ) { if ( ! get_post_meta( $product_id, '_my_3d_feature', true ) ) { return; } wp_enqueue_script( 'my-3d-addon', '…', array( 'mkl_pc/fe_3d_viewer' ), '1.0', true );} );
mkl_pc_3d_preload_urls
The glTF model URLs emitted as <link rel="preload"> in the head of a 3D product page. Filter it
to drop a model that is rarely used, or to add one you load yourself.
add_filter( 'mkl_pc_3d_preload_urls', function ( $urls, $product_id ) { return array_slice( $urls, 0, 1 ); // preload only the first model}, 10, 2 );
mkl_pc/sku_mode and mkl_pc/sku_label
sku_mode is 'individual' by default, printing each choice's SKU beside it in cart and order
meta. sku_label is the markup before the value.
add_filter( 'mkl_pc/sku_mode', function ( $mode, $product ) { return 'none';}, 10, 2 );
Note that mkl_pc/sku_mode is applied in two places, only one of which passes $product — guard
against it being absent.
mkl_pc_do_not_override_images
The configurator normally re-resolves every image URL to the sizes chosen in its settings. Return
true to leave the stored URLs alone — useful when a CDN or an image optimiser has already
rewritten them.
mkl_pc_configuration_price_shortcode_output
The rendered output of the configuration price shortcode, with the raw price, the shortcode attributes and the configuration id alongside it.
add_filter( 'mkl_pc_configuration_price_shortcode_output', function ( $output, $price, $atts, $config_id ) { return '<span class="from">' . esc_html__( 'from', 'my-plugin' ) . '</span> ' . $output;}, 10, 4 );
Compatibility filters
configurator_convert_base_price, wc_aelia_cs_get_product_price and
woocommerce_product_price_class exist for multi-currency plugins and themes. The first decides
whether the browser converts the base price itself; the other two are third-party hooks the
plugin fires so existing customisations keep working.