I have an online store built with WordPress and Woocommerce. I sell and ship products to different countries from Ukraine, but I have a couple of products that can't be shipped outside of Ukraine.
I want to remove ALL the other countries except Ukraine from the billing_country field (I don't use shipping_ fields) on the checkout page and show a custom error message (which I can translate then with WPML) under this billing_country field if these products are in the cart. Something like
"Sorry, but %_product-name(s)_% can't be shipped outside of Ukraine"
This is the image I took from another similar question here, and I love how it looks - Example
I might be wrong, but I think the best way to identify these specific products is to use their IDs, and a country code to identify the specific country.
I have already searched through other similar topics here and tried to use all the solutions suggested at:
Disable shipping for specific products based on country in Woocommerce
How do I disable shipping in some of my woocommerce products
Avoid physical products purchases outside specific country in WooCommerce
Avoid checkout for specific products on specific country in Woocommerce
Remove a country from allowed countries when specific products are in WooCommerce cart
Set specific Products to be shipped only in specific countries in WooCommerce
Remove a country from allowed countries if specific product category is in WooCommerce cart
Unfortunately, nothing worked for me. I think some of these solutions worked for older WC versions as they were written years ago, but now they don't.
I should also mention that I'm not a skilled developer and have very little knowledge about WP hooks - I'm just a guy who builds websites with WordPress but doesn't want to make it chunky with dozens of plugins. I would be very grateful for a ready code snippet with comments inside that I can put inside my funtions.php file.
Slightly reworked code from this topic - Remove a country from allowed countries if specific product category is in WooCommerce cart – so it removes all the countries from the checkout form and returns only one country if it finds the needed products in the the cart.
add_filter( 'woocommerce_countries_allowed_countries', 'restrict_delivery_to_ukraine_for_specific_products', 10, 1 );
function restrict_delivery_to_ukraine_for_specific_products( $countries ) {
// Only on cart and checkout pages
if( is_cart() || ( is_checkout() && !is_wc_endpoint_url() ) ) {
$country_code = 'UA'; // Define the country code for Ukraine
$product_ids = array(1111, 2222); // Define the targeted product IDs
$product_found = false; // Initialize
// Loop through cart items
foreach( WC()->cart->get_cart() as $item ){
// Check if one of the targeted products is in the cart
if( in_array( $item['product_id'], $product_ids ) ){
$product_found = true;
break; // Stop the loop if a targeted product is found
}
}
// If a targeted product is found, restrict delivery only to Ukraine
if ( $product_found ) {
// Keep only Ukraine in the list of allowed countries
$countries = array( 'UA' => $countries['UA'] );
}
}
return $countries;
}
To display message about the products that can't be shipped outside of your country under the country field, you need to use the woocommerce_after_checkout_billing_form
hook. It might not work properly in newly checkout blocks, so you should try to switch back to classic checkout.
First, find the products you don't want to ship outside of Ukraine in your cart again to get their names.
Second, wrap your message with __( 'Sorry but these products can't be shipped outside of Ukraine: %s', 'your-domain' )
and use 'your-domain' to translate your message with WPML.
Third, use the woocommerce-info
CSS class to display your message in a nice-looking block instead of just plain text.
add_action( 'woocommerce_after_checkout_billing_form', 'add_notice_above_country_field' );
function add_notice_above_country_field() {
$product_ids = array(1111, 2222); // Define target product IDs
$product_names = array(); // Array to store product names
$product_found = false; // Initialization
// Loop through cart items
foreach( WC()->cart->get_cart() as $item ){
// Check if the target product is in the cart
if( in_array( $item['product_id'], $product_ids ) ){
$product_found = true;
// Get product name
$product = wc_get_product( $item['product_id'] );
if ( $product ) {
$product_names[] = $product->get_name(); // Add product name to array
}
}
}
// If a target product is found, display a message with product names
if ( $product_found ) {
if ( count( $product_names ) === 1 ) {
// If there's one product, add a period after the name
$product_names_list = $product_names[0] . '.';
} else {
// If there are multiple products, separate them with commas and add a period at the end
$product_names_list = implode(', ', $product_names) . '.';
}
$message = sprintf(
__( 'Sorry but these products cannot be shipped outside of Ukraine: %s', 'your-domain' ),
esc_html( $product_names_list )
);
echo '<div class="woocommerce-info">' . $message . '</div>';
}
}
Paste both code snippets into your functions.php file.