If you’re working with bundled products in Easy Digital Downloads, you’ll notice it’s not easy. It’s actually hard and not performant at all. Making them fast requires custom code and a custom table.

Before we start, we need to understand why we would need this.

Working with Easy Digital Download Bundles is hard

Why is working with bundled products hard?

Easy Digital Downloads provides you with a useful function edd_is_bundled_product. But that’s it.

With that function, you can find out if a product is a bundle.

What if you want to show all products that are in a bundle from another product that is in the same bundle?

Let’s say, we have 3 albums that we can buy separately. They are also bundled in an album “Top Hits 2022”.

And to increase conversions, when a visitor checks one album, we want to show a “Get these albums bundled together” and display information about the other 2 albums as well.

Well, tough luck.

What you’d need to do is to fetch all products that are bundles using postmeta and then find which of those bundles contain our album.

I’ve encountered such when I worked for a client that wanted to bundle different templates together. Example: “Laywer Template” where each template is a different one (About Page, Services Page) and they all are bundled together.

So, when when the template “About Page” is viewed, we needed to show a CTA with “This product is bundled in Laywer Templates. Get it for $$”.

Let’s now learn how to do it.

Plugin Files

Let’s first create our plugin which will contain the code. Create a plugin folder edd-bundle-functions.

Then, create a file with the same name; edd-bundle-functions.php. Then, inside the same folder add this:

  • includes/class-admin.php
  • includes/class-installer.php
  • includes/class-bundles.php

Be aware, I have not namespaced this code nor did I give them unique names. So, either create unique class names and such or namespace it yourself.

If you’re interested in using namespaces in WordPress plugins, check my article: How to use PHP Namespaces in WordPress Plugins.

First, let’s prepare our initial plugin file edd-bundle-functions.php.

Do not activate it as you’ll get errors now.

Creating Easy Digital Downloads Bundles Table

To have a fast query when checking if a product is part of a bundle, we need to have a custom table.

This custom table needs to have a bundle_id and a product_id.

The bundle_id will be the product ID that is a bundle.

Add this code inside of the class-installer.php file.

Here, we are adding the code that will check if it was installed already or not. And if we change the version of our plugin, it will again update the table.

Our table is called edd_product_bundles, prefixed with the site’s $wpdb prefix.

I’ve already written about Installer classes in more detail in my article on Working with Custom Tables in WordPress – Installing and Updating.

Custom Easy Digital Downloads Bundles Wrapper

We need a way to read the table and write to it. Now, we’ll create a wrapper class that will do just that.

All the code below will go into class-bundles.php file.

First, we have a helper method to get the full table name. That way, we don’t have to write it in every other method.

With the method get_bundle_id_from_product, we can check if a product is part of a bundle. This function will either return an ID or null if it did not find anything.

Then, in the method is_product_in_bundle, we utilize the previous method to check if the product is inside of a bundle or not. In case we did get a bundle ID, it means that the product we checked is inside of a bundle.

Lastly, we have a method get_all_by_bundle. This is used to get all product IDs that belong to a bundle.

Now, we also need a method to add data to the table. To register products that are inside of a bundle.

We now have methods to read data and to create add. Last methods will be used to delete data.

With this methods we either delete all records related to a bundle or delete just a specific product ID.

Update Easy Digital Downloads Bundles Data

Let’s now listen to updates in Easy Digital Downloads Bundles so we can sync such data. We will hook into the action edd_save_download.

When this is triggered, we will check if we are saving a bundle. If we are, we will add or remove products from our custom table.

Easy Digital Downloads Bundles have product data saved inside of the meta _edd_bundled_products. We will retrieve such information and then sync it with our custom table.

We get all currently synced products from our custom table and all the newly saved products inside of the meta. If none exist, we skip the rest.

We use the array_diff function in both cases, to find new products and to find removed products. This will return the difference if something doesn’t exist in the other arrays.

For each new product, we add them to our custom table. For each removed product, we remove it with our delete method.

That’s it. With this, we have our table synced everytime a bundle product is being updated or created.

Displaying Products in a Bundle

Now, let’s see an example on how we can use this. Let’s imagine the example I described at the beginning.

We are on an Album 1 product page. We want to show Album 2 and Album 3 as part of a bundle in which Album 1 is as well.

We get the bundle ID first by checking if Album 1 is inside of a bundle. After that, we retrieve IDs of all products inside of a such bundle.

If we have them, we save the IDs in a variable $in_same_pack. Then, we go iterate through them and display a link, image, and title.


Easy Digital Downloads do not make working with bundles easy. But if you have ever worked with custom tables and custom solutions, you can always come up with similar ideas on how to make something better and how to make the client experience enjoyable.

Become a Sponsor

Posted by Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at https://leanpub.com/u/igorbenic.

Leave a reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.