Last active
August 3, 2026 11:07
-
-
Save plugin-republic/d3f1a6b6969ce367aba100fad4b84f0c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Snippet: Add a 'Shipping speed' radio field (Standard / Express) to the checkout page, | |
| * inside the order review table immediately below the subtotal row and above the | |
| * shipping/payment method options. | |
| * | |
| * Selecting 'Express' adds a 15% fee based on the cart's current total. | |
| * The field is saved to the order as post meta and shown on the admin order screen. | |
| * | |
| * Usage: add this file as an mu-plugin, or require it from your theme/child-theme | |
| * functions.php, or paste the contents into a plugin such as Code Snippets. | |
| */ | |
| define( 'CSSR_FIELD_KEY', 'shipping_speed' ); | |
| define( 'CSSR_EXPRESS_FEE_PERCENT', 15 ); | |
| /** | |
| * Render the radio field as a row in the order review table, right after the | |
| * cart subtotal row and before shipping/payment methods are shown. | |
| */ | |
| add_action( 'woocommerce_review_order_after_cart_contents', 'cssr_render_shipping_speed_field' ); | |
| function cssr_render_shipping_speed_field() { | |
| $chosen = WC()->session ? WC()->session->get( CSSR_FIELD_KEY, 'standard' ) : 'standard'; | |
| ?> | |
| <tr class="cssr-shipping-speed"> | |
| <th><?php esc_html_e( 'Shipping speed', 'woocommerce' ); ?></th> | |
| <td> | |
| <div id="cssr_shipping_speed_field"> | |
| <?php | |
| woocommerce_form_field( | |
| CSSR_FIELD_KEY, | |
| array( | |
| 'type' => 'radio', | |
| 'class' => array( 'cssr-shipping-speed-field form-row-wide' ), | |
| 'options' => array( | |
| 'standard' => __( 'Standard', 'woocommerce' ), | |
| 'express' => sprintf( | |
| /* translators: %d: express fee percentage */ | |
| __( 'Express (+%d%% of cart total)', 'woocommerce' ), | |
| CSSR_EXPRESS_FEE_PERCENT | |
| ), | |
| ), | |
| 'required' => true, | |
| ), | |
| $chosen | |
| ); | |
| ?> | |
| </div> | |
| </td> | |
| </tr> | |
| <?php | |
| } | |
| /** | |
| * Require a selection before allowing the order to be placed. | |
| */ | |
| add_action( 'woocommerce_checkout_process', 'cssr_validate_shipping_speed_field' ); | |
| function cssr_validate_shipping_speed_field() { | |
| if ( empty( $_POST[ CSSR_FIELD_KEY ] ) ) { | |
| wc_add_notice( __( 'Please choose a shipping speed.', 'woocommerce' ), 'error' ); | |
| } | |
| } | |
| /** | |
| * Persist the selection to the order and session so it survives page reloads | |
| * and is available when the fee is calculated. | |
| */ | |
| add_action( 'woocommerce_checkout_create_order', 'cssr_save_shipping_speed_to_order', 10, 2 ); | |
| function cssr_save_shipping_speed_to_order( $order, $data ) { | |
| if ( ! empty( $_POST[ CSSR_FIELD_KEY ] ) ) { | |
| $value = sanitize_text_field( wp_unslash( $_POST[ CSSR_FIELD_KEY ] ) ); | |
| $order->update_meta_data( '_' . CSSR_FIELD_KEY, $value ); | |
| } | |
| } | |
| /** | |
| * Keep the chosen value in the WC session, updated on every checkout field change, | |
| * so the cart fee recalculates live via AJAX (woocommerce_update_order_review). | |
| */ | |
| add_action( 'woocommerce_checkout_update_order_review', 'cssr_store_shipping_speed_in_session' ); | |
| function cssr_store_shipping_speed_in_session( $post_data ) { | |
| parse_str( $post_data, $data ); | |
| $value = isset( $data[ CSSR_FIELD_KEY ] ) ? sanitize_text_field( wp_unslash( $data[ CSSR_FIELD_KEY ] ) ) : 'standard'; | |
| WC()->session->set( CSSR_FIELD_KEY, $value ); | |
| } | |
| /** | |
| * Add the 15% express fee to the cart when 'Express' is selected. | |
| */ | |
| add_action( 'woocommerce_cart_calculate_fees', 'cssr_add_express_fee' ); | |
| function cssr_add_express_fee( $cart ) { | |
| if ( is_admin() && ! defined( 'DOING_AJAX' ) ) { | |
| return; | |
| } | |
| if ( ! WC()->session ) { | |
| return; | |
| } | |
| $shipping_speed = WC()->session->get( CSSR_FIELD_KEY ); | |
| if ( 'express' !== $shipping_speed ) { | |
| return; | |
| } | |
| $fee = $cart->get_cart_contents_total() * ( CSSR_EXPRESS_FEE_PERCENT / 100 ); | |
| if ( $fee > 0 ) { | |
| $cart->add_fee( __( 'Express shipping fee (15%)', 'woocommerce' ), $fee, true ); | |
| } | |
| } | |
| /** | |
| * Show the chosen shipping speed on the admin order edit screen. | |
| */ | |
| add_action( 'woocommerce_admin_order_data_after_billing_address', 'cssr_display_shipping_speed_in_admin' ); | |
| function cssr_display_shipping_speed_in_admin( $order ) { | |
| $value = $order->get_meta( '_' . CSSR_FIELD_KEY ); | |
| if ( ! $value ) { | |
| return; | |
| } | |
| $label = 'express' === $value ? __( 'Express', 'woocommerce' ) : __( 'Standard', 'woocommerce' ); | |
| echo '<p><strong>' . esc_html__( 'Shipping speed', 'woocommerce' ) . ':</strong> ' . esc_html( $label ) . '</p>'; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment