Easy Digital Download Confusion

Once a customer has purchased more than one download from your Easy Digital Downloads (EDD) e-commerce shop, and especially if they have renewed their purchases year-over-year, there will be a source of confusion for them in their account pages, if/when they go to fetch a download file.

The list of downloads will include duplicate links in table rows, and the customer might not know which link to click to get the latest file. In fact, all the links with the same title are the same download. But how are they to know that? Why should they have to suss all that out, when it should just be a quick grab-n-go?

I get asked about this repeatedly, so I decided to code in a fix. I initially thought I’d solve this problem using the ‘edd_before_download_history‘ action hook in the ‘easy-digital-downloads/templates/history-downloads‘ template file, but that action hook doesn’t include the $orders variable, and that’s a shame because I can’t conditionally show a message if the customer has more than one download, e.g.

if ( count( $orders ) > 1 ) {
    // Then show an awkward message, like:
    echo '

awkward message explaining how all the links below with the same title are actually to the same file.

'; }

I’d have to put my awkward message in the template if I wanted to be at least minimally awkward about my message (I mean, only showing it to customers with more than one order). Sigh.

And so I ended up uploading a template override after all, which I try to avoid because updating templates every time EDD updates the parent templates is a pain. That said, I’ve updated EDD and WooCommerce templates so many hundreds of times I could almost do it with my eyes closed. That doesn’t mean it’s fun. I wish EDD would include some $variables in more of its action hooks.

Here’s what I did. I added some logic such that the $orders variable contains orders by DATE, in descending (DESC) order. That way, when the orders are looped through in the template, as they already are, I can collect item product IDs in an array. If that item product ID is already shown, I won’t show it again:

First, add two lines after line 31, to add to the edd_get_order query args:

'type'           => 'sale',
'status__not_in' => array( 'trash', 'refunded', 'abandoned' ),
'order'          => 'DESC', // add this line
'orderby'        => 'date_created', // add this line, too!

Next, add one line after line 51, so it looks more like this:

$prod_ids = [];
foreach ( $orders as $order ) :

Finally, add 6 lines of code after line 53, so it looks like this:

foreach ( $order->get_items_with_bundles() as $key => $item ) :

    if ( in_array( $item->product_id, $prod_ids ) ) {
        continue; // download link is already shown
    if ( $item->is_deliverable() ) {
        $prod_ids[] = $item->product_id;

Makes it much easier for a customer to just get their download without guesswork, which is what EDD is all about, right?

Prorated Software Upgrade Crack

It’s amazing how some customers’ behavior can highlight innovative ways of saving money.

It never occurred to me until I started selling software, and managing annual software licenses, that there’s a pretty simple way to save money when trying to renew software licenses, without a coupon. Many businesses pro-rate license upgrades, and prorate them by date, such that the closer you come to expiration, the cheaper an upgrade gets. So a frugal move to make is to wait until just days before your software license expires, then upgrade to the next level up… for a tiny fraction of what it would cost to renew the lesser license currently held. VoilĂ  – we now have better access for another year, for cheaper than a straight renewal!

While this is pretty cool for the customer, this is a big problem for software sellers that causes significant loss of income. In particular it’s a weakness for some Easy Digital Downloads (EDD) admins using EDD’s Software Licensing extension. I wrote a PHP code snippet for use with EDD Software Licensing. It locks out prorated upgrades after a certain number of months of license ownership (3 months):

 * Customers lose prorate upgrades if less than 9 months left on license
 * @param float|int $prorated Calculated prorated price
 * @param int $license_id ID of license being upgraded
 * @param float|int $old_price Price of the original license being upgraded
 * @param float|int $new_price Price of the new license level
 * @return float|int
function my_get_pro_rated_upgrade_cost( $prorated, $license_id, $old_price, $new_price ) {

    if ( ! class_exists( 'EDD_Software_Licensing' ) ) {
        require_once WP_PLUGIN_DIR . '/edd-software-licensing/includes/classes/class-edd-software-licensing.php';
    // Get license object from license ID
    $license = EDD_Software_Licensing()->get_license( $license_id );
    if ( 'lifetime' === $license->expiration ) {
        return $prorated; // why lifetime licenses should get caught in this hook is beyond me
    // 23670000 is the number of seconds in 9 months, change ad lib
    if ( ! is_object( $license ) || $license->is_expired() || ( ! $license->is_expired() && ( (int) $license->expiration - time() < 23670000 ) ) ) {
        return $new_price; 
    return $prorated;

add_filter( 'edd_sl_get_pro_rated_upgrade_cost', 'my_get_pro_rated_upgrade_cost', 11, 4 );

Should a customer decide they need to upgrade the software, they need to do it soon after purchase, not as a way to obtain a deep discount. In the case of this EDD add-on snippet below, they need to upgrade within 3 months, otherwise prorating is not offered. If they try to upgrade an expired license, prorating is not offered.

I hope this helps you. If it does please reach out to say hi!