Guide

Frontend template hooks

The configurator renders from wp.template markup printed into the page as <script type="text/html"> blocks. These hooks let you add to that markup, or change the attributes and classes it carries.

They are ordinary PHP actions and filters, but what they print is Underscore template syntax evaluated later in the browser — {{ }} escapes, {{{ }}} does not, and <# #> is JavaScript. See Template hooks are different.

Everything here runs once, when the templates are printed. It does not run per choice — the same markup is reused for every choice in the configurator, so anything conditional has to be expressed in template syntax rather than in PHP.

The main view

HookTypePurpose
mkl_pc_frontend_templates_beforeactionBefore any template part is included
mkl_pc_frontend_templates_afteractionAfter all of them
mkl_pc_frontend_templates_partsfilterThe list of template part files to include
mkl_pc_frontend_configurator__main_viewactionInside the configurator's root template
mkl_pc_containeractionInside .mkl_pc_container

Viewer

HookTypePurpose
mkl_pc_layers_beforeactionBefore the layers container
mkl_pc_layersactionInside .mkl_pc_layers
mkl_pc_layers_afteractionAfter the layers container
mkl_pc_templates_empty_vieweractionInside the empty-viewer template
HookTypePurpose
mkl_pc_frontend_configurator_toolbaractionInside the toolbar template
mkl_pc_frontend_configurator_footer_section_left_beforeactionBefore the left footer section
mkl_pc_frontend_configurator_footer_section_left_inner_beforeactionInside it, first
mkl_pc_frontend_configurator_footer_section_left_inneractionInside it
mkl_pc_frontend_configurator_footer_section_left_inner_afteractionInside it, last
mkl_pc_frontend_configurator_footer_section_right_beforeactionBefore the right footer section
mkl_pc_frontend_configurator_footer_form_beforeactionBefore the cart form
mkl_pc_frontend_configurator_footer_formactionInside the cart form
mkl_pc_frontend_configurator_footer_form_afteractionAfter the cart form
mkl_pc_frontend_configurator_footer_afteractionAfter the whole footer
mkl_pc_reset_button_classesfilterClasses on the reset button
mkl_pc/reset_button/before_labelactionInside the reset button, before its label

Steps

HookTypePurpose
mkl_pc/previous_step/button_classesfilterClasses on the previous-step button
mkl_pc/previous_step/beforeactionInside it, before the label
mkl_pc/previous_step/afteractionInside it, after the label
mkl_pc/next_step/button_classesfilterClasses on the next-step button
mkl_pc/next_step/beforeactionInside it, before the label
mkl_pc/next_step/afteractionInside it, after the label

Layers and choices

HookTypePurpose
tmpl-mkl-pc-configurator-layer-item-buttonactionInside a layer button
mkl_pc_layer_thumbnail_altfilteralt text on a layer thumbnail
mkl-pc-configurator-layer-item.with.buttonJS filterWhether a layer renders as <button> or <span>
mkl-pc-configurator-choices--afteractionEnd of the choices list template
tmpl-pc-configurator-choice-item-attributesactionExtra attributes on a choice button
mkl_pc_choice_items_attributesfilterThe attribute array for a choice item
tmpl-pc-configurator-choice-itemactionInside a choice button
tmpl-pc-configurator-choice-item--afteractionAfter a choice button
tmpl-pc-configurator-choice-item-labelfilterThe choice name expression
tmpl-pc-configurator-choice-group-item--beforeactionBefore a choice group
tmpl-pc-configurator-choice-group-item--afteractionAfter a choice group

Summary and add to cart

HookTypePurpose
mkl_pc_frontend_configurator_summaryactionInside the summary template
tmpl-mkl-pc-configurator-add-to-cart--modalactionInside the add-to-cart modal
tmpl-mkl-pc-atc-addedactionThe "added to cart" state
tmpl-mkl-pc-atc-redirection-contentactionThe redirection state

tmpl-pc-configurator-choice-item and tmpl-pc-configurator-choice-item--after

The two you will use most. The first prints inside the choice's <button>, the second after it — which matters, because markup inside a button cannot contain interactive elements.

Core itself uses the first at three priorities: thumbnail at 5, name at 10, description at 50.

php functions.php
add_action( 'tmpl-pc-configurator-choice-item', function () { ?>	<# if ( data.sku ) { #><span class="choice-sku">{{ data.sku }}</span><# } #><?php }, 20 ); // between the name and the description
tmpl-pc-configurator-choice-item and tmpl-pc-configurator-choice-item–after.

Anything you reference as data.… must actually be on the choice model — add it with mkl_pc_choice_default_settings and it will be. See Adding custom data to choices.

Put links, buttons and inputs in --after:

php functions.php
add_action( 'tmpl-pc-configurator-choice-item--after', function () { ?>	<# if ( data.spec_sheet ) { #>		<a class="spec-link" href="{{ data.spec_sheet }}" target="_blank">Specification</a>	<# } #><?php } );
Put links, buttons and inputs in –after.

Both fire for choice groups too, from inside the group's label.

tmpl-pc-configurator-choice-item-attributes and mkl_pc_choice_items_attributes

Two ways to get attributes onto a choice. The action prints raw attribute markup into the button tag, so it can use template syntax:

php functions.php
add_action( 'tmpl-pc-configurator-choice-item-attributes', function () { ?>	data-sku="{{ data.sku }}"<?php } );
tmpl-pc-configurator-choice-item-attributes and mkl_pc_choice_items_attributes.

The filter works on an array and is escaped for you, so it is the safer choice for static values:

php functions.php
add_filter( 'mkl_pc_choice_items_attributes', function ( $attributes ) {	$attributes['data-analytics'] = 'choice';	return $attributes;} );
The filter works on an array and is escaped for you, so it is the safer choice for static values.

Both are printed into every choice. Anything that varies per choice has to come from data.….

tmpl-pc-configurator-choice-item-label

The expression used for the choice name, {{{data.name}}} by default. Because it is passed through wp_kses_post(), you can wrap it but not introduce arbitrary markup.

php functions.php
add_filter( 'tmpl-pc-configurator-choice-item-label', function ( $label ) {	return '<strong>' . $label . '</strong>';} );
tmpl-pc-configurator-choice-item-label.

The footer is where the price, quantity, add-to-cart button and reset button live. The hooks bracket each section, so you can insert without replacing anything:

php functions.php
add_action( 'mkl_pc_frontend_configurator_footer_form_before', function () { ?>	<div class="lead-time"><# if ( data.lead_time ) { #>Ships in {{ data.lead_time }} days<# } #></div><?php } );
mkl_pc_frontend_configurator_footer_*.

Core attaches the reset button to …_footer_section_right_before at priority 30 and the product name to …_footer_section_left_inner, so use priorities around those to position your own.

mkl_pc_frontend_templates_parts

The list of template part files, each an array with path and file. Adding an entry is the supported way to ship a whole template of your own; replacing one is how you override core markup wholesale.

php functions.php
add_filter( 'mkl_pc_frontend_templates_parts', function ( $parts ) {	// Swap the summary template for your own.	foreach ( $parts as &$part ) {		if ( 'summary.php' === $part['file'] ) {			$part['path'] = plugin_dir_path( __FILE__ ) . 'templates/';		}	}	return $parts;} );
mkl_pc_frontend_templates_parts.

A missing file is not fatal but is dumped to the page with var_dump, so check your paths.

mkl-pc-configurator-layer-item.with.button

A JavaScript filter, despite living in a PHP template — it is evaluated in the browser each time a layer renders. It decides whether a layer is a <button> or a non-interactive <span>; core returns false for step layers.

javascript custom.js
wp.hooks.addFilter(	'mkl-pc-configurator-layer-item.with.button',	'my-plugin/layers',	function ( useButton, data ) {		return data.my_readonly ? false : useButton;	});
mkl-pc-configurator-layer-item.with.button.

Register it like any other JavaScript hook — it is listed here because that is where you will find it in the source.

mkl_pc_layer_thumbnail_alt

Layer thumbnails are decorative and carry an empty alt by default. Return a non-empty string to make them informative — but only if the image genuinely conveys something the layer name does not, or you are adding noise for screen reader users.

mkl_pc_layers and mkl_pc_layers_before / _after

The viewer's own hooks. mkl_pc_layers prints inside the element the 2D layer images are stacked into, which makes it the place for a watermark or an overlay:

php functions.php
add_action( 'mkl_pc_layers', function () { ?>	<div class="my-overlay" aria-hidden="true"></div><?php } );
mkl_pc_layers and mkl_pc_layers_before / _after.

On a 3D product the same container holds the canvas instead, so anything you add here must be positioned rather than in normal flow.

mkl_pc_frontend_templates_before and _after

Bracket the whole template block. Use them to print templates of your own without touching the parts list:

php functions.php
add_action( 'mkl_pc_frontend_templates_after', function () { ?>	<script type="text/html" id="tmpl-my-badge">		<span class="badge">{{ data.label }}</span>	</script><?php } );
mkl_pc_frontend_templates_before and _after.