search ]

Adding Products to the Shopping Cart Through a Link

Recently, a customer approached me with a request to create a dynamic scenario on a WordPress site where clicking a button would lead the user directly to the Checkout page, which already contains a number of products in the shopping cart as decided by the site owner.

It turns out that WooCommerce allows you to do this very easily for a single product using the following code, where XX in the first line is the ID of the product you want to add to the cart:

$product_id = XX;
$url = esc_url_raw( add_query_arg( 'add-to-cart', $product_id, wc_get_checkout_url() ) );

All you need to do is print the variable $url inside an href somewhere, and here is a link to the payment page that automatically adds product XX to the cart.

However, when I looked for a way to add multiple products to the cart in parallel through a link, I found that it’s a bit more complicated…

Adding Multiple Products in Parallel to the Cart

Browsing the web led me to an article by a developer who created a function that works great and allows adding multiple products in parallel to the shopping cart, as well as choosing the quantity for each product. Take a look at the following code:

function woocommerce_add_multiple_products_to_cart( $url = false ) {
	// Make sure WC is installed, and add-to-cart qauery arg exists, and contains at least one comma.
	if ( ! class_exists( 'WC_Form_Handler' ) || empty( $_REQUEST['add-to-cart'] ) || false === strpos( $_REQUEST['add-to-cart'], ',' ) ) {

	// Remove WooCommerce's hook, as it's useless (doesn't handle multiple products).
	remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );

	$product_ids = explode( ',', $_REQUEST['add-to-cart'] );
	$count       = count( $product_ids );
	$number      = 0;

	foreach ( $product_ids as $id_and_quantity ) {
		// Check for quantities defined in curie notation (<product_id>:<product_quantity>)
		$id_and_quantity = explode( ':', $id_and_quantity );
		$product_id = $id_and_quantity[0];

		$_REQUEST['quantity'] = ! empty( $id_and_quantity[1] ) ? absint( $id_and_quantity[1] ) : 1;

		if ( ++$number === $count ) {
			// Ok, final item, let's send it back to woocommerce's add_to_cart_action method for handling.
			$_REQUEST['add-to-cart'] = $product_id;

			return WC_Form_Handler::add_to_cart_action( $url );

		$product_id        = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $product_id ) );
		$was_added_to_cart = false;
		$adding_to_cart    = wc_get_product( $product_id );

		if ( ! $adding_to_cart ) {

		$add_to_cart_handler = apply_filters( 'woocommerce_add_to_cart_handler', $adding_to_cart->get_type(), $adding_to_cart );

		// Variable product handling
		if ( 'variable' === $add_to_cart_handler ) {
			woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_variable', $product_id );

			// Grouped Products
		} elseif ( 'grouped' === $add_to_cart_handler ) {
			woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_grouped', $product_id );

			// Custom Handler
		} elseif ( has_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler ) ){
			do_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler, $url );

			// Simple Products
		} else {
			woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_simple', $product_id );

// Fire before the WC_Form_Handler::add_to_cart_action callback.
add_action( 'wp_loaded', 'woocommerce_add_multiple_products_to_cart', 15 );

  Invoke class private method

 * @since   0.1.0
 * @param   string $class_name
 * @param   string $methodName
 * @return  mixed
function woo_hack_invoke_private_method( $class_name, $methodName ) {
	if ( version_compare( phpversion(), '5.3', '<' ) ) {
		throw new Exception( 'PHP version does not support ReflectionClass::setAccessible()', __LINE__ );

	$args = func_get_args();
	unset( $args[0], $args[1] );
	$reflection = new ReflectionClass( $class_name );
	$method = $reflection->getMethod( $methodName );
	$method->setAccessible( true );

	$args = array_merge( array( $class_name ), $args );
	return call_user_func_array( array( $method, 'invoke' ), $args );

Add this code to the functions.php file in your child theme, and afterward, you can add products to the cart using the following links:

// Multiple products, multiple quantities per product.
$product_ids = '53:2,68:4';
$add_to_cart_url = esc_url_raw( add_query_arg( 'add-to-cart', $product_ids, wc_get_checkout_url() ) );

// Multiple products (default quantity of 1)
$product_ids = '53,68';
$add_to_cart_url = esc_url_raw( add_query_arg( 'add-to-cart', $product_ids, wc_get_checkout_url() ) );

// Normal add-to-cart URL
$product_ids = '53';
$add_to_cart_url = esc_url_raw( add_query_arg( 'add-to-cart', $product_ids, wc_get_checkout_url() ) );

In line number 4, for example, we specified that the link will add two products with the ID 53 and four products with the ID 68 to the shopping cart.

Note that in the above code, we use the wc_get_checkout_url function, which directly leads to the payment page. If, on the other hand, you want to direct the user to the shopping cart page instead of the payment page, you should replace this function with wc_get_cart_url.


The idea of creating a prompt action that takes the potential customer directly to the payment page along with a specific number of products can certainly increase sales for those products that require a boost in sales.

By using custom fields or with the help of the Advanced Custom Fields plugin, you can allow your customers to easily choose the products they want to leverage.

Ideas and comments are welcome 🙂

Roee Yossef
Roee Yossef

I develop custom WordPress themes by design. I love typography, colors & everything between, and aim to provide high performance, seo optimized websites with a clean & semantic code.


Leave a Comment

Add code using the buttons below. For example, to add PHP click the PHP button & add the code inside the shortcode. Typo? Please let us know...