Asked  7 Months ago    Answers:  5   Viewed   36 times

I'd like to add a button next to "Add to Cart" on the product page that adds "-sample" to the product URL when clicked.

Example:

You're viewing Product 1's page and the URL is "http://www.example.com/shop/product-1/"

When you click on the button, it adds "-sample" to the URL "http://www.example.com/shop/product-1-sample/"

How can I achieve this?

Thanks

 Answers

10

For woocommerce 3+ (only):

In woocommerce 3 you will use woocommerce_after_shop_loop_item action hook instead, as the hook woocommerce_after_add_to_cart_button will not work anymore.

add_action( 'woocommerce_after_add_to_cart_button', 'add_custom_button', 10, 0 );
function add_custom_button() {
    global $product;

    $product_link = $product->get_permalink();

    $sample_link = substr($product_link, 0, -1) . '-sample/';
    echo '<a class="button alt btn-sample" href="' . esc_url( $sample_link ) .'">' . __( "Get a sample", "my_theme_slug" )  . '</a>';
}

Code goes on function.php file of your active child theme (or active theme). Tested and works.


Before woocommerce 3:

This is possible using hook woocommerce_after_add_to_cart_button to add your additional button on product pages, using this custom function:

add_action( 'woocommerce_after_add_to_cart_button', 'add_custom_button', 10, 0 );
function add_custom_button() {
    global $product;

    $product_link = get_permalink( get_the_id() );

    $sample_link = substr($product_link, 0, -1) . '-sample/';
    echo '<a class="button alt btn-sample" href="' . esc_url( $sample_link ) .'">' . __( "Get a sample", "my_theme_slug" )  . '</a>';
}

This code goes on function.php file of your active child theme or theme.

This code is tested and fully functional.


Based on this: Add a button after add to cart and redirect it to some custom link in WooCommerce

And this: PHP - How to remove all specific characters at the end of a string?

Wednesday, March 31, 2021
 
clean_coding
answered 7 Months ago
82

Use this custom function hooked in woocommerce_after_shop_loop_item action hook, to add your custom button linked to the product (except variable and grouped product types):

add_action('woocommerce_after_shop_loop_item', 'add_a_custom_button', 5 );
function add_a_custom_button() {
    global $product;

    // Not for variable and grouped products that doesn't have an "add to cart" button
    if( $product->is_type('variable') || $product->is_type('grouped') ) return;

    // Output the custom button linked to the product
    echo '<div style="margin-bottom:10px;">
        <a class="button custom-button" href="' . esc_attr( $product->get_permalink() ) . '">' . __('View product') . '</a>
    </div>';
}

Code goes in functions.php file of your active child theme (or active theme).

Tested and still perfectly works on WooCommerce 3.7.x (with last storefront theme):

on shop page


Embedding your styles (related to author comments):

add_action('wp_head', 'custom_button_styles', 9999 );
function custom_button_styles() {
    if( is_shop() || is_product_category() || is_product_tag() ):

    // The styles
    ?>
    <style>
        .button.custom-button { background-color: white !important;
            color: black !important; border: 2px solid #4CAF50 !important; }
        .button.custom-button:hover { background-color: black !important;
            color: white !important; border: 2px solid black !important; }
    </style>
    <?php
    endif;
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

Tested and works.

Wednesday, March 31, 2021
 
Karsten
answered 7 Months ago
75

Tried to test your code on a test server, but your booking product was not showing on backend.

Your issue could come from here: I think you are using with public function add_to_cart() an existing name function, and you have to rename-it differently.

Then I have revisited your code, based on this thread.

It's may be better to extend WC_Product_Simple class rather than WC_Product class, since your product uses simple product add-to-cart button template:
single-product/add-to-cart/simple.php.

With this custom code I don't face like you Multiple add to cart sections.

— @Update1 —
But you can still keep WC_Product extended instead of WC_Product_Simple. This way, as you requested in comment, your product type will be "simple_booking" as specified in 1st and 2nd functions. That does not mean that your product is simple (it's just a slug that you can change, changing at the same time in both places).

So I have modified the code again and tested: It works…

This is the code I use (and I have tested):

/**
 * Register the custom product type after init
 */
function register_simple_booking_product_type() {

    /**
     * This should be in its own separate file.
     */
    class WC_Product_Booking extends WC_Product{ // <= changed back to WC_product class

        public function __construct( $product ) {

            $this->product_type = 'simple_booking';
            $this->supports[]   = 'ajax_add_to_cart';

            parent::__construct( $product );

            // As we extend simple product class, you may not need this anymore.
            add_action('woocommerce_booking_add_to_cart', array($this, 'simple_booking_add_to_cart'),30);

        }

    }

}
add_action( 'init', 'register_simple_booking_product_type' );

// Registering the slug name (YOU can CHANGE IT)
function add_simple_booking_product( $types ){

    // Key should be exactly the same as in the class product_type parameter
    $types[ 'simple_booking' ] = __( 'Simple booking' );

    return $types;

}
add_filter( 'product_type_selector', 'add_simple_booking_product' );

/**
 * Show pricing fields for simple_booking product.
 */
function simple_booking_custom_js() {

    if ( 'product' != get_post_type() ) :
        return;
    endif;

    ?><script type='text/javascript'>
        jQuery( document ).ready( function() {
            jQuery( '.options_group.pricing' ).addClass( 'show_if_simple_booking' ).show();
        });
    </script><?php
}
add_action( 'admin_footer', 'simple_booking_custom_js' );

// Not sure you will need that (because of the change of the extended class)
function simple_booking_add_to_cart() {
    wc_get_template( 'single-product/add-to-cart/simple.php' );
}

Tested this code on function.php file located in active child theme (or theme).

Reference: Adding a custom WooCommerce product type


— @Update2 — The solution (find by the author of this question):

To puts the add-to-cart button once in the right place (to use it in your own custom product make an action called woocommerce_YOURPRODUCTTYPE_add_to_cart), with this code:

if (! function_exists( 'woocommerce_booking_add_to_cart' ) ) {

  /**
  * Output the simple product add to cart area.
  *
  * @subpackage Product
  */

  function booking_add_to_cart() {
    wc_get_template( 'single-product/add-to-cart/simple.php' );
  }

  add_action('woocommerce_booking_add_to_cart',  'booking_add_to_cart');
}
Saturday, May 29, 2021
 
muncherelli
answered 5 Months ago
61

You must indeed provide a piece of jQuery yourself. How this is applied to the other check boxes (default) can be found in js/admin/meta-boxes-product.js (line 122...)

Note: I have also made some minor changes to your existing code, among which certain classes

So you get:

// Add a checkbox as Woocommerce admin product option
function filter_product_type_options( $product_type_options ) { 
    $product_type_options['batches'] = array(
        'id'            => '_batches',
        'wrapper_class' => 'show_if_simple show_if_variable',
        'label'         => __( 'Batches', 'woo-batches' ),
        'description'   => __( 'Product is sold from batches.', 'woo-batches' ),
        'default'       => 'no',
    );

    return $product_type_options;
}
add_filter( 'product_type_options', 'filter_product_type_options', 10, 1 );

// Add custom product setting tab.
function filter_woocommerce_product_data_tabs( $default_tabs ) {
    $default_tabs['woo_batches'] = array(
        'label'    => __( 'Batches', 'woo-batches' ),
        'target'   => 'woo_batches',
        'class'    => array( 'hide_if_simple', 'hide_if_variable', 'show_if_batches' ),
        'priority' => 25
    );
    
    return $default_tabs;
}
add_filter( 'woocommerce_product_data_tabs', 'filter_woocommerce_product_data_tabs', 10, 1 );

// Prints scripts or data before the default footer scripts.
// This hook is for admin only and can’t be used to add anything on the front end.
function action_admin_footer() {
    ?>
    <script>
        jQuery(document).ready(function($) {
            $( 'input#_batches' ).change( function() {
                var is_batches = $( 'input#_batches:checked' ).length;
            
                // Show rules.
                if ( is_batches ) {
                    $( '.show_if_batches' ).show();
                }
            });            
        });
    </script>
    <?php
}
add_action( 'admin_footer', 'action_admin_footer' );
Saturday, May 29, 2021
 
Arman
answered 5 Months ago
80

So what I ended up doing was adding the single page add to cart action to a hook for the shop page loop as follows:

add_action('woocommerce_after_shop_loop_item',
           'woocommerce_template_single_add_to_cart', 30);

Thanks.

Saturday, May 29, 2021
 
inVader
answered 5 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share