---
title: "How to add multiple products to the cart from a URL?"
description: "Recently one of our customers, Bestway, asked us for a custom plugin to send to Salesforce the new sign-ups to their newsletter and the abandoned carts. It should also generate an exclusive discount coupon for each new sign-up confirmed in"
url: https://artprojectgroup.com/how-to-add-multiple-products-to-the-cart-from-a-url
date: 2023-08-04
modified: 2023-08-04
author: "Art Project Group"
image: https://artprojectgroup.com/wp-content/uploads/2023/04/woocommerce-blog.webp
categories: ["Tutorials"]
tags: ["functions.php", "PHP", "WooCommerce"]
type: post
lang: en-US
---

# How to add multiple products to the cart from a URL?

Recently one of our customers, [Bestway](https://bestwaystore.es), asked us for a custom plugin to send to Salesforce the new sign-ups to their newsletter and the abandoned carts. It should also generate an exclusive discount coupon for each new sign-up confirmed in the newsletter.

So far so good, we built all the necessary code and linked the sign-ups generated with Avada Form, we created a webhook to receive information from Salesforce about the confirmation of the sign-ups in order to be able to activate the coupon previously created and sent to Salesforce and to redirect the customer to the corresponding landing page according to the language in which they signed up, and we send the abandoned WooCommerce carts, and it does all of that in real time and in the background without affecting in any way the usability or the performance of the website.

The problem arose for us when the customer required of us the need to create a URL so that the customer could recover that abandoned cart easily.

As you will well know, for this there is a query string that can be passed in the URL and adds a product to the cart. In [WooCommerce Custom “Add to Cart” URLs – The Ultimate Guide](https://www.businessbloomer.com/woocommerce-custom-add-cart-urls-ultimate-guide/) you have a fantastic guide for learning to use the `add-to-cart` and `quantity` parameters. The problem is that this query does not allow adding anything more than a single product and a specific quantity of units for that product, but we needed to add more than one product and the relevant quantities for each one of them.

Searching the Internet we came across a fantastic piece of code: [WooCommerce: Allow adding multiple products to the cart via the add-to-cart query string](https://dsgnwrks.pro/snippets/woocommerce-allow-adding-multiple-products-to-the-cart-via-the-add-to-cart-query-string/), but it did not quite work for us, fundamentally because of one of the requirements of the customer, that as well as being able to add the products by their ID they could be added by their SKU.

It also turns out that the code shared in that post has some errors and does not work, so the cart is never filled.

### Let us get to work

With the needs of the customer known and the problems detected in the base code created by [Justin Sainton](https://twitter.com/JS_Zao), we get to work and build the following code:

Copy to clipboardSyntax Highlighter//Adds multiple products to the cart. Original at https://dsgnwrks.pro/snippets/woocommerce-allow-adding-multiple-products-to-the-cart-via-the-add-to-cart-query-string/
function apg_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' ], ',' ) ) {
return;
}

// 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 (:)
// https://dsgnwrks.pro/snippets/woocommerce-allow-adding-multiple-products-to-the-cart-via-the-add-to-cart-query-string/#comment-12236
$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;

//Is it a SKU?
if ( get_post_type( $product_id ) != 'product' ) {
$product_id = wc_get_product_id_by_sku( $product_id );
}

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 ) {
continue;
}

$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 );
}
}
}
add_action( 'wp_loaded', 'apg_multiple_products_to_cart', 15 );

function woo_hack_invoke_private_method( $class_name, $methodName, $product_id ) {
$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( $reflection ), $args );

return call_user_func_array( array( $method, 'invoke' ), $args );
}Where, as well as adding the possibility of using the SKU instead of the ID of the product, we corrected all the errors that we detected in the `woo_hack_invoke_private_method` function, therefore this code is completely operational and functional, it does not return any kind of error and it generates the cart without any kind of problem.

With this code added in your custom plugin or in the `functions.php` file of your child theme, you can now pass a URL along the lines of `https://domain.ext/checkout?add-to-cart=XXX:x,YYY:y,ZZZ:z` on your website, where the values *XXX*, *YYY* and *ZZZ* are product IDs or SKUs and the values *x*, *y* and *z* are the quantities of each one of the products. With it on your website you will see that that URL redirects you "magically" to the checkout of your online shop with all the products and their corresponding quantities added to it and waiting for the data of the billing form in order to be able to complete the purchase.

### But how do I build that URL from PHP?

We use AJAX to generate the sending of the abandoned cart data to Salesforce, among which the URL that we generate in real time is included.

A simple example for being able to create this URL would be this small PHP function:

Copy to clipboardSyntax Highlighter//Carrito abandonado
function apg_carrito_abandonado() {
$carrito = wc_get_checkout_url() . "?add-to-cart=";
//Carrito
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$carrito .= $cart_item[ 'product_id' ] . ":" . $cart_item[ 'quantity' ] . ",";
}

return substr_replace( $carrito, "", -1 );
}This simple function will return a URL with the protocol, the domain name and the checkout path of your online shop, followed by the list of product IDs and quantities to add inside the `add-to-cart` parameter.

That is how simple it is to generate a dynamic URL that is capable of adding a complete order to your online shop.

We hope you find this code useful and we look forward to your comments.
