Home / eCommerce / WooCommerce Delivery Address Popup – Sync Address in Header & Checkout
Duplicate Snippet

Embed Snippet on Your Site

WooCommerce Delivery Address Popup – Sync Address in Header & Checkout

Enhance your WooCommerce store with an Amazon-style "Deliver to" address popup. Allow customers to select or update their delivery address directly in the header, syncing seamlessly with their cart and checkout fields. This feature works for both logged-in users and guests, saving the address in sessions and cookies for easy re-use.

Key Features:

Show "Deliver to" address in header or anywhere with shortcode

Users can easily update their address via a popup

Syncs with WooCommerce checkout and cart fields

Supports logged-in users and guests (session & cookie support)

⚙️ Usage Instructions
1. ✅ Add the Code
Paste the provided PHP code into your theme's functions.php file or save it as a custom plugin.

2. ✅ Add the Shortcode
Use the shortcode [deliver_to_address] wherever you want the address to appear (e.g., header, sidebar, pages).

Code Preview
php
<?php
/*
 * Use the shortcode [deliver_to_address] wherever you want the address to appear (e.g., header, sidebar, pages).
 * Author: Muhammad Mubeen A (wp_expert28)
 * 
*/ 
// Shortcode to display "Deliver to:" widget with address edit popup 
add_shortcode('deliver_to_address', function () {
    if (!function_exists('WC') || !WC()->session) return ''; // Prevent fatal error in admin/editor
    $data = WC()->session->get('checkout_data', []);
    $street = $data['billing_address_1'] ?? '';
    $city   = $data['billing_city'] ?? '';
    $zip    = $data['billing_postcode'] ?? '';
    $parts = array_filter([$street, $zip, $city]);
    $address = $parts ? implode(', ', $parts) : 'Enter Address:';
    ob_start();
    ?>
    <div id="deliver-to-wrapper">
        <strong>Deliver to:</strong> <span id="deliver-to-text"><?= esc_html($address) ?></span>
        <a href="#" id="change-address-link" style="margin-left: 5px;"><i class="fa fa-edit"></i> Edit</a>
    </div>
    <!-- Popup Modal -->
    <div id="address-popup" style="display:none; position:fixed; top:20%; left:50%; transform:translateX(-50%);
        background:#fff; padding:20px; border-radius:10px;border:1px solid #ccc; z-index:9999; width:280px; box-shadow:0 0 10px rgba(0,0,0,0.3);">
        <h4 style="margin-bottom:8px;text-align:center;">Edit Delivery Address</h4>
        <input type="text" id="edit_street" placeholder="Street Address" style="width:100%; margin-bottom:10px;" value="<?= esc_attr($street) ?>" />
        <input type="text" id="edit_zip" placeholder="Postcode" style="width:100%; margin-bottom:10px;" value="<?= esc_attr($zip) ?>" />
        <input type="text" id="edit_city" placeholder="City" style="width:100%; margin-bottom:10px;" value="<?= esc_attr($city) ?>" />
		<div class="address-actions" >
			<button id="save-address" style="margin-right:10px;">Save</button>
			<button id="close-popup">Cancel</button>
		</div>
    </div>
    <script>
    document.addEventListener('DOMContentLoaded', function () {
        const popup = document.getElementById('address-popup');
        const changeBtn = document.getElementById('change-address-link');
        const closeBtn = document.getElementById('close-popup');
        const saveBtn = document.getElementById('save-address');
        const originalBtnText = saveBtn.textContent;
        changeBtn.addEventListener('click', function(e) {
            e.preventDefault();
            popup.style.display = 'block';
        });
        closeBtn.addEventListener('click', function() {
            popup.style.display = 'none';
        });
        saveBtn.addEventListener('click', function() {
            const street = document.getElementById('edit_street').value.trim();
            const zip = document.getElementById('edit_zip').value.trim();
            const city = document.getElementById('edit_city').value.trim();
            if (!street && !zip && !city) {
                alert('Please fill at least one field.');
                return;
            }
            saveBtn.disabled = true;
            saveBtn.textContent = 'Saving...';
            fetch("<?= admin_url('admin-ajax.php') ?>", {
                method: "POST",
                headers: { "Content-Type": "application/x-www-form-urlencoded" },
                body: new URLSearchParams({
                    action: "save_custom_checkout_address",
                    street, zip, city
                })
            })
            .then(res => res.json())
            .then(data => {
                saveBtn.disabled = false;
                saveBtn.textContent = originalBtnText;
                if (data.success) {
                    document.getElementById('deliver-to-text').textContent = data.data.address;
                    popup.style.display = 'none';
                    if (typeof jQuery !== 'undefined') {
                        jQuery('body').trigger('update_checkout');
                    }
                } else {
                    alert('Error updating address');
                }
            })
            .catch(() => {
                saveBtn.disabled = false;
                saveBtn.textContent = originalBtnText;
                alert('AJAX error occurred');
            });
        });
    });
    </script>
	<style>
		.woocommerce-checkout #change-address-link{
			display:none;
		}
	</style>
    <?php
    return ob_get_clean();
});
// AJAX handler to save popup address to WooCommerce session
add_action('wp_ajax_save_custom_checkout_address', 'save_custom_checkout_address');
add_action('wp_ajax_nopriv_save_custom_checkout_address', 'save_custom_checkout_address');
function save_custom_checkout_address() {
    if (!function_exists('WC') || !WC()->session) wp_send_json_error();
    $street = sanitize_text_field($_POST['street'] ?? '');
    $zip    = sanitize_text_field($_POST['zip'] ?? '');
    $city   = sanitize_text_field($_POST['city'] ?? '');
    $output = [
        'billing_address_1' => $street,
        'billing_postcode'  => $zip,
        'billing_city'      => $city,
    ];
    WC()->session->set('checkout_data', $output);
    $address = implode(', ', array_filter([$street, $zip, $city]));
    wp_send_json_success(['address' => $address]);
}
// Save posted checkout data into session on order review update (important for WooCommerce AJAX)
add_action('woocommerce_checkout_update_order_review', 'mb_save_checkout_values', 9999);
function mb_save_checkout_values($posted_data) {
    parse_str($posted_data, $output);
    WC()->session->set('checkout_data', $output);
}
// Fill checkout fields from session data (priority over default values)
add_filter('woocommerce_checkout_get_value', 'mb_get_saved_checkout', 9999, 2);
function mb_get_saved_checkout($value, $index) {
    $data = WC()->session->get('checkout_data');
    if (!$data || empty($data[$index])) return $value;
    return is_bool($data[$index]) ? (int) $data[$index] : $data[$index];
}
// Optional: Keep ship_to_different_address checkbox state synced
add_filter('woocommerce_ship_to_different_address_checked', 'mb_get_saved_ship_to_different');
function mb_get_saved_ship_to_different($checked) {
    $data = WC()->session->get('checkout_data');
    if (!$data || empty($data['ship_to_different_address'])) return $checked;
    return true;
} 

Comments

Add a Comment