Blog Sections Open

Building Quantity-Based Cart Discounts with OnSHKcalcTotalPrice

A practical Shopkeeper recipe for progressive discounts based on the total number of items in the cart, not just the quantity of one SKU.

Shopkeeper gives you a useful extension point in OnSHKcalcTotalPrice, but the first examples teams find often solve only the simplest case: discount a single product when its quantity crosses a threshold. the original question pushed the logic further by asking for progressive discounts based on how many items are in the cart overall.

That is a better fit for custom total-price calculation, because the discount rule is about the cart state, not a single line item.

Base pattern

$e = &$modx->Event;
$output = 0;

if ($e->name == 'OnSHKcalcTotalPrice') {
    $discountMap = [2 => 0.05, 3 => 0.10, 4 => 0.15];
    $itemsCount = 0;

    foreach ($purchases as $item) {
        $itemsCount += (int) $item[1];
    }

    $discount = 0;
    foreach ($discountMap as $threshold => $value) {
        if ($itemsCount >= $threshold) {
            $discount = $value;
        }
    }

    foreach ($purchases as $item) {
        $price = round($item[2] * (1 - $discount), 2);
        $output += $item[1] * $price;
    }

    $e->output($output);
}

Why this version is different

The common forum example checks whether one product quantity is greater than a threshold. This version first calculates the total number of units in the cart and then applies the correct discount tier to the full order logic.

That makes it much better for promotions like “5% off from the second item, 10% from the third, 15% from the fourth.”

Newer post

Keeping Child Menus Expanded for the Active Branch in pdoMenu

How to keep submenu wrappers open for the active branch in pdoMenu without hard-coding separate menu trees.

Older post

Fixing phpThumbOf Path Errors in CatalogFill Imports

How to diagnose phpThumbOf path failures when imported image paths from CatalogFill do not resolve correctly.