

Adds a progressive discount based on the shopping cart.
/**
* Snippet Name: Cart Dynamic Discount
* Snippet Author: coding-bunny.com
* Description: Adds a progressive discount based on the shopping cart.
*/
// === ADD DISCOUNT HERE ===
function cbpds_get_discount_tiers() {
return [
50 => 5, // Example: €50 = 5% discount
150 => 10,
250 => 15,
500 => 25
];
}
add_action('woocommerce_cart_calculate_fees', 'cbpds_apply_cart_discount');
function cbpds_apply_cart_discount() {
if (is_admin() && !defined('DOING_AJAX')) return;
if (!WC()->cart) return;
$cart_total = WC()->cart->get_subtotal();
$discount_percentage = cbpds_get_discount_percentage($cart_total);
if ($discount_percentage > 0) {
$discount_amount = ($cart_total * $discount_percentage) / 100;
$discount_label = sprintf('Discount %d%% (-€%.2f)', $discount_percentage, $discount_amount);
WC()->cart->add_fee($discount_label, -$discount_amount);
}
}
function cbpds_get_discount_percentage($total) {
$discount = 0;
foreach (cbpds_get_discount_tiers() as $threshold => $percentage) {
if ($total >= $threshold) {
$discount = $percentage;
}
}
return $discount;
}
add_action('wp_ajax_cbpds_update_progress', 'cbpds_ajax_update_progress');
add_action('wp_ajax_nopriv_cbpds_update_progress', 'cbpds_ajax_update_progress');
function cbpds_ajax_update_progress() {
if (!wp_verify_nonce($_POST['nonce'], 'cbpds_nonce')) {
wp_die('Security check failed');
}
$cart_total = WC()->cart ? WC()->cart->get_subtotal() : 0;
$progress_data = cbpds_calculate_progress($cart_total);
$tiers = cbpds_get_discount_tiers();
ob_start();
?>
<div class="cbpds-minimal-steps">
<?php foreach ($tiers as $tier => $discount):
$is_achieved = $cart_total >= $tier;
$is_current = !$is_achieved && $progress_data['next_tier'] == $tier;
?>
<div class="cbpds-minimal-step <?php echo $is_achieved ? 'achieved' : ($is_current ? 'current' : ''); ?>">
<div class="cbpds-spend-row">
<span class="cbpds-label">Spend</span>
<span class="cbpds-amount">€<?php echo $tier; ?></span>
</div>
<div class="cbpds-discount-row">
<span class="cbpds-label">Discount</span>
<span class="cbpds-percent"><?php echo $discount; ?>%</span>
</div>
<?php if ($is_achieved): ?>
<div class="cbpds-minimal-check">✓</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php if ($progress_data['next_tier']): ?>
<div class="cbpds-minimal-progress">
<div class="cbpds-minimal-bar">
<div class="cbpds-minimal-fill" style="width: <?php echo $progress_data['progress_percentage']; ?>%"></div>
</div>
<div class="cbpds-minimal-text">
<?php if ($progress_data['remaining_amount'] > 0): ?>
€<?php echo number_format($progress_data['remaining_amount'], 2); ?> remaining for <?php echo $tiers[$progress_data['next_tier']]; ?>% discount
<?php endif; ?>
</div>
</div>
<?php else: ?>
<div class="cbpds-minimal-complete">
Maximum discount reached
</div>
<?php endif; ?>
<?php
$html = ob_get_clean();
wp_send_json_success([
'html' => $html,
'cart_total' => $cart_total,
'current_discount' => $progress_data['current_discount']
]);
}
// === ADD HERE WHERE TO SHOW IT ===
add_action('woocommerce_after_add_to_cart_button', 'cbpds_show_minimal_progress_bar', 25);
add_action('woocommerce_before_cart_table', 'cbpds_show_minimal_progress_bar');
add_action('woocommerce_review_order_before_payment', 'cbpds_show_minimal_progress_bar');
function cbpds_show_minimal_progress_bar() {
$cart_total = WC()->cart ? WC()->cart->get_subtotal() : 0;
$progress_data = cbpds_calculate_progress($cart_total);
$tiers = cbpds_get_discount_tiers();
?>
<div class="cbpds-minimal-container" id="cbpds-progress-container">
<div class="cbpds-minimal-steps">
<?php foreach ($tiers as $tier => $discount):
$is_achieved = $cart_total >= $tier;
$is_current = !$is_achieved && $progress_data['next_tier'] == $tier;
?>
<div class="cbpds-minimal-step <?php echo $is_achieved ? 'achieved' : ($is_current ? 'current' : ''); ?>">
<div class="cbpds-spend-row">
<span class="cbpds-label">Spend</span>
<span class="cbpds-amount">€<?php echo $tier; ?></span>
</div>
<div class="cbpds-discount-row">
<span class="cbpds-label">Discount</span>
<span class="cbpds-percent"><?php echo $discount; ?>%</span>
</div>
<?php if ($is_achieved): ?>
<div class="cbpds-minimal-check">✓</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php if ($progress_data['next_tier']): ?>
<div class="cbpds-minimal-progress">
<div class="cbpds-minimal-bar">
<div class="cbpds-minimal-fill" style="width: <?php echo $progress_data['progress_percentage']; ?>%"></div>
</div>
<div class="cbpds-minimal-text">
<?php if ($progress_data['remaining_amount'] > 0): ?>
€<?php echo number_format($progress_data['remaining_amount'], 2); ?> remaining for <?php echo $tiers[$progress_data['next_tier']]; ?>% discount
<?php endif; ?>
</div>
</div>
<?php else: ?>
<div class="cbpds-minimal-complete">
Maximum discount reached
</div>
<?php endif; ?>
</div>
<style>
.cbpds-minimal-container {
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 6px;
padding: 16px;
margin: 16px 0;
font-size: 14px;
color: #495057;
}
.cbpds-minimal-steps {
display: flex;
gap: 8px;
margin-bottom: 12px;
flex-wrap: wrap;
}
.cbpds-minimal-step {
flex: 1;
min-width: 100px;
text-align: center;
padding: 12px 8px;
border-radius: 4px;
position: relative;
transition: all 0.2s ease;
display: flex;
flex-direction: column;
gap: 6px;
}
.cbpds-minimal-step:not(.achieved):not(.current) {
background: #f8f9fa;
border: 1px solid #dee2e6;
color: #6c757d;
}
.cbpds-minimal-step.current {
background: #fff3cd;
border: 1px solid #ffeaa7;
color: #856404;
}
.cbpds-minimal-step.achieved {
background: #d4edda;
border: 1px solid #c3e6cb;
color: #155724;
}
.cbpds-spend-row,
.cbpds-discount-row {
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.cbpds-label {
font-size: 10px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
opacity: 0.7;
white-space: nowrap;
}
.cbpds-amount,
.cbpds-percent {
font-size: 12px;
font-weight: 700;
}
.cbpds-minimal-check {
position: absolute;
top: -2px;
right: -2px;
background: #28a745;
color: white;
width: 16px;
height: 16px;
border-radius: 50%;
font-size: 10px;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
}
.cbpds-minimal-progress {
margin-top: 12px;
}
.cbpds-minimal-bar {
background: #e9ecef;
border-radius: 3px;
height: 6px;
overflow: hidden;
margin-bottom: 6px;
}
.cbpds-minimal-fill {
background: #29a745;
height: 100%;
border-radius: 3px;
transition: width 0.3s ease;
}
.cbpds-minimal-text {
text-align: center;
font-size: 12px;
color: #6c757d;
font-weight: 500;
}
.cbpds-minimal-complete {
background: #d4edda;
color: #155724;
padding: 10px 12px;
border-radius: 4px;
text-align: center;
font-weight: 500;
border: 1px solid #c3e6cb;
font-size: 13px;
}
@media (max-width: 768px) {
.cbpds-minimal-container {
padding: 12px;
font-size: 13px;
}
.cbpds-minimal-steps {
flex-direction: column;
gap: 6px;
}
.cbpds-minimal-step {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 12px;
text-align: left;
min-width: auto;
gap: 8px;
}
.cbpds-spend-row,
.cbpds-discount-row {
justify-content: flex-start;
}
.cbpds-spend-row {
order: 1;
}
.cbpds-discount-row {
order: 2;
}
.cbpds-minimal-check {
position: static;
order: 3;
margin-left: auto;
}
}
@media (max-width: 480px) {
.cbpds-minimal-container {
margin: 12px 0;
padding: 10px;
}
.cbpds-amount {
font-size: 12px;
}
.cbpds-percent {
font-size: 14px;
}
.cbpds-label {
font-size: 9px;
}
}
</style>
<script>
jQuery(document).ready(function($) {
var cbpds_nonce = '<?php echo wp_create_nonce('cbpds_nonce'); ?>';
var cbpds_ajax_url = '<?php echo admin_url('admin-ajax.php'); ?>';
var cbpds_updating = false;
function cbpds_update_progress() {
if (cbpds_updating) return;
cbpds_updating = true;
var $container = $('#cbpds-progress-container');
$.post(cbpds_ajax_url, {
action: 'cbpds_update_progress',
nonce: cbpds_nonce
})
.done(function(response) {
if (response.success) {
$container.html(response.data.html);
cbpds_bind_hover_events();
}
})
.fail(function() {
console.log('CBPDS: Error updating progress bar');
})
.always(function() {
cbpds_updating = false;
});
}
function cbpds_bind_hover_events() {
$('.cbpds-minimal-step').off('mouseenter mouseleave').hover(
function() {
if (!$(this).hasClass('achieved')) {
$(this).css('transform', 'translateY(-1px)');
}
},
function() {
$(this).css('transform', 'translateY(0)');
}
);
}
cbpds_bind_hover_events();
$(document.body).on('added_to_cart removed_from_cart updated_cart_totals updated_checkout', function() {
setTimeout(cbpds_update_progress, 100);
});
$(document.body).on('wc_fragments_refreshed wc_fragments_loaded', function() {
setTimeout(cbpds_update_progress, 100);
});
$(document).on('change', '.qty', function() {
setTimeout(cbpds_update_progress, 500);
});
$('form.cart').on('submit', function() {
setTimeout(cbpds_update_progress, 1000);
});
if ($('body').hasClass('woocommerce-cart') || $('body').hasClass('woocommerce-checkout')) {
setInterval(cbpds_update_progress, 3000);
}
});
</script>
<?php
}
function cbpds_calculate_progress($total) {
$tiers = cbpds_get_discount_tiers();
$tier_keys = array_keys($tiers);
$current_tier = 0;
$current_discount = 0;
$next_tier = $tier_keys[0];
$progress_percentage = 0;
foreach ($tier_keys as $tier) {
if ($total >= $tier) {
$current_tier = $tier;
$current_discount = $tiers[$tier];
}
}
foreach ($tier_keys as $tier) {
if ($total < $tier) {
$next_tier = $tier;
break;
}
}
if ($total >= max($tier_keys)) {
$progress_percentage = 100;
$next_tier = null;
} else {
$previous_tier = 0;
foreach ($tier_keys as $tier) {
if ($tier < $next_tier) {
$previous_tier = $tier;
}
}
if ($next_tier > $previous_tier) {
$progress_percentage = (($total - $previous_tier) / ($next_tier - $previous_tier)) * 100;
}
}
return [
'current_tier' => $current_tier,
'current_discount' => $current_discount,
'next_tier' => $next_tier,
'progress_percentage' => min(100, max(0, $progress_percentage)),
'remaining_amount' => $next_tier ? max(0, $next_tier - $total) : 0
];
}
?>
Choose one of the following options:
Powered by CodingBunny