Override External/Affiliate Product Button URL (with Query String Parameters) - php

I'm attempting to override the URL of the 'Buy Product' button for all External/Affiliate WooCommerce products. The button needs to link to a contact page and pre-fill the 'Subject' form field with the product title included via query string (e.g. Product enquiry: Product Title).
After reading https://stackoverflow.com/a/43947253/4068853 I've been able to get pretty close by adding the following to functions.php:
// Override external button url
function override_external_product_url( $url, $product ){
if ( 'external' === $product->get_type() ) {
// custom add to cart url example
$url = home_url( "/contact/?your-subject=Product enquiry:");
}
return $url;
}
add_filter( 'woocommerce_product_add_to_cart_url', 'override_external_product_url', 10, 2 );
The only thing remaining is to add the product title to the end of the query string. I know the product title can be fetched with <?php the_title_attribute(); ?> but being a PHP noob I'm just not sure how to implement this into the function?
Thanks.

Ended up using get_the_title instead because the_title_attribute was causing an error (product title text duplicating and rendering outside the button markup). Also added url encoding, final code looks like:
// Override external button url
function override_external_product_url( $url, $product ){
if ( 'external' === $product->get_type() ) {
// custom add to cart url example
$url = home_url("/contact/?your-subject=" . urlencode("Product Enquiry: " . get_the_title()));
}
return $url;
}
add_filter( 'woocommerce_product_add_to_cart_url', 'override_external_product_url', 10, 2 );

Related

How to append a product & category ID to a query string to the end of a URL for all product in woocommerce

I currently have a Woocommerce store and an mobile application that pulls products and category from the site.
I am in the process of implementing android app links in the mobile application and in order to link the correct webpage with the product on the app. I would like to add a parameter/query string to the end of all product URLS.
I managed to get this right by adding the post ID (Which is the same as a product ID) at the end of the URL by using.
I did this by using this function in the function.php file
<pre>
add_filter( 'post_type_link', 'append_query_string', 10, 2 );
function append_query_string( $url, $post )
{
return add_query_arg('wine_id',$post->ID, $url);
}
</pre>
Is there any way to append the category ID at the end of the URL as well?
I searched the web flat and could not find anything.
You can pass an array with query params to append multiple.
<pre>
add_filter( 'post_type_link', 'append_query_string', 10, 2 );
function append_query_string( $url, $post )
{
return add_query_arg(array('wine_id'=>$post->ID,'category_id'=>$category_id), $url);
}
</pre>

Add custom class to links if product is out of stock in WooCommerce

In WooCommerce, do you know of a way to add a class to a <a> html element (product link) if the product is out of stock?
Basically, I have product links on a page, and each link goes to a particular product. I am trying to add an "oos" class to the product's link, if that product is out of stock. Then I can style those links differently.
More info:
https://jsfiddle.net/Garconis/qtvkxkga/
I am creating an SVG map. Each piece/path will link to a particular product. If the product that it's linked to is out of stock, it should then add the "oos" class (so that the piece is no longer visible).
I'm not opposed to using some sort of shortcode, if that will help things. But the shortcode would need to be able to wrap each of the unique SVG paths.
In stock:
<svg>
<a href="https://example.com/?p=332">
<path></path>
</a>
</svg>
Out of stock:
<svg>
<a href="https://example.com/?p=332" class="oos">
<path></path>
</a>
</svg>
Note, in the URL, I can also use the product's ID if that helps PHP find the corresponding item (as opposed to using the usual slug URL).
The simplest way should be to build a custom function shortcode for the html <a> tag with the product link and the additional class when it's "out of stock":
Here is that function code:
if( !function_exists('custom_shortcode_svg_product_link') ) {
function custom_shortcode_svg_product_link( $atts, $content = null ) {
// Shortcode Attributes
$atts = shortcode_atts(
array(
'id' => '',
),
$atts, 'svg_product_link'
);
$product_id = $atts['id'];
// Get an instance of the WC_Product object
$product = wc_get_product( $product_id );
// Display the class "oos" when product is out of stock
$class = $product->is_in_stock() ? '"' : '" class="oos"';
// The product link
$product_link = $product->get_permalink();
// The output
return '<a href="'.$product_link.$class.'>'.$content.'</a>';
}
add_shortcode( 'svg_product_link', 'custom_shortcode_svg_product_link' );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested on WooCommerce 3+ and output the desired html.
USAGE Example (for your case):
Note: I am absolutely not familiar with SVG files and html format, so I hope that it will work with <svg><path></path></svg>.
/*
* # id (the product ID argument)
*/
<svg>
[svg_product_link id="332"]
<path></path>
[/svg_product_link]
</a>
</svg>

WooCommerce "CONTACT" button when out of stock

Trying to achieve something that should be simple, but I've tried 3 approaches with multiple code variations and I just can't make it work. I'm trying to create a button that will appear in place of the "ADD TO CART" button on single product pages when the item is out of stock. Clicking the button will fire a popup contact form.
Is creating an add action in functions the right way to go, or should I replace the normal button with an if statement? I've tried both, so help with coding either would be greatly appreciated.
You can either hook into woocommerce_loop_add_to_cart_args using a filter in your functions.php or edit the template file directly by pulling it into your theme. Either way will require a bit of PHP.
If doing it in your functions.php, it would look something like this (untested but should send you down the right path):
<?php
add_filter( 'woocommerce_loop_add_to_cart_link', 'my_out_of_stock_button' );
function my_out_of_stock_button( $args ){
global $product;
if( $product && !$product->is_in_stock() ){
return 'Contact us';
}
return $args;
}
I don't know what your button code should actually look like or what other information you need to capture, but this is how you could override the "Add to Cart" button and replace it if out of stock.
UPDATE
LoicTheAztec brought up a great point - the filter provided only affects the button on the archive, category, tag overview pages - not the individual product pages. There are no hooks for the individual product page buttons BUT you can copy the templates to your theme and override them.
You'll want to look at the files in templates/single-product/add-to-cart. Use a similar if statement as above:
#simple.php
<?php if ( $product->is_in_stock() ) : ?>
// Standard WooCommerce code
<?php else: ?>
// Your button code
<?php endif; ?>
Just add below code in functions.php file of your enabled theme reference
add_action('woocommerce_after_shop_loop_item', 'themelocation_change_outofstock_to_contact_us', 1);
// for shop page
function themelocation_change_outofstock_to_contact_us() {
global $product;
if (!$product->is_in_stock()) {
remove_action('woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart');
remove_action('woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart');
//change the link to your contact us page
echo ' Contact Us ';
}
}
// for single page
add_filter('woocommerce_get_availability', 'wcs_custom_get_availability', 1, 2);
function wcs_custom_get_availability($availability, $_product) {
// Change In Stock Text
if ($_product->is_in_stock()) {
$availability['availability'] = __('Available!', 'woocommerce');
}
// Change Out of Stock Text
if (!$_product->is_in_stock()) {
$availability['availability'] = __(' Contact Us ', 'woocommerce');
}
return $availability;
}
I was looking for a way to show a contact button on bespoke products and
#ahwychkchih solution works great. One issue I had though is that schema markup will show as out of stock for those products which is not the case for beskpoke products is just they can't be purchased straight away so I've added this to force in_stock markup for my products. I'm aware that this solution would affect all products so you can always add a product id filter if needed
// Force In Stock schema markup
function fix_my_product_offers_schema ($markup_offer, $product) {
if (!$product->is_in_stock()) {
$markup_offer['availability'] = 'https://schema.org/InStock';
}
return $markup_offer;
}
add_filter('woocommerce_structured_data_product_offer', 'fix_my_product_offers_schema', 1, 2);

Redirect customers after leaving woocommerce product review

I am trying to redirect users to a thank you page after leaving a product review in woocommerce. I know the code
add_filter('comment_post_redirect', 'redirect_after_comment');
function redirect_after_comment($location)
{
return $_SERVER["HTTP_REFERER"];
}
will redirect all comments to a location, but I can't seem to find a filter or hook to specify only woocommerce product reviews. Has anyone done this before? Ideally I would just like to redirect to a standard wordpress page so I can add options and features to that pages template file in the future.
The comment_post_redirect filter has a second parameter. This parameter is the $comment object from which we can grab the post's ID. With the post's ID you can test for post_type and adjust the returned variable accordingly.
add_filter( 'comment_post_redirect', 'redirect_after_comment', 10, 2 );
function redirect_after_comment( $location, $comment ){
$post_id = $comment->comment_post_ID;
// product-only comment redirects
if( 'product' == get_post_type( $post_id ) ){
$location = 'http://www.woothemes.com';
}
return $location;
}

Woocommerce category page display this custom field before products

The code bellow, is to show a custom field I created to customize Woocommerce product category pages.. This code makes the custom field appear "after" the list of products. I need to make this code appear BEFORE the list of products... any hint on what I have to change in this bit of php code to make the custom field show before?
<?php
// Display details on product category archive pages
add_action( 'woocommerce_after_shop_loop', 'wpm_product_cat_archive_add_meta' );
function wpm_product_cat_archive_add_meta() {
$t_id = get_queried_object()->term_id;
$term_meta = get_option( "taxonomy_$t_id" );
$term_meta_content = $term_meta['custom_term_meta'];
if ( $term_meta_content != '' ) {
echo '<div class="woo-sc-box normal rounded full">';
echo apply_filters( 'the_content', $term_meta_content );
echo '</div>';
}
}
Thank you, I would really like to understand what makes the code appear after and not before, is the filter? in the last lines?
I found this bit of code at http://www.wpmusketeer.com/add-a-wysiwyg-field-to-woocommerce-product-category-page/
use below action to display custom fields before list of products
add_action('woocommerce_before_shop_loop','wpm_product_cat_archive_add_meta');

Categories