SEOS THEMES

seosthemes.org

WordPress Themes
logo My Account
Buy All 34 Premium Themes For the Price Of €79.98

Building a WordPress Plugin for Excavator Services with a Live Price Calculator

услуги с багер
услуги с багер

If you run a small excavation or earthmoving business — digging foundations, clearing land, demolition work, trenching for pipes — you’ve probably had this conversation a hundred times: someone calls, describes a job in three vague sentences, and asks “so how much would that cost?” You do some mental math based on machine size, hours, and distance, and quote a rough number.

What if your website could do that math before the phone even rings?

That’s exactly what we’re building today: a WordPress plugin called Excavator Services Estimator. Visitors pick an excavator/service type, enter job details (hours needed, distance to haul debris, extra equipment), and watch a live price estimate update on screen — no page reload, no waiting for a callback.

It’s also a genuinely great way to learn how WordPress plugins work under the hood: custom post types, meta boxes, shortcodes, and AJAX all show up naturally in a project like this.

Let’s dig in (sorry, had to).

Why build a custom plugin instead of a generic form builder?

Generic contact-form plugins collect information — they don’t calculate anything. A quote calculator plugin needs actual pricing logic (rates per hour, per machine size, per kilometer of transport), and that logic is specific to your business. Building your own plugin means:

  • The pricing rules live in code you control, not in a paid plugin’s black-box settings.
  • You can add machine-specific fields (bucket size, tonnage, fuel surcharge) that no generic tool anticipates.
  • You genuinely learn the core WordPress architecture by building something real instead of following a toy tutorial.

The plan

Our plugin will:

  1. Register a custom post type called Excavator Services — so each service (mini excavator digging, trenching, land clearing, demolition, etc.) is managed like a normal WordPress post.
  2. Let each service define a base hourly rate in a custom pricing field.
  3. Provide an [excavator_estimator] shortcode that renders a live calculator: choose a service, enter hours, distance for debris transport, and whether a second machine/operator is needed.
  4. Use AJAX so the estimate recalculates instantly as the visitor types — the detail that makes it feel like a real tool instead of a static form.

Step 1: The plugin skeleton

Every WordPress plugin starts with a header comment that tells WordPress the plugin’s name and lets it show up in the Plugins screen.

<?php
/**
 * Plugin Name: Excavator Services Estimator
 * Description: A directory of excavation services with a live price calculator.
 * Version: 1.0.0
 * Author: Your Name
 */

if (!defined('ABSPATH')) {
    exit; // Blocks direct access if someone requests this PHP file straight from a browser.
}

define('EXS_PATH', plugin_dir_path(__FILE__));
define('EXS_URL', plugin_dir_url(__FILE__));

That ABSPATH check is a small habit worth keeping in every plugin file — it stops the file from being executed outside the WordPress environment, which is a common attack vector for badly-written plugins.

Step 2: Register the “Excavator Services” custom post type

Instead of hardcoding “mini excavator,” “trenching,” “demolition” into an array somewhere, we register a Custom Post Type (CPT). Each service becomes a normal, editable WordPress post — but grouped under its own admin menu instead of mixing with blog content.

function exs_register_service_cpt() {
    register_post_type('exs_service', [
        'labels' => [
            'name'          => 'Excavator Services',
            'singular_name' => 'Service',
            'add_new_item'  => 'Add New Service',
        ],
        'public'       => true,
        'has_archive'  => true,
        'menu_icon'    => 'dashicons-hammer',
        'supports'     => ['title', 'editor', 'thumbnail'],
        'show_in_rest' => true, // Enables the Gutenberg block editor for descriptions.
    ]);
}
add_action('init', 'exs_register_service_cpt');

Now, in the admin, you’d add posts like: “Mini Excavator Digging,” “Trenching for Pipes,” “Land Clearing,” “Demolition & Debris Removal” — each becomes its own manageable entry.

add_action('init', ...) is the classic WordPress pattern: instead of running code immediately, you tell WordPress “call this function when the init event fires.” Hooks like this are the backbone of nearly everything a WordPress plugin does.

Step 3: Give each service an hourly rate

Custom post types handle titles and descriptions well, but pricing needs a structured field. For that, we add a meta box — a small custom panel inside the post editor.

function exs_add_pricing_metabox() {
    add_meta_box(
        'exs_pricing',
        'Pricing Details',
        'exs_render_pricing_metabox',
        'exs_service',
        'side'
    );
}
add_action('add_meta_boxes', 'exs_add_pricing_metabox');

function exs_render_pricing_metabox($post) {
    $hourly_rate = get_post_meta($post->ID, '_exs_hourly_rate', true);
    wp_nonce_field('exs_save_pricing', 'exs_pricing_nonce');
    ?>
    <label for="exs_hourly_rate">Hourly Rate ($)</label>
    <input type="number" id="exs_hourly_rate" name="exs_hourly_rate"
           value="<?php echo esc_attr($hourly_rate); ?>" step="1" style="width:100%;">
    <p style="color:#666;font-size:12px;">
        e.g. Mini excavator: $85/hr, Standard excavator: $140/hr, Demolition rig: $200/hr
    </p>
    <?php
}

function exs_save_pricing_metabox($post_id) {
    if (!isset($_POST['exs_pricing_nonce']) ||
        !wp_verify_nonce($_POST['exs_pricing_nonce'], 'exs_save_pricing')) {
        return;
    }
    if (isset($_POST['exs_hourly_rate'])) {
        update_post_meta($post_id, '_exs_hourly_rate', floatval($_POST['exs_hourly_rate']));
    }
}
add_action('save_post', 'exs_save_pricing_metabox');

Notice the nonce (wp_nonce_field / wp_verify_nonce). It’s a hidden security token proving the form submission genuinely came from your own admin screen — not from a malicious site tricking a logged-in admin into silently changing prices. Skipping this is one of the most common beginner security mistakes in WordPress plugins, so it’s worth building the habit early.

Step 4: The shortcode — embedding the calculator on any page

A shortcode lets you drop [excavator_estimator] into any page, and WordPress swaps it out for whatever HTML your function returns.

function exs_render_estimator_shortcode() {
    $services = get_posts([
        'post_type'   => 'exs_service',
        'numberposts' => -1,
    ]);

    ob_start(); ?>
    <div id="exs-estimator">
        <label for="exs-service-select">Choose a service:</label>
        <select id="exs-service-select">
            <?php foreach ($services as $service): ?>
                <option value="<?php echo esc_attr($service->ID); ?>">
                    <?php echo esc_html($service->post_title); ?>
                </option>
            <?php endforeach; ?>
        </select>

        <label>Estimated hours needed:
            <input type="number" id="exs-hours" min="1" value="4">
        </label>

        <label>Debris haul-away distance (km):
            <input type="number" id="exs-distance" min="0" value="0">
        </label>

        <label>
            <input type="checkbox" id="exs-second-operator">
            Second machine / operator needed
        </label>

        <div id="exs-result">Estimated cost: <strong>$0</strong></div>
    </div>
    <?php
    return ob_get_clean();
}
add_shortcode('excavator_estimator', 'exs_render_estimator_shortcode');

ob_start() / ob_get_clean() lets you write normal-looking HTML inside PHP tags and “capture” it as a return value, instead of awkwardly echoing piece by piece. It keeps shortcode templates readable, especially once they have several form fields like this one.

Step 5: Making it live with AJAX

This is what makes the calculator feel like a real tool rather than a static quote form. Every time the visitor changes the number of hours or the distance, the price should update instantly.

First, enqueue a JavaScript file and pass it the info it needs to talk securely to WordPress:

function exs_enqueue_scripts() {
    wp_enqueue_script('exs-estimator', EXS_URL . 'js/estimator.js', ['jquery'], '1.0', true);
    wp_localize_script('exs-estimator', 'exsAjax', [
        'url'   => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('exs_estimate_nonce'),
    ]);
}
add_action('wp_enqueue_scripts', 'exs_enqueue_scripts');

wp_localize_script bridges PHP and JavaScript — it’s how the AJAX URL and security nonce, both generated server-side, become available to your front-end script.

Next, the PHP side that actually calculates the price when JavaScript requests it:

function exs_calculate_estimate() {
    check_ajax_referer('exs_estimate_nonce', 'nonce');

    $service_id      = intval($_POST['service_id']);
    $hours           = max(1, intval($_POST['hours']));
    $distance        = max(0, floatval($_POST['distance']));
    $second_operator = !empty($_POST['second_operator']);

    $rate = floatval(get_post_meta($service_id, '_exs_hourly_rate', true));

    $price = $rate * $hours;
    $price += $distance * 3.5;      // $3.50 per km for debris transport
    if ($second_operator) {
        $price += $rate * $hours * 0.8; // Second machine costs 80% of the base job
    }

    wp_send_json_success(['price' => round($price, 2)]);
}
add_action('wp_ajax_exs_calculate', 'exs_calculate_estimate');
add_action('wp_ajax_nopriv_exs_calculate', 'exs_calculate_estimate');

Two hooks matter here: wp_ajax_exs_calculate handles the request for logged-in users, and wp_ajax_nopriv_exs_calculate handles it for anonymous site visitors — which, realistically, is almost everyone requesting a quote on a public site. Forget the nopriv version and your calculator will work perfectly for you in the admin dashboard while silently failing for every actual customer. This is one of the most common “it works for me but not for users” bugs in WordPress AJAX.

Finally, the JavaScript that ties it all together (js/estimator.js):

jQuery(function ($) {
    function updateEstimate() {
        $.post(exsAjax.url, {
            action: 'exs_calculate',
            nonce: exsAjax.nonce,
            service_id: $('#exs-service-select').val(),
            hours: $('#exs-hours').val(),
            distance: $('#exs-distance').val(),
            second_operator: $('#exs-second-operator').is(':checked') ? 1 : 0,
        }, function (response) {
            if (response.success) {
                $('#exs-result strong').text('$' + response.data.price);
            }
        });
    }

    $('#exs-estimator').on('change input', 'select, input', updateEstimate);
    updateEstimate();
});

Every time a visitor changes hours, distance, or the checkbox, jQuery fires an AJAX request, WordPress verifies the nonce, recalculates the price on the server (never trust the browser to calculate its own discount), and sends back a fresh number. The result feels instant, like a real app — but the math always happens safely server-side, where you control it.

Step 6: Putting it together

Your plugin folder should look like this:

excavator-services-estimator/
├── excavator-services-estimator.php   (all the PHP above, combined into one file)
└── js/
    └── estimator.js

Zip the folder, upload it via Plugins → Add New → Upload Plugin, activate it, add a few services with hourly rates (Mini excavator, Standard excavator, Demolition rig…), then drop [excavator_estimator] onto your “Get a Quote” page.

Where to take it from here

Once the basic version works, a few upgrades make it feel like a real business tool:

  • Machine-specific fields — bucket size, tonnage class, or fuel type, each affecting price differently.
  • Site condition multiplier — rocky terrain, restricted access, or urban vs. rural jobs often justify a surcharge; add a dropdown that applies a multiplier.
  • Lead capture — after showing the estimate, ask for a phone number or address before revealing the “final” number, and email yourself the details automatically using wp_mail().
  • Seasonal pricing — frozen ground in winter often costs more to dig; a simple date check can bump the rate automatically.

The takeaway

An excavator-services calculator is a great real-world project because in a couple hundred lines of code, you touch nearly every core WordPress plugin concept: custom post types, meta boxes, nonces for security, shortcodes, and AJAX for interactivity. Once this pattern clicks, you can adapt it to almost any service business — landscaping, moving companies, cleaning services, tree removal — because underneath, they’re all the same skeleton with different pricing rules.

Build it once properly, and every future “quote calculator” project becomes a lot less intimidating.