# Bundle Discount for Products Bought Together

> Gives a discount when a set of products is in the cart together, and suggests the missing items with an add-to-cart link when only part of the bundle is there.

- Type: PHP
- Runs: Run everywhere
- Category: [WooCommerce](https://wpide.com/library/category/woocommerce/)
- Requires: WooCommerce
- Tags: woocommerce, bundles, discounts, upsell
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/woo-bundle-together-discount/

## Code

```php
$wpide_bundles = array(
    array(
        'name'     => 'Camera starter kit',
        'products' => array( 101, 102, 103 ), // Product IDs in the bundle.
        'discount' => 15,                     // Amount off when all are in the cart.
    ),
);

$wpide_bundle_status = function ( $bundle ) {
    $in_cart = array();

    foreach ( WC()->cart->get_cart() as $item ) {
        $in_cart[ $item['product_id'] ] = ( $in_cart[ $item['product_id'] ] ?? 0 ) + (int) $item['quantity'];
    }

    $sets    = PHP_INT_MAX;
    $missing = array();

    foreach ( $bundle['products'] as $id ) {
        $qty = $in_cart[ $id ] ?? 0;
        $sets = min( $sets, $qty );

        if ( ! $qty ) {
            $missing[] = $id;
        }
    }

    return array(
        'sets'    => PHP_INT_MAX === $sets ? 0 : $sets,
        'missing' => $missing,
        'partial' => count( $missing ) < count( $bundle['products'] ),
    );
};

add_action( 'woocommerce_cart_calculate_fees', function ( $cart ) use ( $wpide_bundles, $wpide_bundle_status ) {
    if ( is_admin() && ! wp_doing_ajax() ) {
        return;
    }

    foreach ( $wpide_bundles as $bundle ) {
        $status = $wpide_bundle_status( $bundle );

        if ( $status['sets'] > 0 ) {
            $cart->add_fee( $bundle['name'] . ' discount', -$bundle['discount'] * $status['sets'], true );
        }
    }
} );

add_action( 'woocommerce_before_cart', function () use ( $wpide_bundles, $wpide_bundle_status ) {
    foreach ( $wpide_bundles as $bundle ) {
        $status = $wpide_bundle_status( $bundle );

        if ( ! $status['partial'] || ! $status['missing'] ) {
            continue;
        }

        $links = array();

        foreach ( $status['missing'] as $id ) {
            $product = wc_get_product( $id );

            if ( $product && $product->is_purchasable() && $product->is_in_stock() ) {
                $links[] = sprintf( '<a href="%s">%s</a>', esc_url( $product->add_to_cart_url() ), esc_html( $product->get_name() ) );
            }
        }

        if ( $links ) {
            wc_print_notice( sprintf( 'Complete the %1$s and save %2$s: add %3$s.', esc_html( $bundle['name'] ), wc_price( $bundle['discount'] ), implode( ', ', $links ) ), 'notice' );
        }
    }
} );
```

## Notes

Add more entries to $wpide_bundles for more bundles; the discount applies once per complete bundle in the cart.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Bundle Discount for Products Bought Together" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
