skip to main content
Menu

WooCommerce: How to swap billing and shipping details around

For some reason in my short experience with Woocommerce, it seems to be massively extensible, yet some things Woocommerce really wants to fight against you in order to acomplish something that a client, and yourself think sound fairly basic. One such example is using the stock Woocommerce checkout and wanting
to swap the order of the billing and shipping details, as a client wants the customer to think first about where their order is going rather than where it will be billed to (it is debatable wether they are right or not, I’m indifferent on either option).

While re-arranging the boxes inside of the template and overriding Woocommerce’s template is relatively straight-forward there is some extra leg work to get the sneaky checkbox working which says,

“Use the same address for billing”

We need to override some Woocommerce templates to output the boxes in the correct order, and then some custom Javascript to get the same experience Woocommerce provides with the checkbox.

This guide was written against and last tested with Woocommerce 3.7.0. Updates to Woocommerce may break this and are provided as-is.

Stage 1: Swap around the fields for billing and checkout

Copy over into your theme the Woocommerce parts checkout/form-checkout.php, checkout/form-billing.php and checkout/form-shipping.php.

Inside of the billing file you will need to add some code to display the “Bill to a different address” box like so:

	<h3 id="bill-to-different-address">
		<label class="woocommerce-form__label woocommerce-form__label-for-checkbox checkbox">
			<input id="bill-to-different-address-checkbox" class="woocommerce-form__input woocommerce-form__input-checkbox input-checkbox" type="checkbox" name="bill_to_different_address" value="1" /> <span><?php esc_html_e( 'Bill to a different address?', 'woocommerce' ); ?></span>
		</label>
	</h3>Code language: HTML, XML (xml)

For shipping file, you can remove similar code which renders the “ship to a different address” box. However, you must instead swap it to silently allow two different addresses otherwise you may end up loosing your shipping addresses!

<input type="hidden" name="ship_to_different_address" value="1" />Code language: HTML, XML (xml)

Finally, in the checkout file you need to swap the order of the two forms to display the other way around.

Stage 2: Add Javascript to make checkout work correctly

The following code ensures the billing details are updated whenever shipping is updated. It should work
with most plugins, but please check yourself as there may be unexepcted issues.

(function($){
	$(document).ready(function() {
		/**
		 * WooCommerce Bill to a Different Address
		 *
		 * @author Invisible Dragon
		 */
		var inputBoxTypes = "input, select, textarea";
		var shippingLength = "shipping_".length;

		// Add in hack to override val function to make it work properly with addons (such as saved addresses)
		var originalVal = $.fn.val;
		$.fn.val = function(){
			var result = originalVal.apply(this,arguments);
			if(arguments.length > 0 && $(this).attr("id") && $(this).attr("id").indexOf("shipping_") === 0) {
				$(this).change(); // OR with custom event $(this).trigger('value-changed');
			}
			return result;
		};

		// For every kind of input on the shipping side of things, try and
		// keep in sync with billing
		$(inputBoxTypes, ".woocommerce-shipping-fields__field-wrapper").on("change keyup update", function () {
			if (!$("#bill-to-different-address-checkbox").prop('checked')) {
				// Update the value on the billing side
				$("#billing_" + $(this).attr("id").substr(shippingLength)).val($(this).val());
			}
		}).trigger('change');
		// We trigger at the end in case of reloaded fields

		$("#bill-to-different-address-checkbox").on("change", function () {
			var isChecked = $(this).prop("checked");
			// Now go through every shipping field
			$(inputBoxTypes, ".woocommerce-shipping-fields__field-wrapper").each(function () {
				var id = $(this).attr("id").substr(shippingLength);
				// And if it has a billing counterpart, we can show/hide/reset the value
				if (isChecked) {
					$("#billing_" + id + "_field").show(300);
				} else {
					$("#billing_" + id + "_field").hide(300);
					// We need to set the value to the shipping value
					$("#billing_" + id).val($(this).val());
				}
			});
		}).trigger('change');

	});
})(jQuery);Code language: JavaScript (javascript)

You will need to enqueue this inside of your theme’s functions.php file.


Post published 28 Sep 2019

Blog

Share:

Other Posts

DOET-Vouchers
Single Use Coupons

22 Jul 2022 Blog Design of Everyday Things

DareMotorsport
Dare Motorsport

19 Jul 2022 Portfolio

GNE
Interface Design for Displays in the Real World

05 May 2022 Blog Design of Everyday Things