WordPress / WooCommerce Custom PHP + JavaScript Product Engineering Live Price Engine

Custom Product
Configurator — Build Your Own. Price in Real Time.

A UK manufacturer needed customers to configure bespoke products online — selecting material, dimensions, finish and accessories — with the total price recalculating instantly on every change. No configurator plugin came close to their requirements. I built the entire engine from scratch — REST API, pricing matrix, live JS layer and full WooCommerce cart integration.

Result: Sub-200ms live price updates — custom configurations processed and displayed instantly, with all selections carried through to cart, checkout, order email and admin panel.

Problem & Solution

WooCommerce's native variable products are built for simple attribute combinations. The client needed a multi-dimensional pricing engine where dozens of option combinations produce unique prices — and every change reflects immediately on screen.

The Challenge

WooCommerce variations cap out at 50 combinations and can't handle matrix-style pricing across multiple independent dimensions. Off-the-shelf configurator plugins brought bloat, £500+/yr licencing and zero flexibility.

  • Native variations couldn't model multi-dimensional pricing rules
  • Every plugin required page reload to recalculate price
  • Custom option metadata had to persist through to every order touchpoint
  • Admin needed to manage pricing rules without touching code
  • Solution must support future option categories without refactoring

The Solution

A custom PHP pricing engine exposed via a WP REST endpoint, paired with a lean vanilla JS layer that fires on every option change and updates the price display without a page reload — zero frameworks, zero overhead.

  • JSON pricing matrix stored in product meta — fully admin-editable
  • Vanilla JS fetches price via REST API on every option change
  • Custom selections stored as cart item meta and persisted to orders
  • Options displayed in cart line items, order confirmation and admin
  • Add new option categories via admin metabox — no code changes needed

Why a Custom REST Endpoint Instead of AJAX Admin Action?

WordPress AJAX requires wp_ajax_* hooks and produces bloated responses through the admin bootstrap. A dedicated REST endpoint under /wp-json/configurator/v1/price is cacheable, returns clean JSON, and runs at a fraction of the overhead — giving us genuine sub-200ms response times even on shared hosting.


Four Configuration Layers

From the options the customer sees to the price they pay and the order the client receives — every layer was engineered to work together as a single, coherent system.

1
Options Rendering Engine PHP Layer

Dynamic Option Groups via Custom Product Meta

Each configurable product stores its option groups — material, dimension, finish, accessories — as structured JSON in product meta. A custom template hook renders these as native HTML form controls, injected cleanly into the product page without overriding WooCommerce templates.

woocommerce_before_add_to_cart_button JSON option schema Admin metabox editor Zero template override

Options renderer — reads product meta schema and outputs accessible form controls:

configurator-options.php
add_action( 'woocommerce_before_add_to_cart_button', 'render_configurator_options' );

function render_configurator_options() {
    global $product;
    $schema = json_decode( get_post_meta( $product->get_id(), '_configurator_schema', true ), true );

    if ( empty( $schema['option_groups'] ) ) return;

    foreach ( $schema['option_groups'] as $group ) {
        echo '<div class="cfg-group" data-group="' . esc_attr( $group['key'] ) . '">';
        echo '<label>' . esc_html( $group['label'] ) . '</label>';
        echo '<select name="cfg[' . esc_attr( $group['key'] ) . ']" class="cfg-select">';
        foreach ( $group['options'] as $opt ) {
            echo '<option value="' . esc_attr( $opt['value'] ) . '">' . esc_html( $opt['label'] ) . '</option>';
        }
        echo '</select></div>';
    }
}
2
Live Price Calculator JS + REST API

Vanilla JS Event Layer → Custom WP REST Endpoint

Every option change triggers a debounced fetch() call to a registered WP REST endpoint. The endpoint receives the product ID and selected option values, runs the PHP pricing matrix lookup, and returns a clean JSON price object. The JS layer updates the displayed price — no page reload, no UI flash.

register_rest_route() Vanilla JS fetch() Debounced on input JSON response Sub-200ms roundtrip

Live price updater — fires on every option change and patches the DOM price display:

configurator-live.js
// Debounce helper — prevents flooding REST endpoint on rapid changes
const debounce = ( fn, ms ) => { let t; return ( ...args ) => { clearTimeout( t ); t = setTimeout( () => fn( ...args ), ms ) }; };

const updatePrice = debounce( async () => {
    const selections = {};
    document.querySelectorAll( '.cfg-select' ).forEach( el => {
        selections[ el.closest( '.cfg-group' ).dataset.group ] = el.value;
    });

    const res = await fetch( cfgData.restUrl, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': cfgData.nonce },
        body: JSON.stringify( { product_id: cfgData.productId, options: selections } )
    });

    const { price_html, price_raw } = await res.json();
    document.querySelector( '.cfg-price-display' ).innerHTML = price_html;
    document.querySelector( '[name="cfg_price"]' ).value = price_raw;
}, 180 );

document.querySelectorAll( '.cfg-select' ).forEach( el => el.addEventListener( 'change', updatePrice ) );
updatePrice(); // Run on page load to show initial price
3
Cart & Order Integration WooCommerce Hooks

Custom Selections Persisted Through the Entire Order Lifecycle

When the customer adds to cart, all configuration selections are captured via woocommerce_add_cart_item_data and stored as cart item meta. From there, they flow automatically into the order line items, the customer confirmation email, and the WooCommerce admin order view — without any duplicate handling logic.

woocommerce_add_cart_item_data woocommerce_get_item_data woocommerce_checkout_create_order_line_item Dynamic cart price override
4
Admin Configuration Panel Custom Metabox

Pricing Matrix Editor — No Code Changes to Update Prices

A custom metabox on the product edit page lets the admin define option groups, option values, and the full pricing matrix — stored as structured JSON in post meta. Adding a new material type or changing a finish surcharge requires a single field update in wp-admin. No developer, no deployment, no downtime.

add_meta_box() JSON matrix editor Repeater UI via JS save_post hook Backwards compatible schema

How It Works Under the Hood

From the customer's first option change to the manufacturer's order notification — every step is handled in a clean, linear flow with no state management library, no React, and no build pipeline.

01

Customer selects a configuration option

The vanilla JS layer attaches a change event listener to every .cfg-select dropdown on the product page. Each change triggers the debounced updatePrice() function, which first collects all current selections into a key-value object before sending anything to the server.

02

fetch() fires to the WP REST endpoint with current selections

A POST request is sent to /wp-json/configurator/v1/price with the product ID and the full selections object as JSON. The request is authenticated via a localized nonce — preventing spoofed price submissions. The 180ms debounce ensures rapid option changes don't flood the endpoint.

03

PHP reads the pricing matrix and calculates the final price

The REST callback retrieves the product's JSON pricing matrix from post meta, extracts the base price, then iterates over each selected option to apply its surcharge modifier. The result is formatted using WooCommerce's wc_price() function and returned as a JSON object containing both the raw numeric value and the formatted HTML string.

04

JS updates the price display — no reload, no flash

On receiving the JSON response, the JS patches two DOM elements: the visible price display receives the formatted price_html, and a hidden input field stores the raw price_raw value that will be submitted with the add-to-cart form. The update is imperceptible — typically under 200ms from change to display.

PHP REST handler — matrix lookup and price assembly:

configurator-rest.php
register_rest_route( 'configurator/v1', '/price', [
    'methods'  => 'POST',
    'callback' => 'configurator_calculate_price',
    'permission_callback' => '__return_true',
] );

function configurator_calculate_price( $request ) {
    $product_id = absint( $request['product_id'] );
    $options    = array_map( 'sanitize_text_field', (array) $request['options'] );
    $matrix     = json_decode( get_post_meta( $product_id, '_configurator_schema', true ), true );

    $price = (float) $matrix['base_price'];

    // Add surcharge for each selected option from the pricing matrix
    foreach ( $options as $group_key => $option_value ) {
        if ( isset( $matrix['pricing'][ $group_key ][ $option_value ] ) ) {
            $price += (float) $matrix['pricing'][ $group_key ][ $option_value ];
        }
    }

    return rest_ensure_response( [
        'price_raw'  => round( $price, 2 ),
        'price_html' => wc_price( $price ),
    ] );
}
05

Add to cart — all selections stored as order item meta

On add-to-cart, woocommerce_add_cart_item_data captures the posted selections and the calculated price. A woocommerce_before_calculate_totals hook overrides the cart item's price with the custom value. The selections then flow through woocommerce_get_item_data for cart display and woocommerce_checkout_create_order_line_item for permanent order storage — visible in emails, admin, and customer account.

Cart meta persistence — captures selections and custom price on add-to-cart:

configurator-cart.php
// Attach custom selections and price to cart item data
add_filter( 'woocommerce_add_cart_item_data', 'cfg_add_cart_item_data', 10, 2 );

function cfg_add_cart_item_data( $data, $product_id ) {
    if ( ! empty( $_POST['cfg'] ) ) {
        $data['cfg_options'] = array_map( 'sanitize_text_field', (array) $_POST['cfg'] );
        $data['cfg_price']   = floatval( $_POST['cfg_price'] ?? 0 );
    }
    return $data;
}

// Override WooCommerce price with the custom-calculated value
add_action( 'woocommerce_before_calculate_totals', 'cfg_set_cart_item_price' );

function cfg_set_cart_item_price( $cart ) {
    foreach ( $cart->get_cart() as $item ) {
        if ( isset( $item['cfg_price'] ) ) {
            $item['data']->set_price( $item['cfg_price'] );
        }
    }
}

Stack & Approach

No build pipeline, no JavaScript framework, no licensing fees. Just clean PHP, vanilla ES6 and WooCommerce's own hooks — making this system fast, portable and trivially maintainable.

🔌

WP REST API

A registered REST endpoint under /wp-json/configurator/v1/price handles all price calculations — cacheable, clean JSON, no admin bootstrap overhead.

Vanilla JS (ES6)

Zero framework dependency. Native fetch(), querySelectorAll() and DOM patching — delivering a sub-200ms live update experience without loading React or jQuery.

🛒

WooCommerce Cart Hooks

Custom selections attached via woocommerce_add_cart_item_data, price overridden via woocommerce_before_calculate_totals, displayed via woocommerce_get_item_data.

📦

JSON Pricing Matrix

All pricing rules stored as structured JSON in product post meta — edited through a custom metabox UI. Add new options or change prices with zero code changes or deployments.

🧾

Order Item Meta API

Selections stored permanently via woocommerce_checkout_create_order_line_item — visible in the cart, checkout summary, order confirmation email and admin order view.

🔧

Custom Admin Metabox

A dynamic repeater interface lets the store admin define option groups, option labels and surcharges directly in the product edit screen — no custom admin page required.


What the Client Got

A fully owned, plugin-free product configurator that handles real-time pricing, complete order lifecycle tracking and admin-managed pricing rules — with no recurring costs and no external dependencies.

Real-Time Price Updates Under 200ms

Every option change reflects in the displayed price almost instantly — no page reload, no spinner, no delay — via a lean REST endpoint and debounced fetch calls.

🎛️

Admin-Managed Pricing — Zero Developer Dependency

The client updates material surcharges, adds new finish options and adjusts the base price entirely from wp-admin. No deployments, no code changes, no support tickets.

📋

Full Order Lifecycle Visibility

Every custom configuration — material, finish, dimensions, accessories — is visible in the cart, checkout confirmation, customer order email and the WooCommerce admin order panel.

🔒

Tamper-Proof Custom Pricing

Prices are calculated server-side on every add-to-cart — the client-side value is verified against the matrix before being applied. Customers cannot manipulate prices by editing the DOM.

"The challenge here was not just the pricing logic — any developer can write a conditional. The challenge was architecting it so the price feels instant to the customer, the cart is always accurate, every order tells the manufacturer exactly what to build, and the client never needs a developer to change a price again. All four had to be true simultaneously."

Muhammad Abdullah Hashmi  ·  Full-Stack WordPress, WooCommerce & PHP Developer  ·  8 Years Experience

Available for New Projects

Need a custom product engine?

I build bespoke WooCommerce solutions engineered precisely to your business logic — no plugin compromises, no recurring licence costs, and complete code ownership.