How to Customize Woocommerce Orders page? (20 hacks)

In this post I’ll show you how to customize Woocommerce orders page with the help of simple code snippets. Now, in order to make this work add your chosen snippets shown to your child theme’s functions.php file or better yet, use a snippet manager like Code Snippets or WpCodeBox (my favorite). If you’re interested, then grab WPCodeBox with a nice 20% discount here (SAVE 20% Coupon WPSH20).

Video: How to Customize Woocommerce Orders page?

In case you have a hard time using or following snippets shown below, take a look at the video. In it I’ll show you how to use them.

How to add an Woocommerce order number search field to the WP Admin top bar?

At the moment you have to go to the Woocommerce >> Orders page in order to search orders. With the help of this hack you can do it directly from your WordPress admin bar (see screenshot)

How to add an Woocommerce order number search field to the WP Admin top bar?
// Add an Woocommerce order number search field to the WP Admin top bar
add_action('wp_before_admin_bar_render', function() {
  if(!current_user_can('administrator')) {
    return;
  }
  
  global $wp_admin_bar;

  $search_query = '';
  if (!empty($_GET['post_type']) && $_GET['post_type'] == 'shop_order' ) {

    $search_query = !empty($_GET['s']) ? $_GET['s'] : '';

    if($search_query) {
        $order = get_post(intval($search_query));

        if($order) {
            wp_redirect(get_edit_post_link($order->ID, ''));
            exit;
        }
    }
  }

  $wp_admin_bar->add_menu(array(
    'id' => 'admin_bar_shop_order_form',
    'title' => '<form method="get" action="'.get_site_url().'/wp-admin/edit.php?post_type=shop_order">
      <input name="s" type="text" placeholder="Order ID" value="' . esc_attr($search_query) . '" style="width:100px; height: 25px; padding-left: 5px;">
      <button  class="button button-primary" style="height: 25px; padding: 0px 10px 0px 10px; margin-left: -5px;">Check this order</button>
      <input name="post_type" value="shop_order" type="hidden">
    </form>'
  ));
},100
);

How to send a custom reminder email for WooCommerce On-Hold orders after two days?

By default, Woocommerce doesn’t send out reminder emails for the on-hold emails. With the help of this snippet here you can send a custom reminder email for WooCommerce On-Hold orders after two days of order completion.

NB! Pay attention to the line 8. In it, you can change the remider delay.

// Send a custom reminder email for WooCommerce On-Hold orders after two days of order completion

add_action( 'restrict_manage_posts', 'wpsh_payment_reminder' );
function wpsh_payment_reminder() {
    global $pagenow, $post_type;

    if( 'shop_order' === $post_type && 'edit.php' === $pagenow
        && get_option( 'unpaid_orders_reminder_daily_process' ) < time() ) :

    $days_delay = 2; // 24 hours
    $one_day    = 24 * 60 * 60;
    $today      = strtotime( date('Y-m-d') );

    $unpaid_orders = (array) wc_get_orders( array(
        'limit'        => -1,
        'status'       => 'on-hold',
        'date_created' => '<' . ( $today - ($days_delay * $one_day) ),
    ) );

    if ( sizeof($unpaid_orders) > 0 ) {
        $reminder_text = __("Payment reminder email sent to customer $today.", "woocommerce");

        foreach ( $unpaid_orders as $order ) {
            $order->update_meta_data( '_send_on_hold', true );
            $order->update_status( 'reminder', $reminder_text );

            $wc_emails = WC()->mailer()->get_emails(); // Get all WC_emails objects instances
            $wc_emails['WC_Email_Customer_On_Hold_Order']->trigger( $order->get_id() ); // Send email
        }
    }
    update_option( 'unpaid_orders_reminder_daily_process', $today + $one_day );

    endif;
}

add_action ( 'woocommerce_email_order_details', 'wpsh_payment_reminder_notification', 5, 4 );
function wpsh_payment_reminder_notification( $order, $sent_to_admin, $plain_text, $email ){
    if ( 'customer_on_hold_order' == $email->id && $order->get_meta('_send_on_hold') ){
        $order_id     = $order->get_id();
        $order_link   = wc_get_page_permalink('myaccount').'view-order/'.$order_id.'/';
        $order_number = $order->get_order_number();

        echo '<h2>'.__("Do not forget about your order.").'</h2>
        <p>'.sprintf( __("CUSTOM MESSAGE HERE… %s"), 
            '<a href="'.$order_link.'">'.__("Your My account order #").$order_number.'<a>'
        ) .'</p>';

        $order->delete_meta_data('_send_on_hold');
        $order->save();
    }
}

How to create custom order status for Woocommerce?

Now let’s take a look at how to create custom order status for Woocommerce. With the help of this snippet I’m going to create a custom status called “In-progress” that is displayed on both backend and front-end order pages.

// Add custom Woocommerce order status
function register_in_progress_order_status() {
    register_post_status( 'wc-invoiced', array(
            'label' => _x( 'In-progress', 'Order Status', 'woocommerce' ),
            'public' => true,
            'exclude_from_search' => false,
            'show_in_all_admin_list' => true,
            'show_in_admin_status_list' => true,
            'label_count' => _n_noop( 'In-progress <span class="count">(%s)</span>', 'In-progress <span class="count">(%s)</span>', 'woocommerce' )
        )
    );
}

add_action( 'init', 'register_in_progress_order_status' );

function my_invoiced_order_status( $order_statuses ){
    $order_statuses['wc-invoiced'] = _x( 'In-progress', 'Order Status', 'woocommerce' );
    return $order_statuses;

}
add_filter( 'wc_order_statuses', 'my_invoiced_order_status' );

function show_in_bulk_actions() {
    global $post_type;

    if( 'shop_order' == $post_type ) {
        ?>
            <script type="text/javascript">
                jQuery(document).ready(function(){
                    jQuery('<option>').val('mark_invoiced').text('<?php _e( 'Change Status to In-progress','woocommerce' ); ?>').appendTo("select[name='action']");
                    jQuery('<option>').val('mark_invoiced').text('<?php _e( 'Change Status to In-progress','woocommerce' ); ?>').appendTo("select[name='action2']");
                });
            </script>
        <?php
    }
}
add_action( 'admin_footer', 'show_in_bulk_actions' );

How to Filter Woocommerce orders by coupons used?

If you would like to know how to filter Woocommerce orders by coupons used, then it’s just a snippet away. That is, use this one here below.

// Filter Woocommerce orders by coupons used
defined( 'ABSPATH' ) or exit;

// fire it up!
add_action( 'plugins_loaded', 'wc_filter_orders_by_coupon' );

 class WC_Filter_Orders_By_Coupon {
	const VERSION = '1.1.0';

	/** @var WC_Filter_Orders_By_Coupon single instance of this plugin */
	protected static $instance;
	public function __construct() {

		// load translations
		add_action( 'init', array( $this, 'load_translation' ) );
		if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {

			// adds the coupon filtering dropdown to the orders page
			add_action( 'restrict_manage_posts', array( $this, 'filter_orders_by_coupon_used' ) );

			// makes coupons filterable
			add_filter( 'posts_join',  array( $this, 'add_order_items_join' ) );
			add_filter( 'posts_where', array( $this, 'add_filterable_where' ) );
		}
	}

	public function filter_orders_by_coupon_used() {
		global $typenow;

		if ( 'shop_order' === $typenow ) {

			$args = array(
				'posts_per_page' => - 1,
				'orderby'        => 'title',
				'order'          => 'asc',
				'post_type'      => 'shop_coupon',
				'post_status'    => 'publish',
			);

			$coupons = get_posts( $args );

			if ( ! empty( $coupons ) ) : ?>

				<select name="_coupons_used" id="dropdown_coupons_used">
					<option value="">
						<?php esc_html_e( 'Filter by coupon used', 'wc-filter-orders' ); ?>
					</option>
					<?php foreach ( $coupons as $coupon ) : ?>
						<option value="<?php echo esc_attr( $coupon->post_title ); ?>" <?php echo esc_attr( isset( $_GET['_coupons_used'] ) ? selected( $coupon->post_title, $_GET['_coupons_used'], false ) : '' ); ?>>
							<?php echo esc_html( $coupon->post_title ); ?>
						</option>
					<?php endforeach; ?>
				</select>
			<?php endif;
		}
	}

	public function add_order_items_join( $join ) {
		global $typenow, $wpdb;

		if ( 'shop_order' === $typenow && isset( $_GET['_coupons_used'] ) && ! empty( $_GET['_coupons_used'] ) ) {

			$join .= "LEFT JOIN {$wpdb->prefix}woocommerce_order_items woi ON {$wpdb->posts}.ID = woi.order_id";
		}

		return $join;
	}

	public function add_filterable_where( $where ) {
		global $typenow, $wpdb;

		if ( 'shop_order' === $typenow && isset( $_GET['_coupons_used'] ) && ! empty( $_GET['_coupons_used'] ) ) {

			// Main WHERE query part
			$where .= $wpdb->prepare( " AND woi.order_item_type='coupon' AND woi.order_item_name='%s'", wc_clean( $_GET['_coupons_used'] ) );
		}

		return $where;
	}

	public function load_translation() {
		// localization
		load_plugin_textdomain( 'wc-filter-orders', false, dirname( plugin_basename( __FILE__ ) ) . '/i18n/languages' );
	}

	public static function instance() {
		if ( is_null( self::$instance ) ) {
		 	self::$instance = new self();
		}
		return self::$instance;
	}

	public function __clone() {
		/* translators: Placeholders: %s - plugin name */
		_doing_it_wrong( __FUNCTION__, sprintf( esc_html__( 'You cannot clone instances of %s.', 'wc-filter-orders' ), 'Filter WC Orders by Coupon' ), '1.1.0' );
	}

	public function __wakeup() {
		/* translators: Placeholders: %s - plugin name */
		_doing_it_wrong( __FUNCTION__, sprintf( esc_html__( 'You cannot unserialize instances of %s.', 'wc-filter-orders' ), 'Filter WC Orders by Coupon' ), '1.1.0' );
	}
}

function wc_filter_orders_by_coupon() {
	return WC_Filter_Orders_By_Coupon::instance();
}

How to filter WooCommerce orders by payment method?

Now let’s see how to filter WooCommerce orders by payment method. Just use this snippet here below.

// Filter Woocommerce orders by payment method
defined( 'ABSPATH' ) or exit;

// fire it up!
add_action( 'plugins_loaded', 'wc_filter_orders_by_payment' );

class WC_Filter_Orders_By_Payment {

	const VERSION = '1.0.0';

	/** @var WC_Filter_Orders_By_Payment single instance of this plugin */
	protected static $instance;

	public function __construct() {

		if ( is_admin() ) {

			// add bulk order filter for exported / non-exported orders
			add_action( 'restrict_manage_posts', array( $this, 'filter_orders_by_payment_method') , 20 );
			add_filter( 'request',               array( $this, 'filter_orders_by_payment_method_query' ) );		
		}
	}

	public function filter_orders_by_payment_method() {
		global $typenow;

		if ( 'shop_order' === $typenow ) {

			// get all payment methods, even inactive ones
			$gateways = WC()->payment_gateways->payment_gateways();

			?>
			<select name="_shop_order_payment_method" id="dropdown_shop_order_payment_method">
				<option value="">
					<?php esc_html_e( 'All Payment Methods', 'wc-filter-orders-by-payment' ); ?>
				</option>

				<?php foreach ( $gateways as $id => $gateway ) : ?>
				<option value="<?php echo esc_attr( $id ); ?>" <?php echo esc_attr( isset( $_GET['_shop_order_payment_method'] ) ? selected( $id, $_GET['_shop_order_payment_method'], false ) : '' ); ?>>
					<?php echo esc_html( $gateway->get_method_title() ); ?>
				</option>
				<?php endforeach; ?>
			</select>
			<?php
		}
	}
	public function filter_orders_by_payment_method_query( $vars ) {
		global $typenow;
		if ( 'shop_order' === $typenow && isset( $_GET['_shop_order_payment_method'] ) && ! empty( $_GET['_shop_order_payment_method'] ) ) {

			$vars['meta_key']   = '_payment_method';
			$vars['meta_value'] = wc_clean( $_GET['_shop_order_payment_method'] );
		}
		return $vars;
	}
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}
}

function wc_filter_orders_by_payment() {
    return WC_Filter_Orders_By_Payment::instance();
}

How to filter Woocommerce orders by user role?

Next, let’s filter Woocommerce orders by user role. The end result is the one you see on the screenshot here below.

How to Customize Woocommerce Orders page?
// Filter Woocommerce orders by user role

function wpsh_user_role_filter() {

	global $typenow, $wp_query;

	if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ) ) ) {
		$user_role	= '';

		// Get all user roles
		$user_roles = array( 'guest' => 'Guest' );
		foreach ( get_editable_roles() as $key => $values ) {
			$user_roles[ $key ] = $values['name'];
		}

		// Set a selected user role
		if ( ! empty( $_GET['_user_role'] ) ) {
			$user_role	= sanitize_text_field( $_GET['_user_role'] );
		}

		// Display drop down
		?><select name='_user_role'>
			<option value=''><?php _e( 'Select a user role', 'woocommerce' ); ?></option><?php
			foreach ( $user_roles as $key => $value ) :
				?><option <?php selected( $user_role, $key ); ?> value='<?php echo $key; ?>'><?php echo $value; ?></option><?php
			endforeach;
		?></select><?php
	}

}
add_action( 'restrict_manage_posts', 'wpsh_user_role_filter' );

function wpsh_user_role_filter_where( $query ) {

	if ( ! $query->is_main_query() || empty( $_GET['_user_role'] ) || $_GET['post_type'] !== 'shop_order' ) {
		return;
	}

	if ( $_GET['_user_role'] != 'guest' ) {
		$ids = get_users( array( 'role' => sanitize_text_field( $_GET['_user_role'] ), 'fields' => 'ID' ) );
		$ids = array_map( 'absint', $ids );
	} else {
		$ids = array( 0 );
	}

	$query->set( 'meta_query', array(
		array(
			'key' => '_customer_user',
			'compare' => 'IN',
			'value' => $ids,
		)
	) );

	if ( empty( $ids ) ) {
		$query->set( 'posts_per_page', 0 );
	}
}
add_filter( 'pre_get_posts', 'wpsh_user_role_filter_where' );

How to display used coupons on WooCommerce admin orders list?

If you would like to display used coupons on WooCommerce admin orders list then use this snippet here below. If no coupons is used then “No coupons used” is displayed. See the screenshot above.

// Display used coupons on WooCommerce admin orders list
add_filter( 'manage_edit-shop_order_columns', 'woo_customer_order_coupon_column_for_orders' );
function woo_customer_order_coupon_column_for_orders( $columns ) {
    $new_columns = array();

    foreach ( $columns as $column_key => $column_label ) {
        if ( 'order_total' === $column_key ) {
            $new_columns['order_coupons'] = __('Coupons', 'woocommerce');
        }

        $new_columns[$column_key] = $column_label;
    }
    return $new_columns;
}

add_action( 'manage_shop_order_posts_custom_column' , 'woo_display_customer_order_coupon_in_column_for_orders' );
function woo_display_customer_order_coupon_in_column_for_orders( $column ) {
    global $the_order, $post;
    if( $column  == 'order_coupons' ) {
        if( $coupons = $the_order->get_coupon_codes() ) {
            echo implode(', ', $coupons) . ' ('.count($coupons).')';
        } else {
            echo '<small><em>'. __('No coupon used') . '</em></small>';
        }
    }
}

How to display used coupons on Woocommerce order preview template?

With the previous snippet we’re displaying coupons in the Woocommerce admin orders list. Now, with the help of this one here we’re going to display used coupons on Woocommerce order preview template.

// Display used coupons on Woocommerce order preview template

add_filter( 'woocommerce_admin_order_preview_get_order_details', 'wpsh_coupon_in_order_preview', 10, 2 );
function wpsh_coupon_in_order_preview( $data, $order ) {
    // Replace '_custom_meta_key' by the correct postmeta key
    if( $coupons = $order->get_used_coupons() ) {
        $data['coupons_count'] = count($coupons); // <= Store the count in the data array.
        $data['coupons_codes'] = implode(', ', $coupons); // <= Store the count in the data array.
    }
    return $data;
}
// Display coupon in Order preview
add_action( 'woocommerce_admin_order_preview_end', 'wpsh_coupon_in_order_preview_data' );
function wpsh_coupon_in_order_preview_data(){
    // Call the stored value and display it
    echo '<div><strong>' . __('Coupons used') . ' ({{data.coupons_count}})<strong>: {{data.coupons_codes}}</div><br>';
}

How to display customer phone and email in Woocommerce orders table?

Take a look at the screenshot below, and you’ll see that there is a customer phone and email that is displayed in Woocommerce orders table. If you would like to achieve the same result, then use this snippet here below.

Display customer email in Woocommerce orders table
// Display customer phone and email in Woocommerce orders table
add_action( 'manage_shop_order_posts_custom_column' , 'wpsh_phone_and_email_column', 50, 2 );
function wpsh_phone_and_email_column( $column, $post_id ) {
    if ( $column == 'order_number' )
    {
        global $the_order;
 // Display customer phone in Woocommerce orders table
        if( $phone = $the_order->get_billing_phone() ){
            $phone_wp_dashicon = '<span class="dashicons dashicons-phone"></span> ';
            echo '<br><a href="tel:'.$phone.'">' . $phone_wp_dashicon . $phone.'</a></strong>';
        }
	 // Display customer email in Woocommerce orders table
	          if( $email = $the_order->get_billing_email() ){
            echo '<br><strong><a href="mailto:'.$email.'">' . $email . '</a></strong>';
        }
    }
}

How to add custom button to Woocommerce orders page (and products page)

It’s time to add custom button to Woocommerce orders page (and products page). See the screenshot.

Add custom button to Woocommerce orders page
// Add custom button to Woocommerce orders page 
add_action( 'manage_posts_extra_tablenav', 'wpsh_button_on_orders_page', 20, 1 );
function wpsh_button_on_orders_page( $which ) {
    global $typenow;

    if ( 'shop_order' === $typenow && 'top' === $which ) {
        ?>
        <div class="alignright actions custom">
            <button type="submit" name="custom_" style="height:32px;" class="button"  value=""><?php
	  // Change your URL and button text here
                echo __( '<a style="text-decoration: none;" href="/wp-admin/edit.php?post_type=product">
				Go to products &raquo;
				</a>', 'woocommerce' ); ?></button>
        </div>
        <?php
    }
}
// Add custom button to Woocommerce products page 
add_action( 'manage_posts_extra_tablenav', 'wpsh_button_on_products_page', 20, 1 );
function wpsh_button_on_products_page( $which ) {
    global $typenow;

    if ( 'product' === $typenow && 'top' === $which ) {
        ?>
        <div class="alignleft actions custom">
            <button type="submit" name="custom_" style="height:32px;" class="button"  value=""><?php
	  	  // Change your URL and button text here
                echo __( '<a style="text-decoration: none;" href="/wp-admin/edit.php?post_type=shop_order">
				Go to orders &raquo;
				</a>', 'woocommerce' ); ?></button>
        </div>
        <?php
    }
}

How to set default Woocommerce login page to “Orders” page?

This snippet here below will redirect you to the Woocommerce “Orders” after login.

// Set default Woocommerce login page to "Orders" page
add_action( 'load-index.php', 'wpsh_redirect_to_orders' );
function wpsh_redirect_to_orders(){
    wp_redirect( admin_url( 'edit.php?post_type=shop_order' ) );
}
add_filter( 'login_redirect', 'wpsh_redirect_to_orders_dashboard', 9999, 3 );
function wpsh_redirect_to_orders_dashboard( $redirect_to, $request, $user ){
    $redirect_to = admin_url( 'edit.php?post_type=shop_order' );
    return $redirect_to;
}

How to autocomplete Woocommerce processing orders?

Why would you need to autocomplete Woocommerce processing orders? For example, if you’re selling virtual product (Courses etc.) and you would like to add an access to it right after payments.

// Autocomplete Woocommerce processing orders

add_filter( 'woocommerce_payment_complete_order_status', 'processing_orders_autocomplete', 9999 );
function processing_orders_autocomplete() {
   return 'completed';
}

How to autocomplete all Woocommerce orders?

But (just “but) what if you would like to autocomplete all Woocommerce orders? That is evan on-hold orders? If this is the case then use this nippet here below.

// Auto Complete all WooCommerce orders.

add_action( 'woocommerce_thankyou', 'wpsh_complete_all_orders' );
function wpsh_complete_all_orders( $order_id ) { 
    if ( ! $order_id ) {
        return;
    }
    $order = wc_get_order( $order_id );
    $order->update_status( 'completed' );
}

How to add the product image to Woocommerce my account order view at My account page?

What do I mean by that? Take a look at the screenshot below, and you’ll see that there’s an image on Woocommerce orders view at My account page.

Add the product image to Woocommerce my account order view
// Display the product thumbnail in Woocommerce order view pages
add_filter( 'woocommerce_order_item_name', 'wpsh_display_product_image_in_order_item', 20, 3 );
function wpsh_display_product_image_in_order_item( $item_name, $item, $is_visible ) {
    // Targeting view order pages only
    if( is_wc_endpoint_url( 'view-order' ) ) {
        $product   = $item->get_product(); // Get the WC_Product object (from order item)
        $thumbnail = $product->get_image(array( 50, 50)); // Get the product thumbnail (from product object)
        if( $product->get_image_id() > 0 )
            $item_name = '<div class="item-thumbnail">' . $thumbnail . '</div>' . $item_name;
    }
    return $item_name;
}

How to Add Purchased products tab to Woocommerce my account page?

Now let’s add Purchased products tab to Woocommerce my account page (se the screenshot above). This tabb displays your recently purchased products in the separate tabe.

// Add Purchased products tab to Woocommerce my account page

// here we hook the My Account menu links and add our custom one
add_filter( 'woocommerce_account_menu_items', 'wpsh_purchased_products', 40 );
function wpsh_purchased_products( $menu_links ){

// Set 5 in this line to something else if you would like to move the position of the tab
	return array_slice( $menu_links, 0, 5, true )
	+ array( 'purchased-products' => 'Purchased Products' )
	+ array_slice( $menu_links, 2, NULL, true );

}

add_action( 'init', 'wpsh_purchased_products_endpoint' );
function wpsh_purchased_products_endpoint() {
	add_rewrite_endpoint( 'purchased-products', EP_PAGES );
}

// Add purchased porducts as a tab content
add_action( 'woocommerce_account_purchased-products_endpoint', 'wpsh_purchased_products_content' );
function wpsh_purchased_products_content() {

	global $wpdb;

	// Purchased products are sorted by date
	$purchased_products_ids = $wpdb->get_col( 
		$wpdb->prepare(
			"
			SELECT      itemmeta.meta_value
			FROM        " . $wpdb->prefix . "woocommerce_order_itemmeta itemmeta
			INNER JOIN  " . $wpdb->prefix . "woocommerce_order_items items
			            ON itemmeta.order_item_id = items.order_item_id
			INNER JOIN  $wpdb->posts orders
			            ON orders.ID = items.order_id
			INNER JOIN  $wpdb->postmeta ordermeta
			            ON orders.ID = ordermeta.post_id
			WHERE       itemmeta.meta_key = '_product_id'
			            AND ordermeta.meta_key = '_customer_user'
			            AND ordermeta.meta_value = %s
			ORDER BY    orders.post_date DESC
			",
			get_current_user_id()
		)
	);

	// Don’t display duplicate products
	$purchased_products_ids = array_unique( $purchased_products_ids );
	if( ! empty( $purchased_products_ids ) ) {
	  
	 echo '<div class="woocommerce-message">Purchased products</div>';
	  
		$purchased_products = new WP_Query( array(
			'post_type' => 'product',
			'post_status' => 'publish',
			'post__in' => $purchased_products_ids,
			'orderby' => 'post__in',
			'posts_per_page' => -1,
		) );
	
		woocommerce_product_loop_start();

		while ( $purchased_products->have_posts() ) : $purchased_products->the_post();

			wc_get_template_part( 'content', 'product' );

		endwhile;

		woocommerce_product_loop_end();

		woocommerce_reset_loop();
		wp_reset_postdata();

	} else {
	  // Change this text if needed)
		echo 'Unfortunately you have no purchases yet';
	}
}

How to add “Cancel” button to Woocommerce my account page?

Take a look at this screenshot here. As you see, there are two custom buttons (“Cancel” and “Order again” buttons). So, if you would like to add “Cancel” button to Woocommerce my account page, then use this snippet here below.

NB! Pay attention at the line 8. In it you can set the delay in days. Currently it is set to 3 dayst, that is withnin 3 days it’s allowed to cancel the order.

How to add "Cancel" button to Woocommerce my account page?
// Add "Cancel" button to Woocommerce my account page

add_filter( 'woocommerce_valid_order_statuses_for_cancel', 'wpsh_add_cancel_button', 20, 2 );
function wpsh_add_cancel_button( $statuses, $order = '' ){

    // Set HERE the order statuses where you want the cancel button to appear
    $custom_statuses    = array( 'pending', 'processing', 'on-hold', 'failed' );

    // Set HERE the delay (in days)
    $duration = 3; // 3 days

    // UPDATE: Get the order ID and the WC_Order object
    if( ! is_object( $order ) && isset($_GET['order_id']) )
        $order = wc_get_order( absint( $_GET['order_id'] ) );

    $delay = $duration*24*60*60; // (duration in seconds)
    $date_created_time  = strtotime($order->get_date_created()); // Creation date time stamp
    $date_modified_time = strtotime($order->get_date_modified()); // Modified date time stamp
    $now = strtotime("now"); // Now  time stamp

    // Using Creation date time stamp
    if ( ( $date_created_time + $delay ) >= $now ) return $custom_statuses;
    else return $statuses;
}

How to add “Order again” button to Woocommerce my account page?

As menitonet above, we’re goint to add “Order again” button to Woocommerce my account page. Use this snippet here below.

// Add "Order again" button to Woocommerce my account page
add_filter( 'woocommerce_my_account_my_orders_actions', 'wpsh_order_again_button', 9999, 2 );
    
function wpsh_order_again_button( $actions, $order ) {
    if ( $order->has_status( 'completed' ) ) {
        $actions['order-again'] = array(
            'url' => wp_nonce_url( add_query_arg( 'order_again', $order->get_id(), wc_get_cart_url() ), 'woocommerce-order_again' ),
            'name' => __( 'Order again', 'woocommerce' ),
        );
    }
    return $actions;
}

How to set Woocommerce my account page orders display limit?

By default, your Woocommerce “My account” displays a bunch of orders. If you would like to set your own Woocommerce “My account” page orders display limit, then use this snippet. With the help of it we’ll set the display limit to 5 orders.

// Set Woocommerce my account page orders display limit
add_filter( 'woocommerce_my_account_my_orders_query', 'wpsh_my_account_orders_limit', 10, 1 );
function wpsh_my_account_orders_limit( $args ) {
    // Set the post per page
    $args['limit'] = 5;
    return $args;
}

How to display products name and quantity in a new column on Woocommerce “My account” page orders table?

Take a look at the “How to add “Cancel” button to Woocommerce my account page?” section above. There’s a screenshot and you’ll see that in it I display products name and quantity in a new column on Woocommerce “My account” page orders table. So, if you would like to accomplish the same result, just use this snippet here below.

// Display How to display products name and quantity in a new column on Woocommerce "My account" page orders table

add_filter( 'woocommerce_my_account_my_orders_columns', 'wpsh_product_column', 10, 1 );
function wpsh_product_column( $columns ) {
    $new_columns = [];

    foreach ( $columns as $key => $name ) {
        $new_columns[ $key ] = $name;

        if ( 'order-status' === $key ) {
            $new_columns['order-items'] = __( 'Product | Qty', 'woocommerce' );
        }
    }
    return $new_columns;
}

add_action( 'woocommerce_my_account_my_orders_column_order-items', 'wpsh_product_column_content', 10, 1 );
function wpsh_product_column_content( $order ) {
    $details = array();

    foreach( $order->get_items() as $item )
        $details[] = $item->get_name() . '&nbsp;&times;&nbsp;' . $item->get_quantity();

    echo count( $details ) > 0 ? implode( '<br>', $details ) : '&ndash;';
}

How to Link previous WooCommerce guest orders to customer account after registration?

This snippet allows you to link previous WooCommerce guest orders to customer account after registration.

// Link previous WooCommerce guest orders to customer account after registration
function action_woocommerce_created_customer( $customer_id, $new_customer_data, $password_generated ) {
    // Link past orders to this newly created customer
    wc_update_new_customer_past_orders( $customer_id );
}
add_action( 'woocommerce_created_customer', 'action_woocommerce_created_customer', 10, 3 ); 

Woocommerce hacks series

Here are some of my favorite Wordpress tools

Thank you for reading this article. I hope you found it helpful as you build your own websites and e-commerce sites. Here are some tools I use as a Wordpress developer and enthusiast that I hope you’ll also find helpful.

These are affiliate links, so if you do decide to use any of them, I’ll earn a commission and this helps me create these tutorials and make Youtube videos. But in all honesty, these are the exact tools that I use and recommend to everyone, even my friends and family.

Themes: For the last couple of years I have two go-to themes which I use for every kind of projects. Those two themes are Blocksy theme and Kadence Theme. On this site and my Youtube channel you’ll see a lot of tutorials I have made about them. If you would like to get a 10% discount for both of them then:

Code Snippets manager: WPCodeBox allows you to add code snippets to your site. Also, it allows you to build and manage your WordPress Code Snippets library in the cloud. You can grab it with the 20% discount here (SAVE 20% Coupon: WPSH20).

Contact forms: There are hundreds of contact forms out there but Fluent Forms is the one I like the most. If you need a 20% discount then use this link (save 20% coupon is WPSH20).

Gutenberg add-ons: If I need a good Gutenberg blocks add-on then Kadence Blocks is the one I have used the most. You’ll get 10% discount with the coupon SIMPLEHACKS here.

Website migration: While building a website you probably need a good plugin that can help you with the migration, backups, restoration and staging sites. Well, WpVivid is the one I have used for the last couple of years. If you use this link along with the WPSH20 coupon you’ll get 20% discount.

Woocommerce extensions: There are a bunch of Woocommerce extensions that I really like but the one that stands really out is Advanced Dynamic Pricing. Once again, you’ll get a 20% discount if you use this link here (save 20% coupon is WPSH20)

Web Hosting: If you would like to have a really fast and easy to use managed cloud hosting, then I recommend Verpex Hosting (see my review here). Btw, this site is hosted in Verpex.)

To see all my of most up-to-date recommendations, check out this resource that I made for you!

Do you want to thank me and buy me a beer?

Every donation is entirely welcome but NEVER required. Enjoy my work for free but if you would like to thank me and buy me a beer or two then you can use this form here below.

Choose amount

Best selling plugins

Janek T.
Janek T.

I am a Wordpress enthusiast who has been making websites since 2011. In this site I am offering simple to follow tips on how to use Wordpress and Woocommerce.
If you want to be the first to be notified about the new tutorials then please subscribe to my Youtube channel here
Follow me in Twitter here

Articles: 89