Customize Order received page based on shipping method in WooCommerce - php

How could I customise the order thank you page based on the order's shipping method? So for example if a customer used 'Delivery on request' option, the thank you page would display a different title.
add_filter( 'the_title', 'woo_personalize_order_received_title', 10, 2 );
function woo_personalize_order_received_title( $title, $id ) {
if ( is_order_received_page() && get_the_ID() === $id ) {
global $wp;
// Get the order. Line 9 to 17 are present in order_received() in includes/shortcodes/class-wc-shortcode-checkout.php file
$order_id = apply_filters( 'woocommerce_thankyou_order_id', absint( $wp->query_vars['order-received'] ) );
$order_key = apply_filters( 'woocommerce_thankyou_order_key', empty( $_GET['key'] ) ? '' : wc_clean( $_GET['key'] ) );
if ( $order_id > 0 ) {
$order = wc_get_order( $order_id );
if ( $order->get_order_key() != $order_key ) {
$order = false;
}
}
if ( isset ( $order ) ) {
$chosen_titles = array();
$available_methods = $wp->shipping->get_packages();
$chosen_rates = ( isset( $wp->session ) ) ? $wp->session->get( 'chosen_shipping_methods' ) : array();
foreach ($available_methods as $method)
foreach ($chosen_rates as $chosen) {
if( isset( $method['rates'][$chosen] ) ) $chosen_titles[] = $method['rates'][ $chosen ]->label;
}
if( in_array( 'Delivery price on request', $chosen_titles ) ) {
//$title = sprintf( "You are awesome, %s!", esc_html( $order->billing_first_name ) ); // use this for WooCommerce versions older then v2.7
$title = sprintf( "You are awesome, %s!", esc_html( $order->get_billing_first_name() ) );
}
}
}
return $title;
}

is_order_received_page() doesn't exist. Instead use is_wc_endpoint_url( 'order-received' )…
Also $wp->session or $wp->shipping will not work. Instead you can find the chosen shipping method data in the order item "shipping".
Try this instead:
add_filter( 'the_title', 'customizing_order_received_title', 10, 2 );
function customizing_order_received_title( $title, $post_id ) {
if ( is_wc_endpoint_url( 'order-received' ) && get_the_ID() === $post_id ) {
global $wp;
$order_id = absint( $wp->query_vars['order-received'] );
$order_key = isset( $_GET['key'] ) ? wc_clean( $_GET['key'] ) : '';
if ( empty($order_id) || $order_id == 0 )
return $title; // Exit
$order = wc_get_order( $order_id );
if ( $order->get_order_key() != $order_key )
return $title; // Exit
$method_title_names = array();
// Loop through Order shipping items data and get the method title
foreach ($order->get_items('shipping') as $shipping_method )
$method_title_names[] = $shipping_method->get_name();
if( in_array( 'Delivery price on request', $method_title_names ) ) {
$title = sprintf( "You are awesome, %s!", esc_html( $order->get_billing_first_name() ) );
}
}
return $title;
}
Code goes on function.php file of your active child theme (or active theme). Tested and works.
Similar: Adding custom message on Thank You page by shipping method in Woocommerce

Related

Target specific WooCommerce email notifications when using the "woocommerce_order_item_meta_start" hook

I have this function which adds custom meta field to the product detail in all WooCommerce emails. But I need to show only after the order is paid (this can be also just the "completed" email).
add_action( 'woocommerce_order_item_meta_start', 'email_confirmation_display_order_items', 10, 3 );
function email_confirmation_display_order_items( $item_id, $item, $order ) {
// On email notifications for line items
if ( ! is_wc_endpoint_url() && $item->is_type('line_item') ) {
$ot_address = get_post_meta( $item->get_product_id(), 'ot_address', true );
if ( ! empty($ot_address) ) {
printf( '<div>' . __("Terms: %s", "woocommerce") . '</div>', $ot_address );
}
}
}
I hoped that I can nest it inside if ( $email->id == 'customer_completed_order' ) {}, so the final code will look like this:
add_action( 'woocommerce_order_item_meta_start', 'email_confirmation_display_order_items', 10, 3 );
function email_confirmation_display_order_items( $item_id, $item, $order ) {
if ( $email->id == 'customer_completed_order' ) {
// On email notifications for line items
if ( ! is_wc_endpoint_url() && $item->is_type('line_item') ) {
$ot_address = get_post_meta( $item->get_product_id(), 'ot_address', true );
if ( ! empty($ot_address) ) {
printf( '<div>' . __("Terms: %s", "woocommerce") . '</div>', $ot_address );
}
}
}
}
But it stops working after that change. Any advice?
As you can see in your code attempt, $email is not part of the woocommerce_order_item_meta_start hook. So to target certain WooCommerce email notifications, you will need a workaround.
Step 1) creating and adding a global variable, via another hook that only applies to WooCommerce email notifications.
// Setting global variable
function action_woocommerce_email_before_order_table( $order, $sent_to_admin, $plain_text, $email ) {
$GLOBALS['email_id'] = $email->id;
}
add_action( 'woocommerce_email_before_order_table', 'action_woocommerce_email_before_order_table', 1, 4 );
Step 2) In the hook woocommerce_order_item_meta_start, use the global variable so we can target certain WooCommerce email notifications
function action_woocommerce_order_item_meta_start( $item_id, $item, $order, $plain_text ) {
// On email notifications for line items
if ( ! is_wc_endpoint_url() && $item->is_type('line_item') ) {
// Getting the email ID global variable
$ref_name_globals_var = isset( $GLOBALS ) ? $GLOBALS : '';
$email_id = isset( $ref_name_globals_var['email_id'] ) ? $ref_name_globals_var['email_id'] : '';
// NOT empty and targeting specific email. Multiple statuses can be added, separated by a comma
if ( ! empty ( $email_id ) && in_array( $email_id, array( 'new_order', 'customer_completed_order' ) ) ) {
// Get meta
$ot_address = get_post_meta( $item->get_product_id(), 'ot_address', true );
// OR use to get meta
// $ot_address = $item->get_meta( 'ot_address' );
if ( ! empty( $ot_address ) ) {
printf( '<div>' . __( 'Terms: %s', 'woocommerce' ) . '</div>', $ot_address );
}
}
}
}
add_action( 'woocommerce_order_item_meta_start', 'action_woocommerce_order_item_meta_start', 10, 4 );

Woocomerce custom redirection after checkout per category

I'm trying to have 2 diferent thank you pages based on 2 categories after payment.
I can redirect to just 1 page if product is on category item and to another one if not.
But i can't split this for 2 diferent categories, i'm just new on php could be nice if someone could help me with this.
My code:
add_action( ‘template_redirect’, ‘wc_custom_redirect_after_purchase’ );
function wc_custom_redirect_after_purchase() {
global $wp;
if ( is_checkout() && ! empty( $wp->query_vars[‘order-received’] ) ) {
$cat_in_cart = false;
$order_id = isset( $wp->query_vars[‘order-received’] ) ? intval( $wp->query_vars[‘order-received’] ) : 0;
$order = new WC_Order( $order_id );
$product_categories = array( ‘mezcla-y-mastering-online’, ‘asesoria-personalizada’ );
foreach( $order->get_items() as $item ){
if( has_term( $product_categories, ‘product_cat’, $item->get_product_id() ) ) {
$cat_in_cart = true;
break;
}
}
if ( $cat_in_cart) {
if(in_array(«asesoria-personalizada», $product_categories)){
wp_redirect( «https://artchitectsproductions.com/gracias-compra-asesoria/»);
} elseif (in_array(«mezcla-y-mastering-online», $product_categories)){
wp_redirect(«https://artchitectsproductions.com/gracias-compra-mezcla-y-mastering-online/»);
}
} else {
wp_redirect(«https://artchitectsproductions.com/gracias-por-tu-compra/»);
}
exit;
}
}
}
The following code using dedicated template_redirect hook and WordPress has_term() conditional function (to be used with product categories), will redirect customers after checkout to my account section when their order contain items from defined product categories:
add_action( 'template_redirect', 'order_received_redirection_to_my_account' );
function order_received_redirection_to_my_account() {
// Only on "Order received" page
if( is_wc_endpoint_url('order-received') ) {
global $wp;
// HERE below define your product categories in the array
$categories = array('Tshirts', 'Hoodies', 'Glasses');
$order = wc_get_order( absint($wp->query_vars['order-received']) ); // Get the Order Object
$category_found = false;
// Loop theough order items
foreach( $order->get_items() as $item ){
if( has_term( $categories, 'product_cat', $item->get_product_id() ) ) {
$category_found = true;
break;
}
}
if( $category_found ) {
// My account redirection url
$my_account_redirect_url = get_permalink( get_option('woocommerce_myaccount_page_id') );
wp_redirect( $my_account_redirect_url );
exit(); // Always exit
}
}
}
Code goes in the function.php file of your active child theme (or active theme). Tested and works.
You can receive all product terms using get_the_terms() and then push them to an array. Try the below code.
add_action( 'template_redirect', 'wc_custom_redirect_after_purchase' );
function wc_custom_redirect_after_purchase() {
global $wp;
if ( is_checkout() && ! empty( $wp->query_vars['order-received'] ) ) {
$cat_in_cart = false;
$order_id = isset( $wp->query_vars['order-received'] ) ? intval( $wp->query_vars['order-received'] ) : 0;
$order = new WC_Order( $order_id );
$product_categories = array();
foreach( $order->get_items() as $item ){
$product_cat = get_the_terms( $item->get_product_id() , 'product_cat' );
if( !empty( $product_cat ) ){
foreach ( $product_cat as $cat ) {
$product_categories[] = $cat->slug;
}
}
}
if( !empty( $product_categories ) && in_array('asesoria-personalizada', $product_categories ) ){
wp_redirect( 'https://artchitectsproductions.com/gracias-compra-asesoria/');
} elseif ( !empty( $product_categories ) && in_array('mezcla-y-mastering-online', $product_categories ) ){
wp_redirect('https://artchitectsproductions.com/gracias-compra-mezcla-y-mastering-online/');
}else {
wp_redirect('https://artchitectsproductions.com/gracias-por-tu-compra/');
}
exit;
}
}
}

Change WooCommerce thankyou page title based on order status

Attempting to change the title of the thank you page based on specific order statuses, by combining a filter and action as follows:
add_action( 'woocommerce_thankyou', 'order_thank_you_status' );
function order_thank_you_status( $order_id ){
// Get an instance of the `WC_Order` Object
$order = wc_get_order( $order_id );
// Get the order number
$order_number = $order->get_order_number();
// Get the order status name
$status_name = wc_get_order_status_name( $order->get_status() );
// Get the order key
$test_order_key = $order->get_order_key();
if ( $order->has_status('on-hold') || $order->has_status('mockup-requested') || $order->has_status('mockup-sent')|| $order->has_status('mockup-approved')) {
echo 'helllo world';
add_filter( 'the_title', 'woo_title_order_received', 10, 2 );
function woo_title_order_received( $title, $id ) {
if ( function_exists( 'is_order_received_page' ) &&
is_order_received_page() && get_the_ID() === $id ) {
$title = "Mockup request received";
}
return $title;
}
}
}
but I have tried multiple ways to combine the two and without any success.
You can use the following to change "Order received" page title based on order statuses:
add_action( 'the_title', 'change_order_received_page_title_based_on_order_status' );
function change_order_received_page_title_based_on_order_status( $title ){
if ( is_wc_endpoint_url('order-received') && $title === 'Order received' ) {
global $wp;
$targeted_statuses = array('on-hold', 'mockup-requested', 'mockup-sent', 'mockup-approved' );
// Get an instance of the `WC_Order` Object
$order = wc_get_order( absint($wp->query_vars['order-received']) );
if ( is_a( $order, 'WC_Order' ) && in_array( $order->get_status(), $targeted_statuses ) ) {
return __("Mockup request received", "woocommerce");
}
}
return $title;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

need to fix my php code to redirect to different pages after purchase depending con category product in woocommerce

I´m working with this code but it's not working.
How can i fix it to redirect to 3 different pages for each category product (I need to set it for 3 different categories).
add_action( 'template_redirect', 'wc_custom_redirect_after_purchase' );
function wc_custom_redirect_after_purchase($order_product_categories) {
$product_categories1 = jobs;
$product_categories2 = courses;
$product_categories3 = exchange-post;
global $wp;
if ( is_checkout() && ! empty( $wp->query_vars['order-received'] ) ) {
$cat_in_cart = false;
$order_id = isset( $wp->query_vars['order-received'] ) ? intval( $wp->query_vars['order-received'] ) : 0;
$order = new WC_Order( $order_id );
$product_categories = array('jobs', 'courses', 'exchange-post');
foreach( $order->get_items() as $item ){
if( has_term( $product_categories, 'product_cat', $item->get_product_id() ) ) {
$cat_in_cart = true;
break;
}
}
if ( $cat1_in_cart ) {
wp_redirect( 'https://steamroute.com/post-a-job-check-out/');
}
elseif ( $cat2_in_cart ) {
wp_redirect( 'https://steamroute.com/courses-checkout/');
}
elseif ( $cat3_in_cart ) {
wp_redirect( 'https://steamroute.com/exchange-checkout/');
}
exit;
}
}
I think you mean this, don't forget that this code is based on 1 category per product, otherwise you will have to adjust it further
p.s. maybe you should consider this method? instead of a redirect https://markjaquith.wordpress.com/2014/02/19/template_redirect-is-not-for-loading-templates/
function wc_custom_redirect_after_purchase() {
$product_categories1 = 'jobs';
$product_categories2 = 'courses';
$product_categories3 = 'exchange-post';
global $wp;
if ( is_checkout() && ! empty( $wp->query_vars['order-received'] ) ) {
$cat_in_cart = false;
$order_id = isset( $wp->query_vars['order-received'] ) ? intval( $wp->query_vars['order-received'] ) : 0;
$order = new WC_Order( $order_id );
$product_categories = array( $product_categories1, $product_categories2, $product_categories3 );
foreach( $order->get_items() as $item ) {
$item_id = $item->get_product_id();
if( has_term( $product_categories, 'product_cat', $item_id ) ) {
$cat_in_cart = true;
$terms = get_the_terms( $item_id, 'product_cat' );
foreach ( $terms as $term ) {
// Categories by slug
$cat_name = $term->slug;
}
break;
}
}
if ( $cat_in_cart ) {
switch ($cat_name) {
case $product_categories1:
wp_redirect( 'https://steamroute.com/post-a-job-check-out/');
break;
case $product_categories2:
wp_redirect( 'https://steamroute.com/courses-checkout/');
break;
case $product_categories3:
wp_redirect( 'https://steamroute.com/exchange-checkout/');
break;
}
}
}
}
add_action( 'template_redirect', 'wc_custom_redirect_after_purchase' );

Woocommerce change order recieved page title

I am trying to change/add in the title of the "Order Recieved" Woocommerce page.
The below snippet works - I am able to change the pre-existing TEXT with the following code:
add_filter('woocommerce_thankyou_order_received_text', 'woo_change_order_received_text', 10, 2 );
function woo_change_order_received_text( $str, $order ) {
$new_str = $str . ' We have emailed the purchase receipt to you.';
return $new_str;
}
The below snippet does not work. - I am unable to change/add the TITLE and also pass in the username to personalise it. Here is the code and also an image of the output I am trying to achieve....The "You are awesome FIRSTNAME" added in.
<?php
add_filter( 'the_title', 'woo_personalize_order_received_title', 10, 2 );
function woo_personalize_order_received_title( $title, $id ) {
if ( is_order_received_page() && get_the_ID() === $id ) {
global $wp;
// Get the order. Line 9 to 17 are present in order_received() in includes/shortcodes/class-wc-shortcode-checkout.php file
$order_id = apply_filters( 'woocommerce_thankyou_order_id', absint( $wp->query_vars['order-received'] ) );
$order_key = apply_filters( 'woocommerce_thankyou_order_key', empty( $_GET['key'] ) ? '' : wc_clean( $_GET['key'] ) );
if ( $order_id > 0 ) {
$order = wc_get_order( $order_id );
if ( $order->get_order_key() != $order_key ) {
$order = false;
}
}
if ( isset ( $order ) ) {
//$title = sprintf( "You are awesome, %s!", esc_html( $order->billing_first_name ) ); // use this for WooCommerce versions older then v2.7
$title = sprintf( "You are awesome, %s!", esc_html( $order->get_billing_first_name() ) );
}
}
return $title;
}
This should be possible as there are examples on how to do it, such as here...I just can't figure out why the main title wont even appear?
As a workaround I inspected the CSS and changed the text below the header to be a larger size and the font family required.
Then through the below PHP I created the custom text with the customer name in the header.
add_filter('woocommerce_thankyou_order_received_text', 'woo_change_order_received_text', 10, 2 );
function woo_change_order_received_text( $str, $order ) {
$new_str = sprintf( "You are awesome, %s :) - We've recieved your order.", esc_html( $order->get_billing_first_name() ) );
return $new_str;
}
2022 update:
function ps_title_order_received( $title, $id ) {
if ( is_order_received_page() && get_the_ID() === $id ) {
global $wp;
$order_id = apply_filters( 'woocommerce_thankyou_order_id', absint( $wp->query_vars['order-received'] ) );
$order_key = apply_filters( 'woocommerce_thankyou_order_key', empty( $_GET['key'] ) ? '' : wc_clean( $_GET['key'] ) );
if ( $order_id > 0 ) {
$order = wc_get_order( $order_id );
if ( $order->get_order_key() != $order_key ) {
unset( $order );
}
}
if ( isset ( $order ) ) {
$title = sprintf( "Thank you, %s!", esc_html( $order->get_billing_first_name() ) );
}
}
return $title;
}
add_filter( 'the_title', 'ps_title_order_received', 10, 2 );

Categories