I'm using WooCommerce in a marketplace website and I am looking for a solution to disable the "downloadable product" functionality. Mainly I want that it doesn't appear in vendor's backend.
9 Answers
By Claudio Sanches (@claudiosanches): Go to WooCommerce > Settings > Account and clean the downloads endpoint field. This will disable the downloads page.

- 311
- 3
- 2
-
7However, this does not hide the "Downloadable" option when editing a product in wp-admin... – Philipp Jul 31 '17 at 16:07
I got this answer here By Christophvh .
Go to WooCommerce > Settings > Advanced
and remove the entry for Downloads in the Account endpoints section, just leave it Blank. And the menu will not be visible anymore. Just take a look my Attached Image.

- 9,117
- 10
- 52
- 59
function CM_woocommerce_account_menu_items_callback($items) {
unset( $items['downloads'] );
return $items;
}
add_filter('woocommerce_account_menu_items', 'CM_woocommerce_account_menu_items_callback', 10, 1);
Used this in place of the above

- 363
- 2
- 8
-
6+1. This is the correct answer, DON'T modify the plugin, you'll end up patching the plugin at every update, instead use the available filters as shown in this answer! – jnhghy - Alexandru Jantea Jan 06 '17 at 10:11
-
1Rather than change in core file it is better to use supportive hook for any action/filter. – Ashish Patel Feb 02 '17 at 05:59
This code worked for me. I got it from the Woocommerce Support. https://wordpress.org/support/topic/remove-virtual-downloadable-products-selection/
function my_remove_product_type_options( $options ) {
// uncomment this if you want to remove virtual too.
// if ( isset( $options['virtual'] ) ) {
// unset( $options['virtual'] );
// }
if ( isset( $options['downloadable'] ) ) {
unset( $options['downloadable'] );
}
return $options;
}
add_filter( 'product_type_options', 'my_remove_product_type_options' );

- 894
- 1
- 10
- 14
Not sure if I understood it correctly but if you are willing to remove "Downloads" navigation option from the "My Account" page then continue reading :)
- Create Child Theme to your currently used theme. If you are not well known what it is read this: https://codex.wordpress.org/Child_Themes
- Now copy navigation.php from ...\wp-content\plugins\woocommerce\templates\myaccount\ to the Child Theme folder ...\wp-content\themes\yourtheme-child\woocommerce\myaccount\
- Open navigation.php in your Child theme folder. Find line with function wc_get_account_menu_items() and rename the function to for example wc_get_account_menu_items_custom()
Open functions.php in your Child theme folder. Paste inside the file below function. Save the file and that's all. Now the "My Account" page is without "Downloads" navigation option.
function wc_get_account_menu_items_custom() { $endpoints = array( 'orders' => get_option( 'woocommerce_myaccount_orders_endpoint', 'orders' ), 'edit-address' => get_option( 'woocommerce_myaccount_edit_address_endpoint', 'edit-address' ), 'payment-methods' => get_option( 'woocommerce_myaccount_payment_methods_endpoint', 'payment-methods' ), 'edit-account' => get_option( 'woocommerce_myaccount_edit_account_endpoint', 'edit-account' ), 'customer-logout' => get_option( 'woocommerce_logout_endpoint', 'customer-logout' ), ); $items = array( 'dashboard' => __( 'Dashboard', 'woocommerce' ), 'orders' => __( 'Orders', 'woocommerce' ), 'edit-address' => __( 'Addresses', 'woocommerce' ), 'payment-methods' => __( 'Payment Methods', 'woocommerce' ), 'edit-account' => __( 'Account Details', 'woocommerce' ), 'customer-logout' => __( 'Logout', 'woocommerce' ), ); // Remove missing endpoints. foreach ( $endpoints as $endpoint_id => $endpoint ) { if ( empty( $endpoint ) ) { unset( $items[ $endpoint_id ] ); } } // Check if payment gateways support add new payment methods. if ( isset( $items['payment-methods'] ) ) { $support_payment_methods = false; foreach ( WC()->payment_gateways->get_available_payment_gateways() as $gateway ) { if ( $gateway->supports( 'add_payment_method' ) || $gateway->supports( 'tokenization' ) ) { $support_payment_methods = true; break; } } if ( ! $support_payment_methods ) { unset( $items['payment-methods'] ); } } return apply_filters( 'woocommerce_account_menu_items_custom', $items ); }
Note: This is edited original WooCommerce function. There are just deleted array fields mentioning "Downloads" option. Hope this helps.

- 11
- 3
Ok so based on all of the answers above, I've put together an "all-in-one" solution which disables:
- The download endpoint.
- The checkbox options from the admin product editor.
- The dropdown options from Product Type Filter.
- The downloads metabox from orders.
File: class-disablewoocommerceproducttypes.php
class DisableWooCommerceProductTypes {
/**
* @var array Product types in this property will be disabled.
*/
public $disabled = [
'virtual',
'downloadable'
];
/**
* @var array WooCommerce uses different references for the same product types.
*/
private $aliases = [
'downloadable' => [ 'downloads' ]
];
/**
* @var int The priority of these overrides.
*/
public $priority = PHP_INT_MAX;
/**
* @var null|string|array $product_types Accepts a string or array of 'virtual' and/or 'downloadable' product types.
*/
public function __construct( $product_types = null ) {
if ( $product_types ) {
$this->disabled = (array)$product_types;
}
add_filter( 'product_type_options', [ $this, 'disable_admin_options' ], $this->priority );
add_filter( 'woocommerce_account_menu_items', [ $this, 'disable_frontend_nav_items' ], $this->priority );
add_filter( 'add_meta_boxes', [ $this, 'disable_admin_metabox' ], $this->priority );
add_filter( 'woocommerce_products_admin_list_table_filters', [ $this, 'disable_admin_filters' ], $this->priority );
// Disable the downloads endpoint
if ( $this->is_disabled( 'downloadable' ) ) {
add_filter( 'default_option_woocommerce_myaccount_downloads_endpoint', '__return_null' );
add_filter( 'option_woocommerce_myaccount_downloads_endpoint', '__return_null' );
}
}
/**
* Quickly check if a product type is disabled. Returns primary key if $type is an alias and disabled.
*
* @param string $type
* @param bool $aliases Check for aliases.
* @return bool|string
*/
private function is_disabled( string $type, bool $aliases = true ) {
$basic_check = in_array( $type, $this->disabled );
if ( $aliases && !$basic_check ) {
foreach ( $this->aliases as $_type => $_aliases ) {
if ( in_array( $type, $_aliases ) && $this->is_disabled( $_type, false ) ) {
return $_type;
}
}
}
return $basic_check;
}
/**
* Remove product type checkboxes from product editor.
*
* @param array $types
* @return array
*/
public function disable_admin_options( $types ) {
foreach ( $types as $key => $value ) {
if ( $this->is_disabled( $key ) ) {
unset( $types[ $key ] );
}
}
return $types;
}
/**
* Removes product type page from `wc_get_account_menu_items()`
*
* @param array $items
* @return array
*/
public function disable_frontend_nav_items( $items ) {
foreach ( $items as $key => $value ) {
if ( $this->is_disabled( $key ) ) {
unset( $items[ $key ] );
}
}
return $items;
}
/**
* Removes the downloads metabox from orders.
*/
public function disable_admin_metabox() {
if ( $this->is_disabled( 'downloadable' ) ) {
remove_meta_box( 'woocommerce-order-downloads', 'shop_order', 'normal' );
}
}
/**
* Add our admin product table filter modifier.
*
* @param array $filters
* @return array
*/
public function disable_admin_filters( $filters ) {
if ( isset( $filters[ 'product_type' ] ) ) {
$filters[ 'product_type' ] = [ $this, 'disable_product_type_filters' ];
}
return $filters;
}
/**
* Remove disabled product types from the admin products table filters.
*/
public function disable_product_type_filters() {
$current_product_type = isset( $_REQUEST['product_type'] ) ? wc_clean( wp_unslash( $_REQUEST['product_type'] ) ) : false; // WPCS: input var ok, sanitization ok.
$output = '<select name="product_type" id="dropdown_product_type"><option value="">' . esc_html__( 'Filter by product type', 'woocommerce' ) . '</option>';
foreach ( wc_get_product_types() as $value => $label ) {
$output .= '<option value="' . esc_attr( $value ) . '" ';
$output .= selected( $value, $current_product_type, false );
$output .= '>' . esc_html( $label ) . '</option>';
if ( 'simple' === $value ) {
if ( !$this->is_disabled( 'downloadable' ) ) {
$output .= '<option value="downloadable" ';
$output .= selected( 'downloadable', $current_product_type, false );
$output .= '> ' . ( is_rtl() ? '←' : '→' ) . ' ' . esc_html__( 'Downloadable', 'woocommerce' ) . '</option>';
}
if ( !$this->is_disabled( 'virtual' ) ) {
$output .= '<option value="virtual" ';
$output .= selected( 'virtual', $current_product_type, false );
$output .= '> ' . ( is_rtl() ? '←' : '→' ) . ' ' . esc_html__( 'Virtual', 'woocommerce' ) . '</option>';
}
}
}
$output .= '</select>';
echo $output; // WPCS: XSS ok.
}
}
File: functions.php
include_once get_theme_file_path( 'path/to/class-disablewoocommerceproducttypes.php' );
new DisableWooCommerceProductTypes();
By default the above will disable both downloadable
and virtual
product types.
To disable a single product type simply pass the type to the class constructor...
// Example usage for just `downloadable` product type
new DisableWooCommerceProductTypes( 'downloadable' );
// Example usage for just `virtual` product type
new DisableWooCommerceProductTypes( 'virtual' );

- 3,561
- 1
- 21
- 36
There are a couple of extra steps to completely remove the functionality.
Reviewing them all:
as per Osmar Sanches and MD Ashik answers, clear the endpoint on WooCommerce > Settings > Advanced > Downloads
add the filter
product_type_options
as per Maher Aldous answerremove the "Dropdown Options from Product Type Filter" as per this blog post by Misha Rudrasyth:
add_filter( 'woocommerce_products_admin_list_table_filters', function( $filters ) { if( isset( $filters[ 'product_type' ] ) ) { $filters[ 'product_type' ] = 'misha_product_type_callback'; } return $filters; }); function misha_product_type_callback(){ $current_product_type = isset( $_REQUEST['product_type'] ) ? wc_clean( wp_unslash( $_REQUEST['product_type'] ) ) : false; $output = '<select name="product_type" id="dropdown_product_type"><option value="">Filter by product type</option>'; foreach ( wc_get_product_types() as $value => $label ) { $output .= '<option value="' . esc_attr( $value ) . '" '; $output .= selected( $value, $current_product_type, false ); $output .= '>' . esc_html( $label ) . '</option>'; } $output .= '</select>'; echo $output; }
Remove the metabox "Downloadable product permissions" from Orders (edit and new):
add_filter('add_meta_boxes', function() { remove_meta_box('woocommerce-order-downloads', 'shop_order', 'normal'); }, 99 );

- 25,496
- 15
- 91
- 179
CSS fix... no tampering with the functions.
.woocommerce-MyAccount-navigation-link--downloads {
display: none;
}

- 11
- 1
Was having the same problem and just fixed it.
Open this file:
...\www\Your_website_folder\wp-content\plugins\woocommerce\includes\wc_account-functions.php
now search for the wc_get_account_menu_items() function (line 78)
now replace this line (line 91)
'downloads' => __( 'Downloads', 'woocommerce' ),
with this one
/* 'downloads' => __( 'Downloads', 'woocommerce' ),*/
That's it.

- 1
- 3
-
13This answer is wrong. Never modify a plugin's source, it'll just get overwritten when the plugin updates. See the below answer which explains how to properly disable the feature as intended by the plugin. http://stackoverflow.com/a/41988635/3421659 – Andrew Feb 10 '17 at 20:52
-
1Never modify other plugins' or wordpress core code. This way you won't be able to update the plugin, for example. – rodrigobb Oct 31 '19 at 17:05